aboutsummaryrefslogtreecommitdiffstats
path: root/src/sched.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sched.c')
-rw-r--r--src/sched.c38
1 files changed, 29 insertions, 9 deletions
diff --git a/src/sched.c b/src/sched.c
index eb35bc8e..19e428be 100644
--- a/src/sched.c
+++ b/src/sched.c
@@ -19,21 +19,41 @@
static uint16_t millis;
+static struct timer ms_timer, sentinel_timer;
+
// Default millisecond timer. This timer counts milliseconds. It
-// also simplifies the timer code by ensuring there is always at least
-// one timer on the timer list and that there is always a timer not
-// more than 1 ms in the future.
+// also simplifies the timer code by ensuring there is always a timer
+// on the timer list and that there is always a timer not more than
+// 1ms in the future.
static uint_fast8_t
ms_event(struct timer *t)
{
millis++;
timer_periodic();
- t->waketime += sched_from_us(1000);
+ ms_timer.waketime += sched_from_us(1000);
+ sentinel_timer.waketime = ms_timer.waketime + 0x80000000;
return SF_RESCHEDULE;
}
static struct timer ms_timer = {
- .func = ms_event
+ .func = ms_event,
+ .next = &sentinel_timer,
+};
+
+// The sentinel timer is always the last timer on timer_list - its
+// presence allows the code to avoid checking for NULL while
+// traversing timer_list. Since sentinel_timer.waketime is always
+// equal to (ms_timer.waketime + 0x80000000) any added timer must
+// always have a waketime less than one of these two timers.
+static uint_fast8_t
+sentinel_event(struct timer *t)
+{
+ shutdown("sentinel timer called");
+}
+
+static struct timer sentinel_timer = {
+ .func = sentinel_event,
+ .waketime = 0x80000000,
};
// Check if ready for a recurring periodic event
@@ -91,7 +111,7 @@ sched_timer(struct timer *add)
} else {
// Find position in list and insert
struct timer *pos = timer_list;
- while (pos->next && !sched_is_before(waketime, pos->next->waketime))
+ while (!sched_is_before(waketime, pos->next->waketime))
pos = pos->next;
add->next = pos->next;
pos->next = add;
@@ -128,7 +148,7 @@ reschedule_timer(struct timer *t)
{
struct timer *pos = t->next;
uint32_t minwaketime = t->waketime + 1;
- if (!pos || !sched_is_before(pos->waketime, minwaketime))
+ if (!sched_is_before(pos->waketime, minwaketime))
// Timer is still the first - no insertion needed
return t;
@@ -141,7 +161,7 @@ reschedule_timer(struct timer *t)
// micro optimization for AVR - reduces register pressure
asm("" : "+r"(prev) : : "memory");
pos = pos->next;
- if (!pos || !sched_is_before(pos->waketime, minwaketime))
+ if (!sched_is_before(pos->waketime, minwaketime))
break;
}
t->next = pos;
@@ -180,7 +200,7 @@ static void
timer_shutdown(void)
{
timer_list = &ms_timer;
- ms_timer.next = NULL;
+ ms_timer.next = &sentinel_timer;
timer_set_next(timer_list->waketime);
}
DECL_SHUTDOWN(timer_shutdown);