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 debugBelch("tick: pause");
57 waitRes = WaitForSingleObject(hStopEvent, INFINITE);
58 debugBelch("tick: wakeup");
61 /* event has become signalled */
63 CloseHandle(hStopEvent);
64 hStopEvent = INVALID_HANDLE_VALUE;
70 /* event has become signalled */
71 ResetEvent(hStopEvent);
78 sysErrorBelch("TimerProc: WaitForSingleObject failed");
81 errorBelch("TimerProc: unexpected result %lu\n", waitRes);
90 initTicker (nat ms, TickProc handle_tick)
93 /* 'hStopEvent' is a manual-reset event that's signalled upon
94 * shutdown of timer service (=> timer thread.)
96 hStopEvent = CreateEvent ( NULL,
100 if (hStopEvent == INVALID_HANDLE_VALUE) {
101 sysErrorBelch("CreateEvent");
102 stg_exit(EXIT_FAILURE);
104 tickProc = handle_tick;
105 ticker_state = TickerPause;
106 tickThread = (HANDLE)(long)_beginthreadex( NULL,
113 if (tickThread == 0) {
114 sysErrorBelch("_beginthreadex");
115 stg_exit(EXIT_FAILURE);
122 ticker_state = TickerGo;
123 SetEvent(hStopEvent);
129 ticker_state = TickerPause;
130 SetEvent(hStopEvent);
136 // We must wait for the ticker thread to terminate, since if we
137 // are in a DLL that is about to be unloaded, the ticker thread
138 // cannot be allowed to return to a missing DLL.
140 if (hStopEvent != INVALID_HANDLE_VALUE &&
141 tickThread != INVALID_HANDLE_VALUE) {
143 ticker_state = TickerExit;
144 SetEvent(hStopEvent);
146 WaitForSingleObject(tickThread, 20);
147 if (!GetExitCodeThread(tickThread, &exitCode)) {
150 if (exitCode != STILL_ACTIVE) {
151 tickThread = INVALID_HANDLE_VALUE;
152 if ( hStopEvent != INVALID_HANDLE_VALUE ) {
153 CloseHandle(hStopEvent);
154 hStopEvent = INVALID_HANDLE_VALUE;
158 TerminateThread(tickThread, 0);