diff --git a/windows/GNUmakeinc.mk b/windows/GNUmakeinc.mk index fe40521c..c3723f7c 100644 --- a/windows/GNUmakeinc.mk +++ b/windows/GNUmakeinc.mk @@ -47,6 +47,5 @@ endif ifeq ($(PROFILE),1) osCFILES += windows/profiler.c - osCFLAGS += -finstrument-functions - osLDFLAGS += -finstrument-functions + osCFLAGS += -DLIBUIPROFILING endif diff --git a/windows/init.c b/windows/init.c index 38d10994..e2ca3232 100644 --- a/windows/init.c +++ b/windows/init.c @@ -80,6 +80,16 @@ const char *uiInit(uiInitOptions *o) HCURSOR hDefaultCursor; NONCLIENTMETRICSW ncm; +#ifdef LIBUIPROFILING + extern void initprofiler(HANDLE); + HANDLE real; + if (DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), + GetCurrentProcess(), &real, + 0, FALSE, DUPLICATE_SAME_ACCESS) == 0) + return loadLastError("getting the current thread's handle for initializing the profiler"); + initprofiler(real); +#endif + options = *o; if (initAlloc() == 0) diff --git a/windows/profiler.c b/windows/profiler.c index 9573de20..7a0e01fc 100644 --- a/windows/profiler.c +++ b/windows/profiler.c @@ -3,33 +3,41 @@ static FILE *fprof = NULL; -__attribute__((no_instrument_function)) static void init(void) +static DWORD WINAPI profilerThread(LPVOID th) +{ + HANDLE thread = (HANDLE) th; + LARGE_INTEGER counter; + CONTEXT ctxt; + + // TODO check for errors + if (SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL) == 0) + complain("error setting thread priority in profilerThread()"); + for (;;) { + if (SuspendThread(thread) == (DWORD) (-1)) + complain("error suspending thread in profilerThread()"); + QueryPerformanceCounter(&counter); + ZeroMemory(&ctxt, sizeof (CONTEXT)); + ctxt.ContextFlags = CONTEXT_CONTROL; + if (GetThreadContext(thread, &ctxt) == 0) + complain("error getting thread context in profilerThread()"); + fprintf(fprof, "%I64X %I64d\n", + (DWORD64) (ctxt.Eip), + counter.QuadPart); + fflush(fprof); + if (ResumeThread(thread) == (DWORD) (-1)) + complain("error resuming thread in profilerThread()"); + Sleep(100); + } + return 0; +} + +void initprofiler(HANDLE thread) { - if (fprof != NULL) - return; fprof = fopen("profiler.out", "w"); if (fprof == NULL) { fprintf(stderr, "error opening profiler output file\n"); abort(); } -} - -__attribute__((no_instrument_function)) void __cyg_profile_func_enter(void *this_fn, void *call_site) -{ - LARGE_INTEGER counter; - - init(); - QueryPerformanceCounter(&counter); - fprintf(fprof, "enter %p %I64d\n", this_fn, counter.QuadPart); - fflush(fprof); -} - -__attribute__((no_instrument_function)) void __cyg_profile_func_exit(void *this_fn, void *call_site) -{ - LARGE_INTEGER counter; - - init(); - QueryPerformanceCounter(&counter); - fprintf(fprof, "leave %p %I64d\n", this_fn, counter.QuadPart); - fflush(fprof); + if (CreateThread(NULL, 0, profilerThread, thread, 0, NULL) == NULL) + complain("error creating profiler thread"); }