diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2022-04-18 21:10:57 +0300 |
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2022-04-21 12:12:38 +0300 |
| commit | 7967a9ab13214543041e4408086668b4db8d3e62 (patch) | |
| tree | 4dab7b89bd9d5b5b8280877f9d8eb23a1edf1230 /common/timer.c | |
| parent | 1ceed7525272b82c1028ebd353e65c3a63bd2714 (diff) | |
| download | kmi-7967a9ab13214543041e4408086668b4db8d3e62.tar.gz kmi-7967a9ab13214543041e4408086668b4db8d3e62.zip | |
start working on timer subsys
Diffstat (limited to 'common/timer.c')
| -rw-r--r-- | common/timer.c | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/common/timer.c b/common/timer.c new file mode 100644 index 0000000..b48e455 --- /dev/null +++ b/common/timer.c @@ -0,0 +1,124 @@ +#include <apos/sp_tree.h> +#include <apos/string.h> +#include <apos/nodes.h> +#include <apos/utils.h> +#include <apos/timer.h> +#include <arch/timer.h> +#include <arch/cpu.h> + +static ticks_t ticks_per_sec = 0; +static struct sp_root cpu_timers[MAX_CPUS] = {0}; +static struct node_root node_root; + +struct timer_node { + struct sp_node sp_n; + struct timer timer; +}; + +#define timer_container(ptr)\ + container_of(ptr, struct timer_node, sp_n) + +#define timer_node_container(ptr)\ + container_of(ptr, struct timer_node, timer) + +static struct sp_root *__cpu_timers() +{ + return &cpu_timers[cpu_id()]; +} + +void init_timer() +{ + ticks_per_sec = stat_timer(); + init_nodes(&node_root, sizeof(struct timer_node)); +} + +static id_t __insert_timer(struct timer_node *ti) +{ + struct sp_root *root = __cpu_timers(); + struct sp_node *n = sp_root(root), *p = NULL; + enum sp_dir d; + while (n) { + struct timer_node *t = container_of(n, struct timer_node, sp_n); + if (ti->timer.cid == t->timer.cid) + ti->timer.cid--; + + p = n; + + if (ti->timer.cid < t->timer.cid) { + n = sp_left(n); + d = LEFT; + } else { + n = sp_right(n); + d = RIGHT; + } + } + + if (sp_root(root)) + sp_insert(&sp_root(root), p, &ti->sp_n, d); + else + sp_root(root) = &ti->sp_n; + + return ti->timer.cid; +} + +/* ticks is absolute */ +static id_t __new_timer(id_t tid, ticks_t ticks) +{ + struct timer_node *ti = (struct timer_node *)get_node(&node_root); + ti->timer.ticks = ticks; + ti->timer.cid = ticks; + ti->timer.tid = tid; + return __insert_timer(ti); +} + +/* these are likely not perfectly accurate timers due to some random delay from + * function calls etc, but probably good enough. */ +id_t new_rel_timer(id_t tid, ticks_t ticks) +{ + return new_abs_timer(tid, ticks + current_ticks()); +} + +id_t new_abs_timer(id_t tid, ticks_t ticks) +{ + id_t id = __new_timer(tid, ticks); + set_timer(ticks); + return id; +} + +struct timer *newest_timer() +{ + struct sp_node *t = sp_first(sp_root(__cpu_timers())); + return &timer_container(t)->timer; +} + +struct timer *find_timer(id_t cid) +{ + struct sp_node *n = sp_root(__cpu_timers()); + while (n) { + struct timer_node *t = timer_container(n); + if (t->timer.cid == cid) + return &t->timer; + + if (t->timer.cid < cid) + n = sp_left(n); + else + n = sp_right(n); + } + + return 0; +} + +void remove_timer(struct timer *t) +{ + if (!t) + return; + + struct sp_node *n = &timer_node_container(t)->sp_n; + sp_remove(&sp_root(__cpu_timers()), n); +} + +/* TODO: does this overflow too early? */ +ticks_t nsecs_to_ticks(tunit_t nsecs) +{ + return (nsecs * ticks_per_sec) / 1000000000; +} |
