diff options
author | mzuther <mzuther@3ae390bd-cb1e-0410-b409-cd5a39f66f1f> | 2011-01-23 17:01:08 +0000 |
---|---|---|
committer | mzuther <mzuther@3ae390bd-cb1e-0410-b409-cd5a39f66f1f> | 2011-01-23 17:01:08 +0000 |
commit | c15760b9e502d12e4905ef898e9694436ec3bde3 (patch) | |
tree | f8497d464654c9a597ba626a57df1ea2b073cac5 | |
parent | 72e1f7501bd6806022b7a33e1424ea2cc7fa4059 (diff) | |
download | lcd4linux-c15760b9e502d12e4905ef898e9694436ec3bde3.tar.gz |
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
-rw-r--r-- | drv_PICGraphic.c | 2 | ||||
-rw-r--r-- | timer.c | 60 |
2 files changed, 46 insertions, 16 deletions
diff --git a/drv_PICGraphic.c b/drv_PICGraphic.c index 8586eb6..c33973d 100644 --- a/drv_PICGraphic.c +++ b/drv_PICGraphic.c @@ -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; @@ -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? */ |