summaryrefslogtreecommitdiffstats
path: root/win/tclWinTime.c
diff options
context:
space:
mode:
Diffstat (limited to 'win/tclWinTime.c')
-rw-r--r--win/tclWinTime.c201
1 files changed, 150 insertions, 51 deletions
diff --git a/win/tclWinTime.c b/win/tclWinTime.c
index 81d9458..0163723 100644
--- a/win/tclWinTime.c
+++ b/win/tclWinTime.c
@@ -35,7 +35,7 @@ static const int leapDays[] = {
-1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
};
-typedef struct {
+typedef struct ThreadSpecificData {
char tzName[64]; /* Time zone name */
struct tm tm; /* time information */
} ThreadSpecificData;
@@ -45,7 +45,7 @@ static Tcl_ThreadDataKey dataKey;
* Data for managing high-resolution timers.
*/
-typedef struct {
+typedef struct TimeInfo {
CRITICAL_SECTION cs; /* Mutex guarding this structure. */
int initialized; /* Flag == 1 if this structure is
* initialized. */
@@ -87,7 +87,7 @@ typedef struct {
} TimeInfo;
static TimeInfo timeInfo = {
- { NULL, 0, 0, NULL, NULL, 0 },
+ { NULL },
0,
0,
(HANDLE) NULL,
@@ -156,7 +156,7 @@ TclpGetSeconds(void)
{
Tcl_Time t;
- tclGetTimeProcPtr(&t, tclTimeClientData); /* Tcl_GetTime inlined. */
+ (*tclGetTimeProcPtr) (&t, tclTimeClientData); /* Tcl_GetTime inlined. */
return t.sec;
}
@@ -190,7 +190,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;
@@ -200,6 +200,35 @@ 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
@@ -223,7 +252,7 @@ void
Tcl_GetTime(
Tcl_Time *timePtr) /* Location to store time information. */
{
- tclGetTimeProcPtr(timePtr, tclTimeClientData);
+ (*tclGetTimeProcPtr) (timePtr, tclTimeClientData);
}
/*
@@ -281,6 +310,8 @@ NativeGetTime(
ClientData clientData)
{
struct _timeb t;
+ int useFtime = 1; /* Flag == TRUE if we need to fall back on
+ * ftime rather than using the perf counter. */
/*
* Initialize static storage on the first trip through.
@@ -339,7 +370,7 @@ NativeGetTime(
*/
SYSTEM_INFO systemInfo;
- int regs[4];
+ unsigned int regs[4];
GetSystemInfo(&systemInfo);
if (TclWinCPUID(0, regs) == TCL_OK
@@ -351,7 +382,7 @@ NativeGetTime(
|| ((regs[0] & 0x00F00000) /* Extended family */
&& (regs[3] & 0x10000000))) /* Hyperthread */
&& (((regs[1]&0x00FF0000) >> 16)/* CPU count */
- == (int)systemInfo.dwNumberOfProcessors)) {
+ == systemInfo.dwNumberOfProcessors)) {
timeInfo.perfCounterAvailable = TRUE;
} else {
timeInfo.perfCounterAvailable = FALSE;
@@ -383,7 +414,7 @@ NativeGetTime(
WaitForSingleObject(timeInfo.readyEvent, INFINITE);
CloseHandle(timeInfo.readyEvent);
- Tcl_CreateExitHandler(StopCalibration, NULL);
+ Tcl_CreateExitHandler(StopCalibration, (ClientData) NULL);
}
timeInfo.initialized = TRUE;
}
@@ -396,10 +427,6 @@ 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
@@ -413,29 +440,9 @@ NativeGetTime(
posixEpoch.LowPart = 0xD53E8000;
posixEpoch.HighPart = 0x019DB1DE;
- QueryPerformanceCounter(&curCounter);
-
- /*
- * Hold time section locked as short as possible
- */
EnterCriticalSection(&timeInfo.cs);
- 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;
- }
+ QueryPerformanceCounter(&curCounter);
/*
* If it appears to be more than 1.1 seconds since the last trip
@@ -447,27 +454,31 @@ NativeGetTime(
* loop should recover.
*/
- if (curCounter.QuadPart - perfCounterLastCall.QuadPart <
- 11 * curCounterFreq.QuadPart / 10
- ) {
- curFileTime = fileTimeLastCall.QuadPart +
- ((curCounter.QuadPart - perfCounterLastCall.QuadPart)
- * 10000000 / curCounterFreq.QuadPart);
-
+ 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;
usecSincePosixEpoch = (curFileTime - posixEpoch.QuadPart) / 10;
timePtr->sec = (long) (usecSincePosixEpoch / 1000000);
timePtr->usec = (unsigned long) (usecSincePosixEpoch % 1000000);
- return;
+ useFtime = 0;
}
+
+ LeaveCriticalSection(&timeInfo.cs);
}
- /*
- * High resolution timer is not available. Just use ftime.
- */
+ if (useFtime) {
+ /*
+ * 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;
+ }
}
/*
@@ -507,6 +518,93 @@ 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
@@ -524,7 +622,7 @@ StopCalibration(
struct tm *
TclpGetDate(
- const time_t *t,
+ CONST time_t *t,
int useGMT)
{
struct tm *tmPtr;
@@ -1070,7 +1168,7 @@ AccumulateSample(
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 */
{
/*
@@ -1101,8 +1199,9 @@ 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