summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsebres <sebres@users.sourceforge.net>2017-07-03 13:25:25 (GMT)
committersebres <sebres@users.sourceforge.net>2017-07-03 13:25:25 (GMT)
commit1b814ecdc54b17f604790d2242e3249dbf38d068 (patch)
treef1e75eae8f373aadade5ba5766cccec585061636
parentfdc24c5c31c074dce2539aad1c9cc7facb565099 (diff)
downloadtcl-1b814ecdc54b17f604790d2242e3249dbf38d068.zip
tcl-1b814ecdc54b17f604790d2242e3249dbf38d068.tar.gz
tcl-1b814ecdc54b17f604790d2242e3249dbf38d068.tar.bz2
[win32] use timer resolution handling in Tcl_Sleep also;
-rw-r--r--generic/tclTimer.c22
-rw-r--r--win/tclWinNotify.c73
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);
}
}