timer.c: skip intermediate timer intervals

"timer_inc()" now checks how many trigger intervals have passed since
a given timer has been updated.  This might be due to "negative clock
skew" (think of summer time) or the fact that some processing took too
long (i.e. fetching of a web site).  These missed trigger intervals
are then skipped and the user is notified so that he may adapt his
timer settings.  This handling is essential, otherwise unprocessed
timers might stack up and would trigger continuously while at the same
time becoming notoriously late and unreliable.


git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@1141 3ae390bd-cb1e-0410-b409-cd5a39f66f1f
This commit is contained in:
mzuther
2011-01-23 17:01:08 +00:00
parent 72e1f7501b
commit c15760b9e5
2 changed files with 46 additions and 16 deletions
+1 -1
View File
@@ -203,7 +203,7 @@ static void drv_PICGraphic_blit(const int row, const int col, const int height,
delayDone = 0;
int row8, height8;
row8 = 8 * (row / 8);
height8 = 8 * (height / 8) + ! !(height % 8);
height8 = 8 * (height / 8) + !!(height % 8);
info("sending blit");
cmd[0] = 'b';
cmd[1] = row8;
+45 -15
View File
@@ -113,27 +113,57 @@ int nTimers = 0;
TIMER *Timers = NULL;
static void timer_inc(struct timeval *tv, const int interval)
/* Update a timer's trigger by adding the given interval.
static void timer_inc(const int timer, struct timeval *now)
/* Update the time a given timer updates next.
tv (timeval pointer): struct holding the last time the timer has
been processed
timer (integer): internal ID of timer that is to be updated
interval (integer): interval in milliseconds to be added to the
the last time the timer has been processed
now (timeval pointer): struct holding the "current" time
return value: void
*/
{
/* split time interval to be added (given in milliseconds) into
microseconds and seconds */
struct timeval diff = {
/* calculate the time difference between the last time the given
timer has been processed and the current time */
struct timeval diff;
timersub(now, &Timers[timer].when, &diff);
/* convert this time difference to fractional seconds */
float fDiff = diff.tv_sec + diff.tv_usec / 1000000.0f;
/* convert time difference to fractional milliseconds */
fDiff = fDiff * 1000.0f;
/* calculate the number of timer intervals that have passed since
the last timer the given timer has been processed -- value is
truncated (rounded down) to an integer */
int number_of_intervals = (int) (fDiff / Timers[timer].interval);
/* notify the user in case one or more timer intervals have been
missed */
if (number_of_intervals > 0)
info("Timer #%d skipped %d interval(s) or %d ms.", timer, number_of_intervals,
number_of_intervals * Timers[timer].interval);
/* increment the number of passed intervals in order to skip all
missed intervals -- thereby avoiding that unprocessed timers
stack up, continuously update and are notoriously late (certain
railway companies might learn a lesson from us <g>) */
number_of_intervals++;
/* calculate time difference between the last time the timer has
been processed and the next time it will be processed */
int interval = Timers[timer].interval * number_of_intervals;
/* convert time difference (in milliseconds) to a "timeval"
structure (in seconds and microseconds) */
struct timeval tv_interval = {
.tv_sec = interval / 1000,
.tv_usec = (interval % 1000) * 1000
};
/* add interval to timer and store the result in the timer */
timeradd(tv, &diff, tv);
/* finally, add time difference to the timer's trigger */
timeradd(&Timers[timer].when, &tv_interval, &Timers[timer].when);
}
@@ -249,7 +279,7 @@ int timer_add(void (*callback) (void *data), void *data, const int interval, con
/* one-shot timers should NOT fire immediately, so delay them by a
single timer interval */
if (one_shot) {
timer_inc(&Timers[timer].when, interval);
timer_inc(timer, &now);
}
/* signal successful timer creation */
@@ -365,9 +395,9 @@ int timer_process(struct timespec *delay)
been deleted and its allocated memory may be re-used) */
Timers[timer].active = 0;
} else {
/* otherwise, respawn timer by adding one triggering interval
/* otherwise, re-spawn timer by adding one triggering interval
to its triggering time */
timer_inc(&Timers[timer].when, Timers[timer].interval);
timer_inc(timer, &now);
}
}
}
@@ -428,7 +458,7 @@ int timer_process(struct timespec *delay)
timerclear(&diff);
/* display an info message to inform the user */
info("Oops, clock skewed, update timestamp");
info("Oops, clock skewed, update time stamp");
/* update time stamp and timer */
/* FIXME: shouldn't we update *all* timers? */