From d18e0e332fedde28587e8396a7f3be13c693c313 Mon Sep 17 00:00:00 2001 From: Matheus Date: Sun, 23 Apr 2023 16:48:58 -0300 Subject: [PATCH] kernel: initial timer abstraction --- kernel-src/include/kernel/timer.h | 26 +++++++++++ kernel-src/sys/timer.c | 73 +++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 kernel-src/include/kernel/timer.h create mode 100644 kernel-src/sys/timer.c diff --git a/kernel-src/include/kernel/timer.h b/kernel-src/include/kernel/timer.h new file mode 100644 index 00000000..59a833b1 --- /dev/null +++ b/kernel-src/include/kernel/timer.h @@ -0,0 +1,26 @@ +#ifndef _TIMER_H +#define _TIMER_H + +#include +#include + +typedef struct timerentry_t { + struct timerentry_t *next; + time_t absolutetick; + void *private; + void (*func)(void *private, context_t* context); +} timerentry_t; + +typedef struct { + time_t ticksperus; + time_t tickcurrent; + void (*arm)(time_t); + time_t (*stop)(); + timerentry_t *queue; +} timer_t; + +void timer_isr(timer_t *timer, context_t *context); +void timer_insert(timer_t *timer, timerentry_t *entry, time_t us); +timer_t *timer_new(time_t ticksperus, void (*arm)(time_t), time_t (*stop)()); + +#endif diff --git a/kernel-src/sys/timer.c b/kernel-src/sys/timer.c new file mode 100644 index 00000000..deb7865b --- /dev/null +++ b/kernel-src/sys/timer.c @@ -0,0 +1,73 @@ +#include +#include +#include +#include + +void timer_isr(timer_t *timer, context_t *context) { + // TODO 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); + } + + // TODO unlock + oldentry->func(oldentry->private, context); +} + +void timer_insert(timer_t *timer, timerentry_t* entry, time_t us) { + long oldipl = interrupt_setipl(IPL_TIMER); + // TODO lock + + timer->tickcurrent += timer->stop(timer); + + time_t tickdiff = us * timer->ticksperus; + entry->absolutetick = timer->tickcurrent + tickdiff; + + 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 + entry->next = timer->queue; + timer->queue = entry; + } else { + timerentry_t *search = timer->queue; + + while(search) { + if (search->next == NULL) { // if last entry in the queue + entry->next = NULL; + search->next = entry; + break; + } else if (entry->absolutetick >= search->absolutetick && search->next->absolutetick > entry->absolutetick) { // insert between two + entry->next = search->next; + search->next = entry; + break; + } + search = search->next; + } + } + + // TODO handle this case properly + __assert(timer->queue->absolutetick > timer->tickcurrent); + timer->arm(timer->queue->absolutetick - timer->tickcurrent); + + // TODO unlock + interrupt_setipl(oldipl); +} + +timer_t *timer_new(time_t ticksperus, void (*arm)(time_t), time_t (*stop)()) { + timer_t *timer = alloc(sizeof(timer_t)); + if (timer == NULL) + return NULL; + + timer->ticksperus = ticksperus; + timer->arm = arm; + timer->stop = stop; + + return timer; +}