diff options
author | Kevin B Kenny <kennykb@acm.org> | 2002-10-09 23:57:25 (GMT) |
---|---|---|
committer | Kevin B Kenny <kennykb@acm.org> | 2002-10-09 23:57:25 (GMT) |
commit | 3cb21be3557aec892643f059671997558259e741 (patch) | |
tree | bc1983e9d14ead261e9708d234d747f8edf23409 /win/tclWinTime.c | |
parent | 16284e7d81c8d903edecbbaa014ae84589140150 (diff) | |
download | tcl-3cb21be3557aec892643f059671997558259e741.zip tcl-3cb21be3557aec892643f059671997558259e741.tar.gz tcl-3cb21be3557aec892643f059671997558259e741.tar.bz2 |
* win/tclWinTime.c: Added code to set an exit handler that
terminates the thread that calibrates the performance counter, so
that the thread won't outlive unloading the Tcl DLL. [Tcl bug
620735].
Diffstat (limited to 'win/tclWinTime.c')
-rw-r--r-- | win/tclWinTime.c | 68 |
1 files changed, 63 insertions, 5 deletions
diff --git a/win/tclWinTime.c b/win/tclWinTime.c index d0aa9ec..87d3c4e 100644 --- a/win/tclWinTime.c +++ b/win/tclWinTime.c @@ -9,7 +9,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclWinTime.c,v 1.10 2002/04/01 20:44:36 kennykb Exp $ + * RCS: @(#) $Id: tclWinTime.c,v 1.11 2002/10/09 23:57:25 kennykb Exp $ */ #include "tclWinInt.h" @@ -65,6 +65,10 @@ typedef struct TimeInfo { * trigger the requesting thread * when the clock calibration procedure * is initialized for the first time */ + HANDLE exitEvent; /* Event to signal out of an exit handler + * to tell the calibration loop to + * terminate */ + /* * The following values are used for calculating virtual time. @@ -95,7 +99,18 @@ typedef struct TimeInfo { } TimeInfo; static TimeInfo timeInfo = { - NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0 + { NULL }, + 0, + 0, + (HANDLE) NULL, + (HANDLE) NULL, + (HANDLE) NULL, + 0, + 0, + 0, + 0, + 0, + 0 }; CONST static FILETIME posixEpoch = { 0xD53E8000, 0x019DB1DE }; @@ -105,9 +120,8 @@ CONST static FILETIME posixEpoch = { 0xD53E8000, 0x019DB1DE }; */ static struct tm * ComputeGMT _ANSI_ARGS_((const time_t *tp)); - +static void StopCalibration _ANSI_ARGS_(( ClientData )); static DWORD WINAPI CalibrationThread _ANSI_ARGS_(( LPVOID arg )); - static void UpdateTimeEachSecond _ANSI_ARGS_(( void )); /* @@ -288,6 +302,7 @@ Tcl_GetTime(timePtr) DWORD id; InitializeCriticalSection( &timeInfo.cs ); timeInfo.readyEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); + timeInfo.exitEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); timeInfo.calibrationThread = CreateThread( NULL, 8192, CalibrationThread, @@ -296,8 +311,16 @@ Tcl_GetTime(timePtr) &id ); SetThreadPriority( timeInfo.calibrationThread, THREAD_PRIORITY_HIGHEST ); + + /* + * Wait for the thread just launched to start running, + * and create an exit handler that kills it so that it + * doesn't outlive unloading tclXX.dll + */ + WaitForSingleObject( timeInfo.readyEvent, INFINITE ); CloseHandle( timeInfo.readyEvent ); + Tcl_CreateExitHandler( StopCalibration, (ClientData) NULL ); } timeInfo.initialized = TRUE; } @@ -356,6 +379,34 @@ Tcl_GetTime(timePtr) /* *---------------------------------------------------------------------- * + * StopCalibration -- + * + * Turns off the calibration thread in preparation for exiting the + * process. + * + * Results: + * None. + * + * Side effects: + * Sets the 'exitEvent' event in the 'timeInfo' structure to ask + * the thread in question to exit, and waits for it to do so. + * + *---------------------------------------------------------------------- + */ + +static void +StopCalibration( ClientData unused ) + /* Client data is unused */ +{ + SetEvent( timeInfo.exitEvent ); + WaitForSingleObject( timeInfo.calibrationThread, INFINITE ); + CloseHandle( timeInfo.exitEvent ); + CloseHandle( timeInfo.calibrationThread ); +} + +/* + *---------------------------------------------------------------------- + * * TclpGetTZName -- * * Gets the current timezone string. @@ -675,6 +726,7 @@ static DWORD WINAPI CalibrationThread( LPVOID arg ) { FILETIME curFileTime; + DWORD waitResult; /* Get initial system time and performance counter */ @@ -699,7 +751,13 @@ CalibrationThread( LPVOID arg ) /* Run the calibration once a second */ for ( ; ; ) { - Sleep( 1000 ); + + /* If the exitEvent is set, break out of the loop. */ + + waitResult = WaitForSingleObjectEx(timeInfo.exitEvent, 1000, FALSE); + if ( waitResult == WAIT_OBJECT_0 ) { + break; + } UpdateTimeEachSecond(); } |