diff options
Diffstat (limited to 'win/tclWinTime.c')
| -rw-r--r-- | win/tclWinTime.c | 219 | 
1 files changed, 63 insertions, 156 deletions
| diff --git a/win/tclWinTime.c b/win/tclWinTime.c index c1e2b6e..18702e7 100644 --- a/win/tclWinTime.c +++ b/win/tclWinTime.c @@ -8,8 +8,6 @@   *   * 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.33 2005/11/04 00:06:51 dkf Exp $   */  #include "tclInt.h" @@ -29,25 +27,27 @@   * month, where index 1 is January.   */ -static int normalDays[] = { +#ifndef TCL_NO_DEPRECATED +static const int normalDays[] = {      -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364  }; -static int leapDays[] = { +static const int leapDays[] = {      -1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365  }; -typedef struct ThreadSpecificData { +typedef struct {      char tzName[64];		/* Time zone name */      struct tm tm;		/* time information */  } ThreadSpecificData;  static Tcl_ThreadDataKey dataKey; +#endif /* TCL_NO_DEPRECATED */  /*   * Data for managing high-resolution timers.   */ -typedef struct TimeInfo { +typedef struct {      CRITICAL_SECTION cs;	/* Mutex guarding this structure. */      int initialized;		/* Flag == 1 if this structure is  				 * initialized. */ @@ -89,7 +89,7 @@ typedef struct TimeInfo {  } TimeInfo;  static TimeInfo timeInfo = { -    { NULL }, +    { NULL, 0, 0, NULL, NULL, 0 },      0,      0,      (HANDLE) NULL, @@ -115,7 +115,9 @@ static TimeInfo timeInfo = {   * Declarations for functions defined later in this file.   */ +#ifndef TCL_NO_DEPRECATED  static struct tm *	ComputeGMT(const time_t *tp); +#endif /* TCL_NO_DEPRECATED */  static void		StopCalibration(ClientData clientData);  static DWORD WINAPI	CalibrationThread(LPVOID arg);  static void 		UpdateTimeEachSecond(void); @@ -158,7 +160,7 @@ TclpGetSeconds(void)  {      Tcl_Time t; -    (*tclGetTimeProcPtr) (&t, tclTimeClientData);    /* Tcl_GetTime inlined. */ +    tclGetTimeProcPtr(&t, tclTimeClientData);	/* Tcl_GetTime inlined. */      return t.sec;  } @@ -192,7 +194,7 @@ TclpGetClicks(void)      Tcl_Time now;		/* Current Tcl time */      unsigned long retval;	/* Value to return */ -    (*tclGetTimeProcPtr) (&now, tclTimeClientData);   /* Tcl_GetTime inlined */ +    tclGetTimeProcPtr(&now, tclTimeClientData);	/* Tcl_GetTime inlined */      retval = (now.sec * 1000000) + now.usec;      return retval; @@ -202,35 +204,6 @@ TclpGetClicks(void)  /*   *----------------------------------------------------------------------   * - * TclpGetTimeZone -- - * - *	Determines the current timezone. The method varies wildly between - *	different Platform implementations, so its hidden in this function. - * - * Results: - *	Minutes west of GMT. - * - * Side effects: - *	None. - * - *---------------------------------------------------------------------- - */ - -int -TclpGetTimeZone( -    unsigned long currentTime) -{ -    int timeZone; - -    tzset(); -    timeZone = timezone / 60; - -    return timeZone; -} - -/* - *---------------------------------------------------------------------- - *   * Tcl_GetTime --   *   *	Gets the current system time in seconds and microseconds since the @@ -254,7 +227,7 @@ void  Tcl_GetTime(      Tcl_Time *timePtr)		/* Location to store time information. */  { -    (*tclGetTimeProcPtr) (timePtr, tclTimeClientData); +    tclGetTimeProcPtr(timePtr, tclTimeClientData);  }  /* @@ -311,9 +284,7 @@ NativeGetTime(      Tcl_Time *timePtr,      ClientData clientData)  { -    struct timeb t; -    int useFtime = 1;		/* Flag == TRUE if we need to fall back on -				 * ftime rather than using the perf counter. */ +    struct _timeb t;      /*       * Initialize static storage on the first trip through. @@ -372,7 +343,7 @@ NativeGetTime(  		 */  		SYSTEM_INFO systemInfo; -		unsigned int regs[4]; +		int regs[4];  		GetSystemInfo(&systemInfo);  		if (TclWinCPUID(0, regs) == TCL_OK @@ -384,7 +355,7 @@ NativeGetTime(  			|| ((regs[0] & 0x00F00000)	/* Extended family */  			&& (regs[3] & 0x10000000)))	/* Hyperthread */  			&& (((regs[1]&0x00FF0000) >> 16)/* CPU count */ -			    == systemInfo.dwNumberOfProcessors)) { +			    == (int)systemInfo.dwNumberOfProcessors)) {  		    timeInfo.perfCounterAvailable = TRUE;  		} else {  		    timeInfo.perfCounterAvailable = FALSE; @@ -416,7 +387,7 @@ NativeGetTime(  		WaitForSingleObject(timeInfo.readyEvent, INFINITE);  		CloseHandle(timeInfo.readyEvent); -		Tcl_CreateExitHandler(StopCalibration, (ClientData) NULL); +		Tcl_CreateExitHandler(StopCalibration, NULL);  	    }  	    timeInfo.initialized = TRUE;  	} @@ -429,6 +400,10 @@ NativeGetTime(  	 * time.  	 */ +	ULARGE_INTEGER fileTimeLastCall; +	LARGE_INTEGER perfCounterLastCall, curCounterFreq; +				/* Copy with current data of calibration cycle */ +  	LARGE_INTEGER curCounter;  				/* Current performance counter. */  	Tcl_WideInt curFileTime;/* Current estimated time, expressed as 100-ns @@ -442,9 +417,29 @@ NativeGetTime(  	posixEpoch.LowPart = 0xD53E8000;  	posixEpoch.HighPart = 0x019DB1DE; +	QueryPerformanceCounter(&curCounter); + +	/* +	 * Hold time section locked as short as possible +	 */  	EnterCriticalSection(&timeInfo.cs); -	QueryPerformanceCounter(&curCounter); +	fileTimeLastCall.QuadPart = timeInfo.fileTimeLastCall.QuadPart; +	perfCounterLastCall.QuadPart = timeInfo.perfCounterLastCall.QuadPart; +	curCounterFreq.QuadPart = timeInfo.curCounterFreq.QuadPart; + +	LeaveCriticalSection(&timeInfo.cs); + +	/* +	 * If calibration cycle occurred after we get curCounter +	 */ +	if (curCounter.QuadPart <= perfCounterLastCall.QuadPart) { +	    usecSincePosixEpoch = +		(fileTimeLastCall.QuadPart - posixEpoch.QuadPart) / 10; +	    timePtr->sec = (long) (usecSincePosixEpoch / 1000000); +	    timePtr->usec = (unsigned long) (usecSincePosixEpoch % 1000000); +	    return; +	}  	/*  	 * If it appears to be more than 1.1 seconds since the last trip @@ -456,31 +451,27 @@ NativeGetTime(  	 * loop should recover.  	 */ -	if (curCounter.QuadPart - timeInfo.perfCounterLastCall.QuadPart < -		11 * timeInfo.curCounterFreq.QuadPart / 10) { -	    curFileTime = timeInfo.fileTimeLastCall.QuadPart + -		 ((curCounter.QuadPart - timeInfo.perfCounterLastCall.QuadPart) -		    * 10000000 / timeInfo.curCounterFreq.QuadPart); -	    timeInfo.fileTimeLastCall.QuadPart = curFileTime; -	    timeInfo.perfCounterLastCall.QuadPart = curCounter.QuadPart; +	if (curCounter.QuadPart - perfCounterLastCall.QuadPart < +		11 * curCounterFreq.QuadPart / 10 +	) { +	    curFileTime = fileTimeLastCall.QuadPart + +		 ((curCounter.QuadPart - perfCounterLastCall.QuadPart) +		    * 10000000 / curCounterFreq.QuadPart); +  	    usecSincePosixEpoch = (curFileTime - posixEpoch.QuadPart) / 10;  	    timePtr->sec = (long) (usecSincePosixEpoch / 1000000);  	    timePtr->usec = (unsigned long) (usecSincePosixEpoch % 1000000); -	    useFtime = 0; +	    return;  	} - -	LeaveCriticalSection(&timeInfo.cs);      } -    if (useFtime) { -	/* -	 * High resolution timer is not available. Just use ftime. -	 */ +    /* +     * High resolution timer is not available. Just use ftime. +     */ -	ftime(&t); -	timePtr->sec = (long)t.time; -	timePtr->usec = t.millitm * 1000; -    } +    _ftime(&t); +    timePtr->sec = (long)t.time; +    timePtr->usec = t.millitm * 1000;  }  /* @@ -520,93 +511,6 @@ StopCalibration(  /*   *----------------------------------------------------------------------   * - * TclpGetTZName -- - * - *	Gets the current timezone string. - * - * Results: - *	Returns a pointer to a static string, or NULL on failure. - * - * Side effects: - *	None. - * - *---------------------------------------------------------------------- - */ - -char * -TclpGetTZName( -    int dst) -{ -    int len; -    char *zone, *p; -    TIME_ZONE_INFORMATION tz; -    Tcl_Encoding encoding; -    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); -    char *name = tsdPtr->tzName; - -    /* -     * tzset() under Borland doesn't seem to set up tzname[] at all. -     * tzset() under MSVC has the following weird observed behavior: -     *	 First time we call "clock format [clock seconds] -format %Z -gmt 1" -     *	 we get "GMT", but on all subsequent calls we get the current time -     *	 ezone string, even though env(TZ) is GMT and the variable _timezone -     *	 is 0. -     */ - -    name[0] = '\0'; - -    zone = getenv("TZ"); -    if (zone != NULL) { -	/* -	 * TZ is of form "NST-4:30NDT", where "NST" would be the name of the -	 * standard time zone for this area, "-4:30" is the offset from GMT in -	 * hours, and "NDT is the name of the daylight savings time zone in -	 * this area. The offset and DST strings are optional. -	 */ - -	len = strlen(zone); -	if (len > 3) { -	    len = 3; -	} -	if (dst != 0) { -	    /* -	     * Skip the offset string and get the DST string. -	     */ - -	    p = zone + len; -	    p += strspn(p, "+-:0123456789"); -	    if (*p != '\0') { -		zone = p; -		len = strlen(zone); -		if (len > 3) { -		    len = 3; -		} -	    } -	} -	Tcl_ExternalToUtf(NULL, NULL, zone, len, 0, NULL, name, -		sizeof(tsdPtr->tzName), NULL, NULL, NULL); -    } -    if (name[0] == '\0') { -	if (GetTimeZoneInformation(&tz) == TIME_ZONE_ID_UNKNOWN) { -	    /* -	     * MSDN: On NT this is returned if DST is not used in the current -	     * TZ -	     */ - -	    dst = 0; -	} -	encoding = Tcl_GetEncoding(NULL, "unicode"); -	Tcl_ExternalToUtf(NULL, encoding, -		(char *) ((dst) ? tz.DaylightName : tz.StandardName), -1, -		0, NULL, name, sizeof(tsdPtr->tzName), NULL, NULL, NULL); -	Tcl_FreeEncoding(encoding); -    } -    return name; -} - -/* - *---------------------------------------------------------------------- - *   * TclpGetDate --   *   *	This function converts between seconds and struct tm. If useGMT is @@ -622,9 +526,10 @@ TclpGetTZName(   *----------------------------------------------------------------------   */ +#ifndef TCL_NO_DEPRECATED  struct tm *  TclpGetDate( -    CONST time_t *t, +    const time_t *t,      int useGMT)  {      struct tm *tmPtr; @@ -736,7 +641,7 @@ ComputeGMT(      struct tm *tmPtr;      long tmp, rem;      int isLeap; -    int *days; +    const int *days;      ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);      tmPtr = &tsdPtr->tm; @@ -824,6 +729,7 @@ ComputeGMT(      return tmPtr;  } +#endif /* TCL_NO_DEPRECATED */  /*   *---------------------------------------------------------------------- @@ -1168,9 +1074,10 @@ AccumulateSample(   *----------------------------------------------------------------------   */ +#ifndef TCL_NO_DEPRECATED  struct tm *  TclpGmtime( -    CONST time_t *timePtr)	/* Pointer to the number of seconds since the +    const time_t *timePtr)	/* Pointer to the number of seconds since the  				 * local system's epoch */  {      /* @@ -1201,9 +1108,8 @@ TclpGmtime(  struct tm *  TclpLocaltime( -    CONST time_t *timePtr)	/* Pointer to the number of seconds since the +    const time_t *timePtr)	/* Pointer to the number of seconds since the  				 * local system's epoch */ -  {      /*       * The MS implementation of localtime is thread safe because it returns @@ -1213,6 +1119,7 @@ TclpLocaltime(      return localtime(timePtr);  } +#endif /* TCL_NO_DEPRECATED */  /*   *---------------------------------------------------------------------- | 
