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 shutdown of the timer service, we use a local
20 * event which the timer thread listens to (and stopVirtTimer()
23 static HANDLE hStopEvent = INVALID_HANDLE_VALUE;
24 static HANDLE tickThread = INVALID_HANDLE_VALUE;
26 static TickProc tickProc = NULL;
29 * Ticking is done by a separate thread which periodically
30 * wakes up to handle a tick.
32 * This is the portable way of providing a timer service under
33 * Win32; features like waitable timers or timer queues are only
34 * supported by a subset of the Win32 platforms (notably not
41 TimerProc(PVOID param)
46 /* interpret a < 0 timeout period as 'instantaneous' */
50 waitRes = WaitForSingleObject(hStopEvent, ms);
54 /* event has become signalled */
56 CloseHandle(hStopEvent);
57 hStopEvent = INVALID_HANDLE_VALUE;
64 DWORD dw = GetLastError();
65 fprintf(stderr, "TimerProc: wait failed -- error code: %lu\n", dw); fflush(stderr);
69 fprintf(stderr, "TimerProc: unexpected result %lu\n", waitRes); fflush(stderr);
78 startTicker(nat ms, TickProc handle_tick)
81 /* 'hStopEvent' is a manual-reset event that's signalled upon
82 * shutdown of timer service (=> timer thread.)
84 hStopEvent = CreateEvent ( NULL,
88 if (hStopEvent == INVALID_HANDLE_VALUE) {
91 tickProc = handle_tick;
92 tickThread = (HANDLE)(long)_beginthreadex( NULL,
99 if (tickThread == 0) {
100 sysErrorBelch("_beginthreadex");
101 stg_exit(EXIT_FAILURE);
108 // We must wait for the ticker thread to terminate, since if we
109 // are in a DLL that is about to be unloaded, the ticker thread
110 // cannot be allowed to return to a missing DLL.
112 if (hStopEvent != INVALID_HANDLE_VALUE &&
113 tickThread != INVALID_HANDLE_VALUE) {
115 SetEvent(hStopEvent);
117 WaitForSingleObject(tickThread, 20);
118 if (!GetExitCodeThread(tickThread, &exitCode)) {
121 if (exitCode != STILL_ACTIVE) {
122 tickThread = INVALID_HANDLE_VALUE;
123 if ( hStopEvent != INVALID_HANDLE_VALUE ) {
124 CloseHandle(hStopEvent);
125 hStopEvent = INVALID_HANDLE_VALUE;
129 TerminateThread(tickThread, 0);