Import Tcl 8.6.10

This commit is contained in:
Steve Dower
2020-09-24 22:53:56 +01:00
parent 0343d03b22
commit 3bb8e3e086
1005 changed files with 593700 additions and 41637 deletions

View File

@@ -51,6 +51,7 @@ typedef struct TimeInfo {
* initialized. */
int perfCounterAvailable; /* Flag == 1 if the hardware has a performance
* counter. */
DWORD calibrationInterv; /* Calibration interval in seconds (start 1 sec) */
HANDLE calibrationThread; /* Handle to the thread that keeps the virtual
* clock calibrated. */
HANDLE readyEvent; /* System event used to trigger the requesting
@@ -61,7 +62,6 @@ typedef struct TimeInfo {
LARGE_INTEGER nominalFreq; /* Nominal frequency of the system performance
* counter, that is, the value returned from
* QueryPerformanceFrequency. */
/*
* The following values are used for calculating virtual time. Virtual
* time is always equal to:
@@ -74,6 +74,8 @@ typedef struct TimeInfo {
ULARGE_INTEGER fileTimeLastCall;
LARGE_INTEGER perfCounterLastCall;
LARGE_INTEGER curCounterFreq;
LARGE_INTEGER posixEpoch; /* Posix epoch expressed as 100-ns ticks since
* the windows epoch. */
/*
* Data used in developing the estimate of performance counter frequency
@@ -90,6 +92,7 @@ static TimeInfo timeInfo = {
{ NULL, 0, 0, NULL, NULL, 0 },
0,
0,
1,
(HANDLE) NULL,
(HANDLE) NULL,
(HANDLE) NULL,
@@ -98,17 +101,30 @@ static TimeInfo timeInfo = {
(ULARGE_INTEGER) (DWORDLONG) 0,
(LARGE_INTEGER) (Tcl_WideInt) 0,
(LARGE_INTEGER) (Tcl_WideInt) 0,
(LARGE_INTEGER) (Tcl_WideInt) 0,
#else
0,
0,
0,
0,
{0, 0},
{0, 0},
{0, 0},
{0, 0},
{0, 0},
#endif
{ 0 },
{ 0 },
0
};
/*
* Scale to convert wide click values from the TclpGetWideClicks native
* resolution to microsecond resolution and back.
*/
static struct {
int initialized; /* 1 if initialized, 0 otherwise */
int perfCounter; /* 1 if performance counter usable for wide clicks */
double microsecsScale; /* Denominator scale between clock / microsecs */
} wideClick = {0, 0, 0.0};
/*
* Declarations for functions defined later in this file.
*/
@@ -123,6 +139,7 @@ static Tcl_WideInt AccumulateSample(Tcl_WideInt perfCounter,
Tcl_WideUInt fileTime);
static void NativeScaleTime(Tcl_Time* timebuf,
ClientData clientData);
static Tcl_WideInt NativeGetMicroseconds(void);
static void NativeGetTime(Tcl_Time* timebuf,
ClientData clientData);
@@ -154,10 +171,19 @@ ClientData tclTimeClientData = NULL;
unsigned long
TclpGetSeconds(void)
{
Tcl_Time t;
Tcl_WideInt usecSincePosixEpoch;
tclGetTimeProcPtr(&t, tclTimeClientData); /* Tcl_GetTime inlined. */
return t.sec;
/* Try to use high resolution timer */
if ( tclGetTimeProcPtr == NativeGetTime
&& (usecSincePosixEpoch = NativeGetMicroseconds())
) {
return usecSincePosixEpoch / 1000000;
} else {
Tcl_Time t;
tclGetTimeProcPtr(&t, tclTimeClientData); /* Tcl_GetTime inlined. */
return t.sec;
}
}
/*
@@ -168,7 +194,7 @@ TclpGetSeconds(void)
* This procedure returns a value that represents the highest resolution
* clock available on the system. There are no guarantees on what the
* resolution will be. In Tcl we will call this value a "click". The
* start time is also system dependant.
* start time is also system dependent.
*
* Results:
* Number of clicks from some start time.
@@ -182,19 +208,147 @@ TclpGetSeconds(void)
unsigned long
TclpGetClicks(void)
{
/*
* Use the Tcl_GetTime abstraction to get the time in microseconds, as
* nearly as we can, and return it.
*/
Tcl_WideInt usecSincePosixEpoch;
Tcl_Time now; /* Current Tcl time */
unsigned long retval; /* Value to return */
/* Try to use high resolution timer */
if ( tclGetTimeProcPtr == NativeGetTime
&& (usecSincePosixEpoch = NativeGetMicroseconds())
) {
return (unsigned long)usecSincePosixEpoch;
} else {
/*
* Use the Tcl_GetTime abstraction to get the time in microseconds, as
* nearly as we can, and return it.
*/
tclGetTimeProcPtr(&now, tclTimeClientData); /* Tcl_GetTime inlined */
Tcl_Time now; /* Current Tcl time */
retval = (now.sec * 1000000) + now.usec;
return retval;
tclGetTimeProcPtr(&now, tclTimeClientData); /* Tcl_GetTime inlined */
return (unsigned long)(now.sec * 1000000) + now.usec;
}
}
/*
*----------------------------------------------------------------------
*
* TclpGetWideClicks --
*
* This procedure returns a WideInt value that represents the highest
* resolution clock in microseconds available on the system.
*
* Results:
* Number of microseconds (from some start time).
*
* Side effects:
* This should be used for time-delta resp. for measurement purposes
* only, because on some platforms can return microseconds from some
* start time (not from the epoch).
*
*----------------------------------------------------------------------
*/
Tcl_WideInt
TclpGetWideClicks(void)
{
LARGE_INTEGER curCounter;
if (!wideClick.initialized) {
LARGE_INTEGER perfCounterFreq;
/*
* The frequency of the performance counter is fixed at system boot and
* is consistent across all processors. Therefore, the frequency need
* only be queried upon application initialization.
*/
if (QueryPerformanceFrequency(&perfCounterFreq)) {
wideClick.perfCounter = 1;
wideClick.microsecsScale = 1000000.0 / perfCounterFreq.QuadPart;
} else {
/* fallback using microseconds */
wideClick.perfCounter = 0;
wideClick.microsecsScale = 1;
}
wideClick.initialized = 1;
}
if (wideClick.perfCounter) {
if (QueryPerformanceCounter(&curCounter)) {
return (Tcl_WideInt)curCounter.QuadPart;
}
/* fallback using microseconds */
wideClick.perfCounter = 0;
wideClick.microsecsScale = 1;
return TclpGetMicroseconds();
} else {
return TclpGetMicroseconds();
}
}
/*
*----------------------------------------------------------------------
*
* TclpWideClickInMicrosec --
*
* This procedure return scale to convert wide click values from the
* TclpGetWideClicks native resolution to microsecond resolution
* and back.
*
* Results:
* 1 click in microseconds as double.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
double
TclpWideClickInMicrosec(void)
{
if (!wideClick.initialized) {
(void)TclpGetWideClicks(); /* initialize */
}
return wideClick.microsecsScale;
}
/*
*----------------------------------------------------------------------
*
* TclpGetMicroseconds --
*
* This procedure returns a WideInt value that represents the highest
* resolution clock in microseconds available on the system.
*
* Results:
* Number of microseconds (from the epoch).
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
Tcl_WideInt
TclpGetMicroseconds(void)
{
Tcl_WideInt usecSincePosixEpoch;
/* Try to use high resolution timer */
if ( tclGetTimeProcPtr == NativeGetTime
&& (usecSincePosixEpoch = NativeGetMicroseconds())
) {
return usecSincePosixEpoch;
} else {
/*
* Use the Tcl_GetTime abstraction to get the time in microseconds, as
* nearly as we can, and return it.
*/
Tcl_Time now;
tclGetTimeProcPtr(&now, tclTimeClientData); /* Tcl_GetTime inlined */
return (((Tcl_WideInt)now.sec) * 1000000) + now.usec;
}
}
/*
@@ -223,7 +377,17 @@ void
Tcl_GetTime(
Tcl_Time *timePtr) /* Location to store time information. */
{
tclGetTimeProcPtr(timePtr, tclTimeClientData);
Tcl_WideInt usecSincePosixEpoch;
/* Try to use high resolution timer */
if ( tclGetTimeProcPtr == NativeGetTime
&& (usecSincePosixEpoch = NativeGetMicroseconds())
) {
timePtr->sec = (long) (usecSincePosixEpoch / 1000000);
timePtr->usec = (unsigned long) (usecSincePosixEpoch % 1000000);
} else {
tclGetTimeProcPtr(timePtr, tclTimeClientData);
}
}
/*
@@ -256,13 +420,14 @@ NativeScaleTime(
/*
*----------------------------------------------------------------------
*
* NativeGetTime --
* NativeGetMicroseconds --
*
* TIP #233: Gets the current system time in seconds and microseconds
* since the beginning of the epoch: 00:00 UCT, January 1, 1970.
* Gets the current system time in microseconds since the beginning
* of the epoch: 00:00 UCT, January 1, 1970.
*
* Results:
* Returns the current time in timePtr.
* Returns the wide integer with number of microseconds from the epoch, or
* 0 if high resolution timer is not available.
*
* Side effects:
* On the first call, initializes a set of static variables to keep track
@@ -275,13 +440,20 @@ NativeScaleTime(
*----------------------------------------------------------------------
*/
static void
NativeGetTime(
Tcl_Time *timePtr,
ClientData clientData)
{
struct _timeb t;
static inline Tcl_WideInt
NativeCalc100NsTicks(
ULONGLONG fileTimeLastCall,
LONGLONG perfCounterLastCall,
LONGLONG curCounterFreq,
LONGLONG curCounter
) {
return fileTimeLastCall +
((curCounter - perfCounterLastCall) * 10000000 / curCounterFreq);
}
static Tcl_WideInt
NativeGetMicroseconds(void)
{
/*
* Initialize static storage on the first trip through.
*
@@ -292,6 +464,10 @@ NativeGetTime(
if (!timeInfo.initialized) {
TclpInitLock();
if (!timeInfo.initialized) {
timeInfo.posixEpoch.LowPart = 0xD53E8000;
timeInfo.posixEpoch.HighPart = 0x019DB1DE;
timeInfo.perfCounterAvailable =
QueryPerformanceFrequency(&timeInfo.nominalFreq);
@@ -368,8 +544,8 @@ NativeGetTime(
DWORD id;
InitializeCriticalSection(&timeInfo.cs);
timeInfo.readyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
timeInfo.exitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
timeInfo.readyEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
timeInfo.exitEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
timeInfo.calibrationThread = CreateThread(NULL, 256,
CalibrationThread, (LPVOID) NULL, 0, &id);
SetThreadPriority(timeInfo.calibrationThread,
@@ -396,22 +572,12 @@ NativeGetTime(
* time.
*/
ULARGE_INTEGER fileTimeLastCall;
LARGE_INTEGER perfCounterLastCall, curCounterFreq;
ULONGLONG fileTimeLastCall;
LONGLONG 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
* ticks since the Windows epoch. */
static LARGE_INTEGER posixEpoch;
/* Posix epoch expressed as 100-ns ticks since
* the windows epoch. */
Tcl_WideInt usecSincePosixEpoch;
/* Current microseconds since Posix epoch. */
posixEpoch.LowPart = 0xD53E8000;
posixEpoch.HighPart = 0x019DB1DE;
QueryPerformanceCounter(&curCounter);
@@ -420,21 +586,18 @@ NativeGetTime(
*/
EnterCriticalSection(&timeInfo.cs);
fileTimeLastCall.QuadPart = timeInfo.fileTimeLastCall.QuadPart;
perfCounterLastCall.QuadPart = timeInfo.perfCounterLastCall.QuadPart;
curCounterFreq.QuadPart = timeInfo.curCounterFreq.QuadPart;
fileTimeLastCall = timeInfo.fileTimeLastCall.QuadPart;
perfCounterLastCall = timeInfo.perfCounterLastCall.QuadPart;
curCounterFreq = 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 (curCounter.QuadPart <= perfCounterLastCall) {
/* Calibrated file-time is saved from posix in 100-ns ticks */
return fileTimeLastCall / 10;
}
/*
@@ -447,27 +610,62 @@ NativeGetTime(
* loop should recover.
*/
if (curCounter.QuadPart - perfCounterLastCall.QuadPart <
11 * curCounterFreq.QuadPart / 10
if (curCounter.QuadPart - perfCounterLastCall <
11 * curCounterFreq * timeInfo.calibrationInterv / 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);
return;
/* Calibrated file-time is saved from posix in 100-ns ticks */
return NativeCalc100NsTicks(fileTimeLastCall,
perfCounterLastCall, curCounterFreq, curCounter.QuadPart) / 10;
}
}
/*
* High resolution timer is not available. Just use ftime.
* High resolution timer is not available.
*/
return 0;
}
/*
*----------------------------------------------------------------------
*
* NativeGetTime --
*
* TIP #233: Gets the current system time in seconds and microseconds
* since the beginning of the epoch: 00:00 UCT, January 1, 1970.
*
* Results:
* Returns the current time in timePtr.
*
* Side effects:
* See NativeGetMicroseconds for more information.
*
*----------------------------------------------------------------------
*/
_ftime(&t);
timePtr->sec = (long)t.time;
timePtr->usec = t.millitm * 1000;
static void
NativeGetTime(
Tcl_Time *timePtr,
ClientData clientData)
{
Tcl_WideInt usecSincePosixEpoch;
/*
* Try to use high resolution timer.
*/
if ( (usecSincePosixEpoch = NativeGetMicroseconds()) ) {
timePtr->sec = (long) (usecSincePosixEpoch / 1000000);
timePtr->usec = (unsigned long) (usecSincePosixEpoch % 1000000);
} else {
/*
* High resolution timer is not available. Just use ftime.
*/
struct _timeb t;
_ftime(&t);
timePtr->sec = (long)t.time;
timePtr->usec = t.millitm * 1000;
}
}
/*
@@ -488,6 +686,8 @@ NativeGetTime(
*----------------------------------------------------------------------
*/
void TclWinResetTimerResolution(void);
static void
StopCalibration(
ClientData unused) /* Client data is unused */
@@ -529,8 +729,18 @@ TclpGetDate(
{
struct tm *tmPtr;
time_t time;
#if defined(_WIN64) || (defined(_USE_64BIT_TIME_T) || (defined(_MSC_VER) && _MSC_VER < 1400))
# define t2 *t /* no need to cripple time to 32-bit */
#else
time_t t2 = *(__time32_t *)t;
#endif
if (!useGMT) {
#if defined(_MSC_VER) && (_MSC_VER >= 1900)
# undef timezone /* prevent conflict with timezone() function */
long timezone = 0;
#endif
tzset();
/*
@@ -556,11 +766,15 @@ TclpGetDate(
#define LOCALTIME_VALIDITY_BOUNDARY 0
#endif
if (*t >= LOCALTIME_VALIDITY_BOUNDARY) {
return TclpLocaltime(t);
if (t2 >= LOCALTIME_VALIDITY_BOUNDARY) {
return TclpLocaltime(&t2);
}
time = *t - timezone;
#if defined(_MSC_VER) && (_MSC_VER >= 1900)
_get_timezone(&timezone);
#endif
time = t2 - timezone;
/*
* If we aren't near to overflowing the long, just add the bias and
@@ -568,10 +782,10 @@ TclpGetDate(
* result at the end.
*/
if (*t < (LONG_MAX - 2*SECSPERDAY) && *t > (LONG_MIN + 2*SECSPERDAY)) {
if (t2 < (LONG_MAX - 2*SECSPERDAY) && t2 > (LONG_MIN + 2*SECSPERDAY)) {
tmPtr = ComputeGMT(&time);
} else {
tmPtr = ComputeGMT(t);
tmPtr = ComputeGMT(&t2);
tzset();
@@ -607,7 +821,7 @@ TclpGetDate(
tmPtr->tm_wday = (tmPtr->tm_wday + (int)time) % 7;
}
} else {
tmPtr = ComputeGMT(t);
tmPtr = ComputeGMT(&t2);
}
return tmPtr;
}
@@ -767,6 +981,8 @@ CalibrationThread(
QueryPerformanceFrequency(&timeInfo.curCounterFreq);
timeInfo.fileTimeLastCall.LowPart = curFileTime.dwLowDateTime;
timeInfo.fileTimeLastCall.HighPart = curFileTime.dwHighDateTime;
/* Calibrated file-time will be saved from posix in 100-ns ticks */
timeInfo.fileTimeLastCall.QuadPart -= timeInfo.posixEpoch.QuadPart;
ResetCounterSamples(timeInfo.fileTimeLastCall.QuadPart,
timeInfo.perfCounterLastCall.QuadPart,
@@ -826,6 +1042,7 @@ UpdateTimeEachSecond(void)
/* Current value returned from
* QueryPerformanceCounter. */
FILETIME curSysTime; /* Current system time. */
static LARGE_INTEGER lastFileTime; /* File time of the previous calibration */
LARGE_INTEGER curFileTime; /* File time at the time this callback was
* scheduled. */
Tcl_WideInt estFreq; /* Estimated perf counter frequency. */
@@ -837,15 +1054,24 @@ UpdateTimeEachSecond(void)
* step over 1 second. */
/*
* Sample performance counter and system time.
* Sample performance counter and system time (from posix epoch).
*/
QueryPerformanceCounter(&curPerfCounter);
GetSystemTimeAsFileTime(&curSysTime);
curFileTime.LowPart = curSysTime.dwLowDateTime;
curFileTime.HighPart = curSysTime.dwHighDateTime;
curFileTime.QuadPart -= timeInfo.posixEpoch.QuadPart;
/* If calibration still not needed (check for possible time switch) */
if ( curFileTime.QuadPart > lastFileTime.QuadPart
&& curFileTime.QuadPart < lastFileTime.QuadPart +
(timeInfo.calibrationInterv * 10000000)
) {
/* again in next one second */
return;
}
QueryPerformanceCounter(&curPerfCounter);
EnterCriticalSection(&timeInfo.cs);
lastFileTime.QuadPart = curFileTime.QuadPart;
/*
* We devide by timeInfo.curCounterFreq.QuadPart in several places. That
@@ -857,7 +1083,6 @@ UpdateTimeEachSecond(void)
*/
if (timeInfo.curCounterFreq.QuadPart == 0){
LeaveCriticalSection(&timeInfo.cs);
timeInfo.perfCounterAvailable = 0;
return;
}
@@ -896,12 +1121,9 @@ UpdateTimeEachSecond(void)
* is estFreq * 20000000 / (vt1 - vt0)
*/
vt0 = 10000000 * (curPerfCounter.QuadPart
- timeInfo.perfCounterLastCall.QuadPart)
/ timeInfo.curCounterFreq.QuadPart
+ timeInfo.fileTimeLastCall.QuadPart;
vt1 = 20000000 + curFileTime.QuadPart;
vt0 = NativeCalc100NsTicks(timeInfo.fileTimeLastCall.QuadPart,
timeInfo.perfCounterLastCall.QuadPart, timeInfo.curCounterFreq.QuadPart,
curPerfCounter.QuadPart);
/*
* If we've gotten more than a second away from system time, then drifting
* the clock is going to be pretty hopeless. Just let it jump. Otherwise,
@@ -910,21 +1132,75 @@ UpdateTimeEachSecond(void)
tdiff = vt0 - curFileTime.QuadPart;
if (tdiff > 10000000 || tdiff < -10000000) {
timeInfo.fileTimeLastCall.QuadPart = curFileTime.QuadPart;
timeInfo.curCounterFreq.QuadPart = estFreq;
/* jump to current system time, use curent estimated frequency */
vt0 = curFileTime.QuadPart;
} else {
driftFreq = estFreq * 20000000 / (vt1 - vt0);
/* calculate new frequency and estimate drift to the next second */
vt1 = 20000000 + curFileTime.QuadPart;
driftFreq = (estFreq * 20000000 / (vt1 - vt0));
/*
* Avoid too large drifts (only half of the current difference),
* that allows also be more accurate (aspire to the smallest tdiff),
* so then we can prolong calibration interval by tdiff < 100000
*/
driftFreq = timeInfo.curCounterFreq.QuadPart +
(driftFreq - timeInfo.curCounterFreq.QuadPart) / 2;
if (driftFreq > 1003*estFreq/1000) {
driftFreq = 1003*estFreq/1000;
} else if (driftFreq < 997*estFreq/1000) {
driftFreq = 997*estFreq/1000;
}
timeInfo.fileTimeLastCall.QuadPart = vt0;
timeInfo.curCounterFreq.QuadPart = driftFreq;
/*
* Average between estimated, 2 current and 5 drifted frequencies,
* (do the soft drifting as possible)
*/
estFreq = (estFreq + 2 * timeInfo.curCounterFreq.QuadPart + 5 * driftFreq) / 8;
}
/* Avoid too large discrepancy from nominal frequency */
if (estFreq > 1003*timeInfo.nominalFreq.QuadPart/1000) {
estFreq = 1003*timeInfo.nominalFreq.QuadPart/1000;
vt0 = curFileTime.QuadPart;
} else if (estFreq < 997*timeInfo.nominalFreq.QuadPart/1000) {
estFreq = 997*timeInfo.nominalFreq.QuadPart/1000;
vt0 = curFileTime.QuadPart;
} else if (vt0 != curFileTime.QuadPart) {
/*
* Be sure the clock ticks never backwards (avoid it by negative drifting)
* just compare native time (in 100-ns) before and hereafter using
* new calibrated values) and do a small adjustment (short time freeze)
*/
LARGE_INTEGER newPerfCounter;
Tcl_WideInt nt0, nt1;
QueryPerformanceCounter(&newPerfCounter);
nt0 = NativeCalc100NsTicks(timeInfo.fileTimeLastCall.QuadPart,
timeInfo.perfCounterLastCall.QuadPart, timeInfo.curCounterFreq.QuadPart,
newPerfCounter.QuadPart);
nt1 = NativeCalc100NsTicks(vt0,
curPerfCounter.QuadPart, estFreq,
newPerfCounter.QuadPart);
if (nt0 > nt1) { /* drifted backwards, try to compensate with new base */
/* first adjust with a micro jump (short frozen time is acceptable) */
vt0 += nt0 - nt1;
/* if drift unavoidable (e. g. we had a time switch), then reset it */
vt1 = vt0 - curFileTime.QuadPart;
if (vt1 > 10000000 || vt1 < -10000000) {
/* larger jump resp. shift relative new file-time */
vt0 = curFileTime.QuadPart;
}
}
}
/* In lock commit new values to timeInfo (hold lock as short as possible) */
EnterCriticalSection(&timeInfo.cs);
/* grow calibration interval up to 10 seconds (if still precise enough) */
if (tdiff < -100000 || tdiff > 100000) {
/* too long drift - reset calibration interval to 1000 second */
timeInfo.calibrationInterv = 1;
} else if (timeInfo.calibrationInterv < 10) {
timeInfo.calibrationInterv++;
}
timeInfo.fileTimeLastCall.QuadPart = vt0;
timeInfo.curCounterFreq.QuadPart = estFreq;
timeInfo.perfCounterLastCall.QuadPart = curPerfCounter.QuadPart;
LeaveCriticalSection(&timeInfo.cs);
@@ -1079,7 +1355,11 @@ TclpGmtime(
* Posix gmtime_r function.
*/
#if defined(_WIN64) || defined(_USE_64BIT_TIME_T) || (defined(_MSC_VER) && _MSC_VER < 1400)
return gmtime(timePtr);
#else
return _gmtime32((CONST __time32_t *)timePtr);
#endif
}
/*
@@ -1110,7 +1390,11 @@ TclpLocaltime(
* provide a Posix localtime_r function.
*/
#if defined(_WIN64) || defined(_USE_64BIT_TIME_T) || (defined(_MSC_VER) && _MSC_VER < 1400)
return localtime(timePtr);
#else
return _localtime32((CONST __time32_t *)timePtr);
#endif
}
/*