From 16f1823897f608ecd268872707603aec123db8a9 Mon Sep 17 00:00:00 2001 From: Matheus Date: Thu, 27 Apr 2023 23:33:55 -0300 Subject: [PATCH] timer: repeat support and running status --- kernel-src/include/kernel/timer.h | 3 + kernel-src/sys/timer.c | 119 +++++++++++++++++------------- 2 files changed, 72 insertions(+), 50 deletions(-) diff --git a/kernel-src/include/kernel/timer.h b/kernel-src/include/kernel/timer.h index 53eafbe4..ecb148aa 100644 --- a/kernel-src/include/kernel/timer.h +++ b/kernel-src/include/kernel/timer.h @@ -4,10 +4,12 @@ #include #include #include +#include typedef struct timerentry_t { struct timerentry_t *next; time_t absolutetick; + time_t repeatus; void *private; void (*func)(void *private, context_t* context); } timerentry_t; @@ -16,6 +18,7 @@ typedef struct { spinlock_t lock; time_t ticksperus; time_t tickcurrent; + bool running; void (*arm)(time_t); time_t (*stop)(); timerentry_t *queue; diff --git a/kernel-src/sys/timer.c b/kernel-src/sys/timer.c index b74cc85c..410bc2e1 100644 --- a/kernel-src/sys/timer.c +++ b/kernel-src/sys/timer.c @@ -3,60 +3,13 @@ #include #include -void timer_isr(timer_t *timer, context_t *context) { - spinlock_acquire(&timer->lock); - __assert(timer->queue); - timer->tickcurrent = timer->queue->absolutetick; - timerentry_t *oldentry = timer->queue; - timer->queue = timer->queue->next; - - if (timer->queue) { - // TODO handle this - __assert(timer->queue->absolutetick > timer->tickcurrent); - timer->arm(timer->queue->absolutetick - timer->tickcurrent); - } - - spinlock_release(&timer->lock); - oldentry->func(oldentry->private, context); -} - -void timer_resume(timer_t *timer) { - spinlock_acquire(&timer->lock); - - if (timer->queue == NULL) - goto leave; - - // TODO handle difference being 0 - __assert(timer->queue->absolutetick > timer->tickcurrent); - timer->arm(timer->queue->absolutetick - timer->tickcurrent); - - leave: - spinlock_release(&timer->lock); -} - -void timer_stop(timer_t *timer) { - long oldipl = interrupt_setipl(IPL_TIMER); - spinlock_acquire(&timer->lock); - - timer->tickcurrent += timer->stop(timer); - - spinlock_release(&timer->lock); - interrupt_setipl(oldipl); -} - -void timer_insert(timer_t *timer, timerentry_t* entry, time_t us) { - long oldipl = interrupt_setipl(IPL_TIMER); - spinlock_acquire(&timer->lock); - - timer->tickcurrent += timer->stop(timer); - - time_t tickdiff = us * timer->ticksperus; - entry->absolutetick = timer->tickcurrent + tickdiff; +static void insert(timer_t *timer, timerentry_t *entry, time_t us) { + entry->absolutetick = timer->tickcurrent + us * timer->ticksperus; if (timer->queue == NULL) { // if no other entries in the queue entry->next = NULL; timer->queue = entry; - }else if (timer->queue->absolutetick > entry->absolutetick) { // if the current entry should be put before all the others in the queue + } else if (timer->queue->absolutetick > entry->absolutetick) { // if the current entry should be put before all the others in the queue entry->next = timer->queue; timer->queue = entry; } else { @@ -75,6 +28,71 @@ void timer_insert(timer_t *timer, timerentry_t* entry, time_t us) { search = search->next; } } +} + +void timer_isr(timer_t *timer, context_t *context) { + spinlock_acquire(&timer->lock); + + __assert(timer->queue); + timer->tickcurrent = timer->queue->absolutetick; + timerentry_t *oldentry = timer->queue; + timer->queue = timer->queue->next; + + oldentry->func(oldentry->private, context); + + if (oldentry->repeatus) + insert(timer, oldentry, oldentry->repeatus); + + if (timer->queue) { + // TODO handle this + __assert(timer->queue->absolutetick > timer->tickcurrent); + timer->arm(timer->queue->absolutetick - timer->tickcurrent); + } + + spinlock_release(&timer->lock); +} + +void timer_resume(timer_t *timer) { + spinlock_acquire(&timer->lock); + + timer->running = true; + + if (timer->queue == NULL) + goto leave; + + // TODO handle difference being 0 + __assert(timer->queue->absolutetick > timer->tickcurrent); + timer->arm(timer->queue->absolutetick - timer->tickcurrent); + + leave: + spinlock_release(&timer->lock); +} + +void timer_stop(timer_t *timer) { + long oldipl = interrupt_setipl(IPL_TIMER); + spinlock_acquire(&timer->lock); + + timer->tickcurrent += timer->stop(timer); + timer->running = false; + + spinlock_release(&timer->lock); + interrupt_setipl(oldipl); +} + +void timer_insert(timer_t *timer, timerentry_t* entry, time_t us) { + long oldipl = interrupt_setipl(IPL_TIMER); + spinlock_acquire(&timer->lock); + + if (timer->running) + timer->tickcurrent += timer->stop(timer); + + insert(timer, entry, us); + + if (timer->running) { + // TODO handle difference being 0 + __assert(timer->queue->absolutetick > timer->tickcurrent); + timer->arm(timer->queue->absolutetick - timer->tickcurrent); + } spinlock_release(&timer->lock); interrupt_setipl(oldipl); @@ -86,6 +104,7 @@ timer_t *timer_new(time_t ticksperus, void (*arm)(time_t), time_t (*stop)()) { return NULL; timer->ticksperus = ticksperus; + timer->running = false; timer->arm = arm; timer->stop = stop; SPINLOCK_INIT(timer->lock);