diff options
author | sebres <sebres@users.sourceforge.net> | 2017-01-02 14:31:22 (GMT) |
---|---|---|
committer | sebres <sebres@users.sourceforge.net> | 2017-01-02 14:31:22 (GMT) |
commit | b901129d9617508943f0a9e70ae6de14b10c8fec (patch) | |
tree | 8dd5d50d589afd40c0d90b93df4dae5c46d09ab0 /win | |
parent | be0289c6ab1c90cdc651dd4219d6566e68ff5d3e (diff) | |
download | tcl-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.c | 54 |
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); } /* |