]> git.webhop.me Git - lcd4linux.git/commitdiff
timer.c: fixed clock skew detection
authormzuther <mzuther@3ae390bd-cb1e-0410-b409-cd5a39f66f1f>
Sun, 23 Jan 2011 22:45:46 +0000 (22:45 +0000)
committermzuther <mzuther@3ae390bd-cb1e-0410-b409-cd5a39f66f1f>
Sun, 23 Jan 2011 22:45:46 +0000 (22:45 +0000)
git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@1142 3ae390bd-cb1e-0410-b409-cd5a39f66f1f

timer.c

diff --git a/timer.c b/timer.c
index bd7eeb0fa8c3d07882cde0b20655b60a9b38b316..d4545cbdb1f678c7d8256da08fb026ec918ac4ca 100644 (file)
--- a/timer.c
+++ b/timer.c
 #include <dmalloc.h>
 #endif
 
-/* FIXME: CLOCK_SKEW_DETECT_TIME_IN_S should have a higher value */
-
-/* delay in seconds between timer events that is considered as being
-   induced by clock skew */
-#define CLOCK_SKEW_DETECT_TIME_IN_S 1
+/* threshold in milliseconds that differentiates between clock skew
+   and clock jitter */
+#define CLOCK_SKEW_DETECT_TIME_IN_MS 1000
 
 /* structure for storing all relevant data of a single timer */
 typedef struct TIMER {
@@ -129,15 +127,15 @@ static void timer_inc(const int timer, struct timeval *now)
     timersub(now, &Timers[timer].when, &diff);
 
     /* convert this time difference to fractional seconds */
-    float fDiff = diff.tv_sec + diff.tv_usec / 1000000.0f;
+    float time_difference = diff.tv_sec + diff.tv_usec / 1000000.0f;
 
     /* convert time difference to fractional milliseconds */
-    fDiff = fDiff * 1000.0f;
+    time_difference = time_difference * 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);
+    int number_of_intervals = (int) (time_difference / Timers[timer].interval);
 
     /* notify the user in case one or more timer intervals have been
        missed */
@@ -156,7 +154,7 @@ static void timer_inc(const int timer, struct timeval *now)
     int interval = Timers[timer].interval * number_of_intervals;
 
     /* convert time difference (in milliseconds) to a "timeval"
-       structure (in seconds and microseconds) */
+       struct (in seconds and microseconds) */
     struct timeval tv_interval = {
        .tv_sec = interval / 1000,
        .tv_usec = (interval % 1000) * 1000
@@ -445,28 +443,50 @@ int timer_process(struct timespec *delay)
        in "diff" */
     timersub(&Timers[next_timer].when, &now, &diff);
 
-    /* for negative delays, set "diff" to the Epoch so the next update
-       is triggered immediately */
-    if (diff.tv_sec < 0)
-       timerclear(&diff);
+    /* convert "diff" to milliseconds */
+    int time_difference = (diff.tv_sec * 1000.0f) + (diff.tv_usec / 1000.0f);
 
-    /* check whether the delay in "diff" has been induced by clock
-       skew */
-    if (diff.tv_sec > CLOCK_SKEW_DETECT_TIME_IN_S) {
-       /* set "diff" to the Epoch so the next update is triggered
-          directly */
+    /* a notable negative delay has occurred (positive clock skew or
+       some timers are faster than the time needed for processing
+       their callbacks) */
+    if (time_difference < (-CLOCK_SKEW_DETECT_TIME_IN_MS)) {
+       /* zero "diff" so the next update is triggered immediately */
        timerclear(&diff);
+    } else {
+       /* if there is a notable difference between "time_difference" and
+          the next upcoming timer's interval, assume clock skew */
+       if (time_difference > (Timers[next_timer].interval + CLOCK_SKEW_DETECT_TIME_IN_MS)) {
+           /* extract clock skew from "time_difference" by eliminating
+              the timer's triggering interval */
+           int skew = time_difference - Timers[next_timer].interval;
+
+           /* display an info message to inform the user */
+           info("Oops, clock skewed by %d ms, updating timestamps...", skew);
+
+           /* convert clock skew from milliseconds to "timeval"
+              structure */
+           struct timeval clock_skew = {
+               .tv_sec = skew / 1000,
+               .tv_usec = (skew % 1000) * 1000
+           };
+
+           /* process all timers */
+           for (timer = 0; timer < nTimers; timer++) {
+               /* skip inactive (i.e. deleted) timers */
+               if (Timers[timer].active == 0)
+                   continue;
+
+               /* correct timer's time stamp by clock skew */
+               timersub(&Timers[timer].when, &clock_skew, &Timers[timer].when);
+           }
 
-       /* display an info message to inform the user */
-       info("Oops, clock skewed, update time stamp");
-
-       /* update time stamp and timer */
-       /* FIXME: shouldn't we update *all* timers? */
-       gettimeofday(&now, NULL);
-       Timers[next_timer].when = now;
+           /* finally, zero "diff" so the next update is triggered
+              immediately */
+           timerclear(&diff);
+       }
     }
 
-    /* finally, set passed timespec "delay" to "diff" ... */
+    /* set timespec "delay" passed by calling function to "diff" */
     delay->tv_sec = diff.tv_sec;
     /* timespec uses nanoseconds instead of microseconds!!! */
     delay->tv_nsec = diff.tv_usec * 1000;