summaryrefslogtreecommitdiffstats
path: root/win
diff options
context:
space:
mode:
authorsebres <sebres@users.sourceforge.net>2017-01-02 14:31:22 (GMT)
committersebres <sebres@users.sourceforge.net>2017-01-02 14:31:22 (GMT)
commitb901129d9617508943f0a9e70ae6de14b10c8fec (patch)
tree8dd5d50d589afd40c0d90b93df4dae5c46d09ab0 /win
parentbe0289c6ab1c90cdc651dd4219d6566e68ff5d3e (diff)
downloadtcl-b901129d9617508943f0a9e70ae6de14b10c8fec.zip
tcl-b901129d9617508943f0a9e70ae6de14b10c8fec.tar.gz
tcl-b901129d9617508943f0a9e70ae6de14b10c8fec.tar.bz2
[win] bug fix in NativeGetTime: each call of it blurs current performance counters actualized in calibration thread in UpdateTimeEachSecond;
This entails that sometimes sporadically time-drifts resp. jump-esque time-shifts occurred, what for example produces very confusing results during time measurement. [unix] wrong cast fixed in TclpGetWideClicks: multiplication with 1000000 in long int may cause overflow See ticket b87ad7e9146832d505f9a430d779c5313c440256
Diffstat (limited to 'win')
-rw-r--r--win/tclWinTime.c54
1 files changed, 37 insertions, 17 deletions
diff --git a/win/tclWinTime.c b/win/tclWinTime.c
index 71a0366..8546c68 100644
--- a/win/tclWinTime.c
+++ b/win/tclWinTime.c
@@ -280,10 +280,6 @@ 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. */
-
/*
* Initialize static storage on the first trip through.
*
@@ -398,6 +394,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
@@ -411,9 +411,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
@@ -425,31 +445,31 @@ 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) {
+ do {
/*
* High resolution timer is not available. Just use ftime.
*/
+ struct _timeb t;
_ftime(&t);
timePtr->sec = (long)t.time;
timePtr->usec = t.millitm * 1000;
- }
+
+ } while(0);
}
/*