X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=rts%2Fwin32%2FTicker.c;h=599604e1c2cb68017e00dc9e72f43719161381f5;hb=c004ec62b41aa2137b5b5e298ca562609b0de92e;hp=9fa40ebe52abf6c42db82a5e96367ccf85d56f05;hpb=610de7d17e09318272b7516bd9b97e8b2cbd170c;p=ghc-hetmet.git diff --git a/rts/win32/Ticker.c b/rts/win32/Ticker.c index 9fa40eb..599604e 100644 --- a/rts/win32/Ticker.c +++ b/rts/win32/Ticker.c @@ -16,15 +16,16 @@ * */ -/* To signal shutdown of the timer service, we use a local - * event which the timer thread listens to (and stopVirtTimer() - * signals.) +/* To signal pause or shutdown of the timer service, we use a local + * event which the timer thread listens to. */ static HANDLE hStopEvent = INVALID_HANDLE_VALUE; static HANDLE tickThread = INVALID_HANDLE_VALUE; static TickProc tickProc = NULL; +static enum { TickerGo, TickerPause, TickerExit } ticker_state; + /* * Ticking is done by a separate thread which periodically * wakes up to handle a tick. @@ -44,37 +45,47 @@ TimerProc(PVOID param) DWORD waitRes; /* interpret a < 0 timeout period as 'instantaneous' */ - if (ms < 0) ms = 0; + if (ms < 0) ms = 0; while (1) { - waitRes = WaitForSingleObject(hStopEvent, ms); - - switch (waitRes) { - case WAIT_OBJECT_0: - /* event has become signalled */ - tickProc = NULL; - CloseHandle(hStopEvent); - return 0; - case WAIT_TIMEOUT: - /* tick */ - tickProc(0); - break; - case WAIT_FAILED: { - DWORD dw = GetLastError(); - fprintf(stderr, "TimerProc: wait failed -- error code: %lu\n", dw); fflush(stderr); - break; - } - default: - fprintf(stderr, "TimerProc: unexpected result %lu\n", waitRes); fflush(stderr); - break; - } + switch (ticker_state) { + case TickerGo: + waitRes = WaitForSingleObject(hStopEvent, ms); + break; + case TickerPause: + waitRes = WaitForSingleObject(hStopEvent, INFINITE); + break; + case TickerExit: + /* event has become signalled */ + tickProc = NULL; + CloseHandle(hStopEvent); + hStopEvent = INVALID_HANDLE_VALUE; + return 0; + } + + switch (waitRes) { + case WAIT_OBJECT_0: + /* event has become signalled */ + ResetEvent(hStopEvent); + continue; + case WAIT_TIMEOUT: + /* tick */ + tickProc(0); + break; + case WAIT_FAILED: + sysErrorBelch("TimerProc: WaitForSingleObject failed"); + break; + default: + errorBelch("TimerProc: unexpected result %lu\n", waitRes); + break; + } } return 0; } -int -startTicker(nat ms, TickProc handle_tick) +void +initTicker (nat ms, TickProc handle_tick) { unsigned threadId; /* 'hStopEvent' is a manual-reset event that's signalled upon @@ -85,21 +96,41 @@ startTicker(nat ms, TickProc handle_tick) FALSE, NULL); if (hStopEvent == INVALID_HANDLE_VALUE) { - return 0; + sysErrorBelch("CreateEvent"); + stg_exit(EXIT_FAILURE); } tickProc = handle_tick; + ticker_state = TickerPause; tickThread = (HANDLE)(long)_beginthreadex( NULL, 0, TimerProc, (LPVOID)ms, 0, &threadId); - return (tickThread != 0); + + if (tickThread == 0) { + sysErrorBelch("_beginthreadex"); + stg_exit(EXIT_FAILURE); + } } -int +void +startTicker(void) +{ + ticker_state = TickerGo; + SetEvent(hStopEvent); +} + +void stopTicker(void) { + ticker_state = TickerPause; + SetEvent(hStopEvent); +} + +void +exitTicker(void) +{ // We must wait for the ticker thread to terminate, since if we // are in a DLL that is about to be unloaded, the ticker thread // cannot be allowed to return to a missing DLL. @@ -107,6 +138,7 @@ stopTicker(void) if (hStopEvent != INVALID_HANDLE_VALUE && tickThread != INVALID_HANDLE_VALUE) { DWORD exitCode; + ticker_state = TickerExit; SetEvent(hStopEvent); while (1) { WaitForSingleObject(tickThread, 20); @@ -115,11 +147,13 @@ stopTicker(void) } if (exitCode != STILL_ACTIVE) { tickThread = INVALID_HANDLE_VALUE; - CloseHandle(hStopEvent); + if ( hStopEvent != INVALID_HANDLE_VALUE ) { + CloseHandle(hStopEvent); + hStopEvent = INVALID_HANDLE_VALUE; + } return 0; } TerminateThread(tickThread, 0); } } - return 0; }