]> git.webhop.me Git - lcd4linux.git/commitdiff
timer.c: skip intermediate timer intervals
authormzuther <mzuther@3ae390bd-cb1e-0410-b409-cd5a39f66f1f>
Sun, 23 Jan 2011 17:01:08 +0000 (17:01 +0000)
committermzuther <mzuther@3ae390bd-cb1e-0410-b409-cd5a39f66f1f>
Sun, 23 Jan 2011 17:01:08 +0000 (17:01 +0000)
"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

drv_PICGraphic.c
timer.c

index 8586eb60ed145209952052370c79d0293db1b041..c33973da0363d787919c9658679807124785525d 100644 (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;
diff --git a/timer.c b/timer.c
index 5dbb379802fd7758d6cb85e8698b7b1050a0b5ff..bd7eeb0fa8c3d07882cde0b20655b60a9b38b316 100644 (file)
--- a/timer.c
+++ b/timer.c
@@ -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? */