From 2ee6ff0cfd1ff418cd01b97af8139c85fc5bf60d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Lichtblau?= <Bjoern.Lichtblau@MSAsafety.com>
Date: Wed, 4 Mar 2015 13:52:19 +0100
Subject: [PATCH] sys/vtimer: Fix longterm_tick_timer handling.

Before, the longterm_tick_timer had special handling in update_shortterm.
This approach was bad because the longterm_tick_timer's shooting microseconds time
had different semantics like the rest and thus it could end up in a blocking
position in the priority queue at some point in time, although it should
get executed at another point in time.

Made the longterm_tick_timer handling / meaning of its microseconds the same
as the other timers and also removed seconds, because it is now the same
as longertm_tick_timer.absolute.seconds.

See also https://github.com/RIOT-OS/RIOT/pull/2515
---
 sys/vtimer/vtimer.c | 26 ++++++++------------------
 1 file changed, 8 insertions(+), 18 deletions(-)

diff --git a/sys/vtimer/vtimer.c b/sys/vtimer/vtimer.c
index 80a0256cf3..ea596c141f 100644
--- a/sys/vtimer/vtimer.c
+++ b/sys/vtimer/vtimer.c
@@ -69,8 +69,6 @@ static volatile int in_callback = false;
 static int hwtimer_id = -1;
 static uint32_t hwtimer_next_absolute;
 
-static uint32_t seconds = 0;
-
 static inline priority_queue_node_t *timer_get_node(vtimer_t *timer)
 {
     if (!timer) {
@@ -117,19 +115,12 @@ static int update_shortterm(void)
     /* short term part of the next vtimer */
     hwtimer_next_absolute = shortterm_priority_queue_root.first->priority;
 
-    uint32_t next = hwtimer_next_absolute;
+    uint32_t next = hwtimer_next_absolute + longterm_tick_start;
 
     /* current short term time */
     uint32_t now_ticks = hwtimer_now();
     uint32_t now = HWTIMER_TICKS_TO_US(now_ticks);
 
-    /* make sure the longterm_tick_timer does not get truncated */
-    if (node_get_timer(shortterm_priority_queue_root.first)->action != vtimer_callback_tick) {
-        /* the next vtimer to schedule is the long term tick */
-        /* it has a shortterm offset of longterm_tick_start */
-        next += longterm_tick_start;
-    }
-
     if((next -  HWTIMER_TICKS_TO_US(VTIMER_THRESHOLD) - now) > MICROSECONDS_PER_TICK ) {
         DEBUG("truncating next (next -  HWTIMER_TICKS_TO_US(VTIMER_THRESHOLD) - now): %lu\n", (next -  HWTIMER_TICKS_TO_US(VTIMER_THRESHOLD) - now));
         next = now +  HWTIMER_TICKS_TO_US(VTIMER_BACKOFF);
@@ -147,16 +138,16 @@ void vtimer_callback_tick(vtimer_t *timer)
     (void) timer;
 
     DEBUG("vtimer_callback_tick().\n");
-    seconds += SECONDS_PER_TICK;
 
-    longterm_tick_start = longterm_tick_timer.absolute.microseconds;
-    longterm_tick_timer.absolute.microseconds += MICROSECONDS_PER_TICK;
+    longterm_tick_start += MICROSECONDS_PER_TICK;
+    longterm_tick_timer.absolute.seconds += SECONDS_PER_TICK;
+    longterm_tick_timer.absolute.microseconds = MICROSECONDS_PER_TICK; // Should never change, just for clarity.
     set_shortterm(&longterm_tick_timer);
 
     while (longterm_priority_queue_root.first) {
         vtimer_t *timer = node_get_timer(longterm_priority_queue_root.first);
 
-        if (timer->absolute.seconds == seconds) {
+        if (timer->absolute.seconds == longterm_tick_timer.absolute.seconds) {
             priority_queue_remove_head(&longterm_priority_queue_root);
             set_shortterm(timer);
         }
@@ -264,7 +255,7 @@ static int vtimer_set(vtimer_t *timer)
     }
 
     unsigned state = disableIRQ();
-    if (timer->absolute.seconds != seconds) {
+    if (timer->absolute.seconds != longterm_tick_timer.absolute.seconds) {
         /* we're long-term */
         DEBUG("vtimer_set(): setting long_term\n");
         result = set_longterm(timer);
@@ -289,9 +280,9 @@ static int vtimer_set(vtimer_t *timer)
 void vtimer_now(timex_t *out)
 {
     uint32_t us = HWTIMER_TICKS_TO_US(hwtimer_now()) - longterm_tick_start;
-    uint32_t us_per_s = 1000ul * 1000ul;
+    static const uint32_t us_per_s = 1000ul * 1000ul;
 
-    out->seconds = seconds + us / us_per_s;
+    out->seconds = longterm_tick_timer.absolute.seconds + us / us_per_s;
     out->microseconds = us % us_per_s;
 }
 
@@ -319,7 +310,6 @@ int vtimer_init(void)
 {
     DEBUG("vtimer_init().\n");
     unsigned state = disableIRQ();
-    seconds = 0;
 
     longterm_tick_start = 0;
 
-- 
GitLab