sched: Use a sentinel timer at the end of the timer_list
Introduce a dummy sentinel timer object that is always the last item on timer_list. This optimizes the timer_list walking code as it no longer needs to check for NULL when traversing the list. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
parent
16e3dbb18c
commit
cb286ede9d
38
src/sched.c
38
src/sched.c
|
@ -19,21 +19,41 @@
|
||||||
|
|
||||||
static uint16_t millis;
|
static uint16_t millis;
|
||||||
|
|
||||||
|
static struct timer ms_timer, sentinel_timer;
|
||||||
|
|
||||||
// Default millisecond timer. This timer counts milliseconds. It
|
// Default millisecond timer. This timer counts milliseconds. It
|
||||||
// also simplifies the timer code by ensuring there is always at least
|
// also simplifies the timer code by ensuring there is always a timer
|
||||||
// one timer on the timer list and that there is always a timer not
|
// on the timer list and that there is always a timer not more than
|
||||||
// more than 1 ms in the future.
|
// 1ms in the future.
|
||||||
static uint_fast8_t
|
static uint_fast8_t
|
||||||
ms_event(struct timer *t)
|
ms_event(struct timer *t)
|
||||||
{
|
{
|
||||||
millis++;
|
millis++;
|
||||||
timer_periodic();
|
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;
|
return SF_RESCHEDULE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct timer ms_timer = {
|
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
|
// Check if ready for a recurring periodic event
|
||||||
|
@ -91,7 +111,7 @@ sched_timer(struct timer *add)
|
||||||
} else {
|
} else {
|
||||||
// Find position in list and insert
|
// Find position in list and insert
|
||||||
struct timer *pos = timer_list;
|
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;
|
pos = pos->next;
|
||||||
add->next = pos->next;
|
add->next = pos->next;
|
||||||
pos->next = add;
|
pos->next = add;
|
||||||
|
@ -128,7 +148,7 @@ reschedule_timer(struct timer *t)
|
||||||
{
|
{
|
||||||
struct timer *pos = t->next;
|
struct timer *pos = t->next;
|
||||||
uint32_t minwaketime = t->waketime + 1;
|
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
|
// Timer is still the first - no insertion needed
|
||||||
return t;
|
return t;
|
||||||
|
|
||||||
|
@ -141,7 +161,7 @@ reschedule_timer(struct timer *t)
|
||||||
// micro optimization for AVR - reduces register pressure
|
// micro optimization for AVR - reduces register pressure
|
||||||
asm("" : "+r"(prev) : : "memory");
|
asm("" : "+r"(prev) : : "memory");
|
||||||
pos = pos->next;
|
pos = pos->next;
|
||||||
if (!pos || !sched_is_before(pos->waketime, minwaketime))
|
if (!sched_is_before(pos->waketime, minwaketime))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
t->next = pos;
|
t->next = pos;
|
||||||
|
@ -180,7 +200,7 @@ static void
|
||||||
timer_shutdown(void)
|
timer_shutdown(void)
|
||||||
{
|
{
|
||||||
timer_list = &ms_timer;
|
timer_list = &ms_timer;
|
||||||
ms_timer.next = NULL;
|
ms_timer.next = &sentinel_timer;
|
||||||
timer_set_next(timer_list->waketime);
|
timer_set_next(timer_list->waketime);
|
||||||
}
|
}
|
||||||
DECL_SHUTDOWN(timer_shutdown);
|
DECL_SHUTDOWN(timer_shutdown);
|
||||||
|
|
Loading…
Reference in New Issue