Index: src/pkg/runtime/windows/thread.c |
=================================================================== |
--- a/src/pkg/runtime/windows/thread.c |
+++ b/src/pkg/runtime/windows/thread.c |
@@ -10,32 +10,48 @@ |
#pragma dynimport runtime·CloseHandle CloseHandle "kernel32.dll" |
#pragma dynimport runtime·CreateEvent CreateEventA "kernel32.dll" |
#pragma dynimport runtime·CreateThread CreateThread "kernel32.dll" |
+#pragma dynimport runtime·CreateWaitableTimer CreateWaitableTimerA "kernel32.dll" |
+#pragma dynimport runtime·DuplicateHandle DuplicateHandle "kernel32.dll" |
#pragma dynimport runtime·ExitProcess ExitProcess "kernel32.dll" |
#pragma dynimport runtime·FreeEnvironmentStringsW FreeEnvironmentStringsW "kernel32.dll" |
#pragma dynimport runtime·GetEnvironmentStringsW GetEnvironmentStringsW "kernel32.dll" |
#pragma dynimport runtime·GetProcAddress GetProcAddress "kernel32.dll" |
#pragma dynimport runtime·GetStdHandle GetStdHandle "kernel32.dll" |
+#pragma dynimport runtime·GetThreadContext GetThreadContext "kernel32.dll" |
#pragma dynimport runtime·LoadLibraryEx LoadLibraryExA "kernel32.dll" |
#pragma dynimport runtime·QueryPerformanceCounter QueryPerformanceCounter "kernel32.dll" |
#pragma dynimport runtime·QueryPerformanceFrequency QueryPerformanceFrequency "kernel32.dll" |
+#pragma dynimport runtime·ResumeThread ResumeThread "kernel32.dll" |
#pragma dynimport runtime·SetConsoleCtrlHandler SetConsoleCtrlHandler "kernel32.dll" |
#pragma dynimport runtime·SetEvent SetEvent "kernel32.dll" |
+#pragma dynimport runtime·SetThreadPriority SetThreadPriority "kernel32.dll" |
+#pragma dynimport runtime·SetWaitableTimer SetWaitableTimer "kernel32.dll" |
+#pragma dynimport runtime·SuspendThread SuspendThread "kernel32.dll" |
+#pragma dynimport runtime·timeBeginPeriod timeBeginPeriod "winmm.dll" |
#pragma dynimport runtime·WaitForSingleObject WaitForSingleObject "kernel32.dll" |
#pragma dynimport runtime·WriteFile WriteFile "kernel32.dll" |
extern void *runtime·CloseHandle; |
extern void *runtime·CreateEvent; |
extern void *runtime·CreateThread; |
+extern void *runtime·CreateWaitableTimer; |
+extern void *runtime·DuplicateHandle; |
extern void *runtime·ExitProcess; |
extern void *runtime·FreeEnvironmentStringsW; |
extern void *runtime·GetEnvironmentStringsW; |
extern void *runtime·GetProcAddress; |
extern void *runtime·GetStdHandle; |
+extern void *runtime·GetThreadContext; |
extern void *runtime·LoadLibraryEx; |
extern void *runtime·QueryPerformanceCounter; |
extern void *runtime·QueryPerformanceFrequency; |
+extern void *runtime·ResumeThread; |
extern void *runtime·SetConsoleCtrlHandler; |
extern void *runtime·SetEvent; |
+extern void *runtime·SetThreadPriority; |
+extern void *runtime·SetWaitableTimer; |
+extern void *runtime·SuspendThread; |
+extern void *runtime·timeBeginPeriod; |
extern void *runtime·WaitForSingleObject; |
extern void *runtime·WriteFile; |
@@ -44,8 +60,13 @@ |
void |
runtime·osinit(void) |
{ |
+ // -1 = current process, -2 = current thread |
+ runtime·stdcall(runtime·DuplicateHandle, 7, |
+ (uintptr)-1, (uintptr)-2, (uintptr)-1, &m->thread, |
+ (uintptr)0, (uintptr)0, (uintptr)DUPLICATE_SAME_ACCESS); |
runtime·stdcall(runtime·QueryPerformanceFrequency, 1, &timerfreq); |
runtime·stdcall(runtime·SetConsoleCtrlHandler, 2, runtime·ctrlhandler, (uintptr)1); |
+ runtime·stdcall(runtime·timeBeginPeriod, 1, (uintptr)1); |
} |
void |
@@ -211,11 +232,13 @@ |
USED(g); // assuming g = m->g0 |
USED(fn); // assuming fn = mstart |
- thandle = runtime·stdcall(runtime·CreateThread, 6, (uintptr)0, (uintptr)0, runtime·tstart_stdcall, m, (uintptr)0, (uintptr)0); |
- if(thandle == 0) { |
+ thandle = runtime·stdcall(runtime·CreateThread, 6, |
+ nil, nil, runtime·tstart_stdcall, m, nil, nil); |
+ if(thandle == nil) { |
runtime·printf("runtime: failed to create new OS thread (have %d already; errno=%d)\n", runtime·mcount(), runtime·getlasterror()); |
runtime·throw("runtime.newosproc"); |
} |
+ runtime·atomicstorep(&m->thread, thandle); |
} |
// Called to initialize a new m (including the bootstrap m). |
@@ -324,6 +347,89 @@ |
return 0; |
} |
+extern void runtime·dosigprof(Context *r, G *gp); |
+extern void runtime·profileloop(void); |
+static void *profiletimer; |
+ |
+static void |
+profilem(M *mp) |
+{ |
+ extern M runtime·m0; |
+ extern uint32 runtime·tls0[]; |
+ byte rbuf[sizeof(Context)+15]; |
+ Context *r; |
+ void *tls; |
+ G *gp; |
+ |
+ tls = mp->tls; |
+ if(mp == &runtime·m0) |
+ tls = runtime·tls0; |
+ gp = *(G**)tls; |
+ |
+ if(gp != nil && gp != mp->g0 && gp->status != Gsyscall) { |
+ // align Context to 16 bytes |
+ r = (Context*)((uintptr)(&rbuf[15]) & ~15); |
+ r->ContextFlags = CONTEXT_CONTROL; |
+ runtime·stdcall(runtime·GetThreadContext, 2, mp->thread, r); |
+ runtime·dosigprof(r, gp); |
+ } |
+} |
+ |
+void |
+runtime·profileloop1(void) |
+{ |
+ M *mp, *allm; |
+ void *thread; |
+ |
+ runtime·stdcall(runtime·SetThreadPriority, 2, |
+ (uintptr)-2, (uintptr)THREAD_PRIORITY_HIGHEST); |
+ |
+ for(;;) { |
+ runtime·stdcall(runtime·WaitForSingleObject, 2, profiletimer, (uintptr)-1); |
+ allm = runtime·atomicloadp(&runtime·allm); |
+ for(mp = allm; mp != nil; mp = mp->alllink) { |
+ thread = runtime·atomicloadp(&mp->thread); |
brainman
2011/09/16 02:56:42
Why do you prefer that to starting new thread susp
|
+ if(thread == nil) |
+ continue; |
+ runtime·stdcall(runtime·SuspendThread, 1, thread); |
+ if(mp->profilehz != 0) |
+ profilem(mp); |
+ runtime·stdcall(runtime·ResumeThread, 1, thread); |
+ } |
+ } |
+} |
+ |
+void |
+runtime·resetcpuprofiler(int32 hz) |
+{ |
+ static Lock lock; |
+ void *timer, *thread; |
+ int32 ms; |
+ int64 due; |
+ |
+ runtime·lock(&lock); |
+ if(profiletimer == nil) { |
+ timer = runtime·stdcall(runtime·CreateWaitableTimer, 3, nil, nil, nil); |
+ runtime·atomicstorep(&profiletimer, timer); |
+ thread = runtime·stdcall(runtime·CreateThread, 6, |
+ nil, nil, runtime·profileloop, nil, nil, nil); |
+ runtime·stdcall(runtime·CloseHandle, 1, thread); |
+ } |
+ runtime·unlock(&lock); |
+ |
+ ms = 0; |
+ due = 1LL<<63; |
+ if(hz > 0) { |
+ ms = 1000 / hz; |
+ if(ms == 0) |
+ ms = 1; |
+ due = ms * -10000; |
+ } |
+ runtime·stdcall(runtime·SetWaitableTimer, 6, |
+ profiletimer, &due, (uintptr)ms, nil, nil, nil); |
+ runtime·atomicstore((uint32*)&m->profilehz, hz); |
+} |
+ |
void |
os·sigpipe(void) |
{ |