12 * Provide a timer service for the RTS, periodically
13 * notifying it that a number of 'ticks' has passed.
17 /* To signal pause or shutdown of the timer service, we use a local
18 * event which the timer thread listens to.
20 static HANDLE hStopEvent = INVALID_HANDLE_VALUE;
21 static HANDLE tickThread = INVALID_HANDLE_VALUE;
23 static TickProc tickProc = NULL;
25 static enum { TickerGo, TickerPause, TickerExit } ticker_state;
28 * Ticking is done by a separate thread which periodically
29 * wakes up to handle a tick.
31 * This is the portable way of providing a timer service under
32 * Win32; features like waitable timers or timer queues are only
33 * supported by a subset of the Win32 platforms (notably not
40 TimerProc(PVOID param)
45 /* interpret a < 0 timeout period as 'instantaneous' */
49 switch (ticker_state) {
51 waitRes = WaitForSingleObject(hStopEvent, ms);
54 waitRes = WaitForSingleObject(hStopEvent, INFINITE);
57 /* event has become signalled */
59 CloseHandle(hStopEvent);
60 hStopEvent = INVALID_HANDLE_VALUE;
66 /* event has become signalled */
67 ResetEvent(hStopEvent);
74 sysErrorBelch("TimerProc: WaitForSingleObject failed");
77 errorBelch("TimerProc: unexpected result %lu\n", waitRes);
86 initTicker (nat ms, TickProc handle_tick)
89 /* 'hStopEvent' is a manual-reset event that's signalled upon
90 * shutdown of timer service (=> timer thread.)
92 hStopEvent = CreateEvent ( NULL,
96 if (hStopEvent == INVALID_HANDLE_VALUE) {
97 sysErrorBelch("CreateEvent");
98 stg_exit(EXIT_FAILURE);
100 tickProc = handle_tick;
101 ticker_state = TickerPause;
102 tickThread = (HANDLE)(long)_beginthreadex( NULL,
109 if (tickThread == 0) {
110 sysErrorBelch("_beginthreadex");
111 stg_exit(EXIT_FAILURE);
118 ticker_state = TickerGo;
119 SetEvent(hStopEvent);
125 ticker_state = TickerPause;
126 SetEvent(hStopEvent);
132 // We must wait for the ticker thread to terminate, since if we
133 // are in a DLL that is about to be unloaded, the ticker thread
134 // cannot be allowed to return to a missing DLL.
136 if (hStopEvent != INVALID_HANDLE_VALUE &&
137 tickThread != INVALID_HANDLE_VALUE) {
139 ticker_state = TickerExit;
140 SetEvent(hStopEvent);
142 WaitForSingleObject(tickThread, 20);
143 if (!GetExitCodeThread(tickThread, &exitCode)) {
146 if (exitCode != STILL_ACTIVE) {
147 tickThread = INVALID_HANDLE_VALUE;
148 if ( hStopEvent != INVALID_HANDLE_VALUE ) {
149 CloseHandle(hStopEvent);
150 hStopEvent = INVALID_HANDLE_VALUE;
154 TerminateThread(tickThread, 0);