diff options
author | sebres <sebres@users.sourceforge.net> | 2017-07-03 13:25:25 (GMT) |
---|---|---|
committer | sebres <sebres@users.sourceforge.net> | 2017-07-03 13:25:25 (GMT) |
commit | 1b814ecdc54b17f604790d2242e3249dbf38d068 (patch) | |
tree | f1e75eae8f373aadade5ba5766cccec585061636 | |
parent | fdc24c5c31c074dce2539aad1c9cc7facb565099 (diff) | |
download | tcl-1b814ecdc54b17f604790d2242e3249dbf38d068.zip tcl-1b814ecdc54b17f604790d2242e3249dbf38d068.tar.gz tcl-1b814ecdc54b17f604790d2242e3249dbf38d068.tar.bz2 |
[win32] use timer resolution handling in Tcl_Sleep also;
-rw-r--r-- | generic/tclTimer.c | 22 | ||||
-rw-r--r-- | win/tclWinNotify.c | 73 |
2 files changed, 75 insertions, 20 deletions
diff --git a/generic/tclTimer.c b/generic/tclTimer.c index aa78b22..f1235be 100644 --- a/generic/tclTimer.c +++ b/generic/tclTimer.c @@ -611,7 +611,7 @@ TimerSetupProc( blockTime.sec = firstTime->sec - blockTime.sec; blockTime.usec = firstTime->usec - blockTime.usec; if (blockTime.usec < 0) { - blockTime.sec -= 1; + blockTime.sec--; blockTime.usec += 1000000; } if (blockTime.sec < 0) { @@ -665,8 +665,8 @@ TimerCheckProc( if (tsdPtr == NULL) { tsdPtr = InitTimer(); }; - /* If already pending */ - if (!tsdPtr->timerList || tsdPtr->timerPending) { + /* If already pending (or no timer-events) */ + if (tsdPtr->timerPending || !tsdPtr->timerList) { return; } @@ -678,18 +678,14 @@ TimerCheckProc( blockTime.sec = firstTime->sec - blockTime.sec; blockTime.usec = firstTime->usec - blockTime.usec; if (blockTime.usec < 0) { - blockTime.sec -= 1; + blockTime.sec--; blockTime.usec += 1000000; } - if (blockTime.sec < 0) { - blockTime.sec = 0; - blockTime.usec = 0; - } /* * If the first timer has expired, stick an event on the queue. */ - if (blockTime.sec == 0 && blockTime.usec == 0) { + if (blockTime.sec < 0 || blockTime.sec == 0 && blockTime.usec <= 0) { TclSetTimerEventMarker(0); tsdPtr->timerPending = 1; } @@ -726,7 +722,6 @@ TclServiceTimerEvents(void) int prevTmrPending; ThreadSpecificData *tsdPtr = InitTimer(); - if (!tsdPtr->timerPending) { return 0; /* no timer events */ } @@ -1375,6 +1370,13 @@ AfterDelay( Tcl_Time endTime, now; Tcl_WideInt diff; + if (ms <= 0) { + /* to cause a context switch only */ + Tcl_Sleep(0); + return TCL_OK; + } + + Tcl_GetTime(&endTime); TclTimeAddMilliseconds(&endTime, ms); diff --git a/win/tclWinNotify.c b/win/tclWinNotify.c index d9d0f5d..9c13ff2 100644 --- a/win/tclWinNotify.c +++ b/win/tclWinNotify.c @@ -671,17 +671,17 @@ Tcl_WaitForEvent( endTime.sec++; } + if (timerResolution.available == -1) { + InitTimerResolution(); + } + + repeat: /* * TIP #233 (Virtualized Time). Convert virtual domain delay to * real-time. */ (*tclScaleTimeProcPtr) (&waitTime, tclTimeClientData); - if (timerResolution.available == -1) { - InitTimerResolution(); - } - - repeat: /* add possible tolerance in percent, so "round" to full ms (-overhead) */ waitTime.usec += waitTime.usec * (TMR_RES_TOLERANCE / 100); /* No wait if timeout too small (because windows may wait too long) */ @@ -846,6 +846,18 @@ Tcl_Sleep( * real. */ DWORD sleepTime; /* Time to sleep, real-time */ + unsigned long actualResolution = 0; + + if (ms <= 0) { + /* causes context switch only */ + Sleep(0); + return; + } + + if (timerResolution.available == -1) { + InitTimerResolution(); + } + vdelay.sec = ms / 1000; vdelay.usec = (ms % 1000) * 1000; @@ -861,10 +873,45 @@ Tcl_Sleep( * TIP #233: Scale delay from virtual to real-time. */ - (*tclScaleTimeProcPtr) (&vdelay, tclTimeClientData); - sleepTime = vdelay.sec * 1000 + vdelay.usec / 1000; - for (;;) { + + (*tclScaleTimeProcPtr) (&vdelay, tclTimeClientData); + + /* add possible tolerance in percent, so "round" to full ms (-overhead) */ + vdelay.usec += vdelay.usec * (TMR_RES_TOLERANCE / 100); + /* No wait if sleep time too small (because windows may wait too long) */ + if (!vdelay.sec && vdelay.usec < (long)timerResolution.minDelay) { + sleepTime = 0; + goto wait; + } + + if (timerResolution.available) { + if (vdelay.sec || vdelay.usec > timerResolution.maxDelay) { + long usec; + sleepTime = vdelay.sec * 1000; + usec = ((sleepTime * 1000) + vdelay.usec) % 1000000; + sleepTime += (usec - (usec % timerResolution.maxDelay)) / 1000; + } else { + /* calculate resolution up to 1000 microseconds + * (don't use highest, because of too large CPU load) */ + ULONG res; + if (vdelay.usec >= 10000) { + res = 10000 * TMR_RES_MICROSEC; + } else { + res = 1000 * TMR_RES_MICROSEC; + } + sleepTime = vdelay.usec / 1000; + /* set more precise timer resolution for minimal delay */ + if (!actualResolution || res < timerResolution.curRes) { + actualResolution = SetTimerResolution( + res, actualResolution); + } + } + } else { + sleepTime = vdelay.sec * 1000 + vdelay.usec / 1000; + } + + wait: Sleep(sleepTime); Tcl_GetTime(&now); if (now.sec > desired.sec) { @@ -875,9 +922,15 @@ Tcl_Sleep( vdelay.sec = desired.sec - now.sec; vdelay.usec = desired.usec - now.usec; + if (vdelay.usec < 0) { + vdelay.sec--; + vdelay.usec += 1000000; + } + } - (*tclScaleTimeProcPtr) (&vdelay, tclTimeClientData); - sleepTime = vdelay.sec * 1000 + vdelay.usec / 1000; + /* restore timer resolution */ + if (actualResolution) { + RestoreTimerResolution(actualResolution); } } |