11 #include "OSThreads.h"
14 * Provide a timer service for the RTS, periodically
15 * notifying it that a number of 'ticks' has passed.
19 /* To signal pause or shutdown of the timer service, we use a local
20 * event which the timer thread listens to.
22 static HANDLE hStopEvent = INVALID_HANDLE_VALUE;
23 static HANDLE tickThread = INVALID_HANDLE_VALUE;
25 static TickProc tickProc = NULL;
27 static enum { TickerGo, TickerPause, TickerExit } ticker_state;
30 * Ticking is done by a separate thread which periodically
31 * wakes up to handle a tick.
33 * This is the portable way of providing a timer service under
34 * Win32; features like waitable timers or timer queues are only
35 * supported by a subset of the Win32 platforms (notably not
42 TimerProc(PVOID param)
47 /* interpret a < 0 timeout period as 'instantaneous' */
51 switch (ticker_state) {
53 waitRes = WaitForSingleObject(hStopEvent, ms);
56 waitRes = WaitForSingleObject(hStopEvent, INFINITE);
59 /* event has become signalled */
61 CloseHandle(hStopEvent);
62 hStopEvent = INVALID_HANDLE_VALUE;
68 /* event has become signalled */
69 ResetEvent(hStopEvent);
76 sysErrorBelch("TimerProc: WaitForSingleObject failed");
79 errorBelch("TimerProc: unexpected result %lu\n", waitRes);
88 initTicker (nat ms, TickProc handle_tick)
91 /* 'hStopEvent' is a manual-reset event that's signalled upon
92 * shutdown of timer service (=> timer thread.)
94 hStopEvent = CreateEvent ( NULL,
98 if (hStopEvent == INVALID_HANDLE_VALUE) {
99 sysErrorBelch("CreateEvent");
100 stg_exit(EXIT_FAILURE);
102 tickProc = handle_tick;
103 ticker_state = TickerPause;
104 tickThread = (HANDLE)(long)_beginthreadex( NULL,
111 if (tickThread == 0) {
112 sysErrorBelch("_beginthreadex");
113 stg_exit(EXIT_FAILURE);
120 ticker_state = TickerGo;
121 SetEvent(hStopEvent);
127 ticker_state = TickerPause;
128 SetEvent(hStopEvent);
134 // We must wait for the ticker thread to terminate, since if we
135 // are in a DLL that is about to be unloaded, the ticker thread
136 // cannot be allowed to return to a missing DLL.
138 if (hStopEvent != INVALID_HANDLE_VALUE &&
139 tickThread != INVALID_HANDLE_VALUE) {
141 ticker_state = TickerExit;
142 SetEvent(hStopEvent);
144 WaitForSingleObject(tickThread, 20);
145 if (!GetExitCodeThread(tickThread, &exitCode)) {
148 if (exitCode != STILL_ACTIVE) {
149 tickThread = INVALID_HANDLE_VALUE;
150 if ( hStopEvent != INVALID_HANDLE_VALUE ) {
151 CloseHandle(hStopEvent);
152 hStopEvent = INVALID_HANDLE_VALUE;
156 TerminateThread(tickThread, 0);