summaryrefslogtreecommitdiffstats
path: root/win
diff options
context:
space:
mode:
authorKevin B Kenny <kennykb@acm.org>2002-10-09 23:57:25 (GMT)
committerKevin B Kenny <kennykb@acm.org>2002-10-09 23:57:25 (GMT)
commit3cb21be3557aec892643f059671997558259e741 (patch)
treebc1983e9d14ead261e9708d234d747f8edf23409 /win
parent16284e7d81c8d903edecbbaa014ae84589140150 (diff)
downloadtcl-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')
-rw-r--r--win/tclWinTime.c68
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();
}