WaitForSomething: allow time to rewind

If time rewinds dramatically, reset all the timers to fix their expiry.
This commit is contained in:
Daniel Stone 2006-10-25 23:55:43 +03:00 committed by Daniel Stone
parent becbda6d51
commit d3e57faffe

View File

@ -119,11 +119,13 @@ mffs(fd_mask mask)
struct _OsTimerRec { struct _OsTimerRec {
OsTimerPtr next; OsTimerPtr next;
CARD32 expires; CARD32 expires;
CARD32 delta;
OsTimerCallback callback; OsTimerCallback callback;
pointer arg; pointer arg;
}; };
static void DoTimer(OsTimerPtr timer, CARD32 now, OsTimerPtr *prev); static void DoTimer(OsTimerPtr timer, CARD32 now, OsTimerPtr *prev);
static void CheckAllTimers(CARD32 now);
static OsTimerPtr timers = NULL; static OsTimerPtr timers = NULL;
/***************** /*****************
@ -200,6 +202,11 @@ WaitForSomething(int *pClientsReady)
{ {
now = GetTimeInMillis(); now = GetTimeInMillis();
timeout = timers->expires - now; timeout = timers->expires - now;
/* time has rewound. reset the timers. */
if (timeout > timers->delta) {
CheckAllTimers(now);
timeout = timers->expires - now;
}
if (timeout < 0) if (timeout < 0)
timeout = 0; timeout = 0;
waittime.tv_sec = timeout / MILLI_PER_SECOND; waittime.tv_sec = timeout / MILLI_PER_SECOND;
@ -426,6 +433,20 @@ ANYSET(FdMask *src)
} }
#endif #endif
/* If time has rewound, re-run every affected timer.
* TimerForce will change timer->next, but it will _generally_ only
* promote timers in the list, meaning that we should still be
* walking every timer. */
static void
CheckAllTimers(CARD32 now)
{
OsTimerPtr timer;
for (timer = timers; timer; timer = timer->next) {
if (timer->expires - now > timer->delta)
TimerForce(timer);
}
}
static void static void
DoTimer(OsTimerPtr timer, CARD32 now, OsTimerPtr *prev) DoTimer(OsTimerPtr timer, CARD32 now, OsTimerPtr *prev)
@ -467,8 +488,13 @@ TimerSet(OsTimerPtr timer, int flags, CARD32 millis,
} }
if (!millis) if (!millis)
return timer; return timer;
if (!(flags & TimerAbsolute)) if (flags & TimerAbsolute) {
timer->delta = millis - now;
}
else {
timer->delta = millis;
millis += now; millis += now;
}
timer->expires = millis; timer->expires = millis;
timer->callback = func; timer->callback = func;
timer->arg = arg; timer->arg = arg;
@ -481,8 +507,10 @@ TimerSet(OsTimerPtr timer, int flags, CARD32 millis,
} }
for (prev = &timers; for (prev = &timers;
*prev && (int) ((*prev)->expires - millis) <= 0; *prev && (int) ((*prev)->expires - millis) <= 0;
prev = &(*prev)->next) prev = &(*prev)->next) {
; if ((*prev)->expires - now > (*prev)->delta)
CheckAllTimers(now);
}
timer->next = *prev; timer->next = *prev;
*prev = timer; *prev = timer;
return timer; return timer;