From 1eaac15cdb220df7536c74774a1ce7d1f0519c63 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Sat, 24 Jan 2026 22:34:12 +0200 Subject: improve timer handling + Previous code assumed a timer would only trigger when requested, but didn't explicitly disable timers during init. Newer versions of qemu (>= 10?) seem to have some kind of timer set, unsure if that's via OpenSBI or what exactly but some slower tests were failing because of it. --- src/timer.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) (limited to 'src/timer.c') diff --git a/src/timer.c b/src/timer.c index 5583cd3..5b3ac86 100644 --- a/src/timer.c +++ b/src/timer.c @@ -73,6 +73,7 @@ static struct sp_root *__cpu_timers() void init_timer(const void *fdt) { + clear_timer(); ticks_per_sec = stat_timer(fdt); info("ticks_per_sec: %" PRIu64 "\n", ticks_per_sec); info("current ticks: %" PRIu64 "\n", current_ticks()); @@ -151,14 +152,23 @@ id_t new_rel_timer(id_t tid, ticks_t ticks) id_t new_abs_timer(id_t tid, ticks_t ticks) { + /* if there are no active timers or this timer is before the next active + * timer, start the hardware timer */ + struct timer *t = newest_timer(); + if (!t || ticks < t->ticks) + set_timer(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())); + struct sp_node *r = sp_root(__cpu_timers()); + if (!r) + return NULL; + + struct sp_node *t = sp_first(r); return &timer_container(t)->timer; } @@ -202,9 +212,25 @@ void handle_timer() /** @todo should this also disable irqs? */ bkl_lock(); struct timer *t = newest_timer(); + if (!t) { + info("spurious timer\n"); + clear_timer(); + bkl_unlock(); + return; + } + id_t tid = t->tid; remove_timer(t); + + /* maybe schedule next timer event, maybe disable timer so we don't + * start infinitely retrigger the timer interrupt */ + t = newest_timer(); + if (t) + set_timer(t->ticks); + else + clear_timer(); + struct tcb *r = get_tcb(tid); if (!r || orphan(r)) { info("tcb %llu dead at timer\n", @@ -213,6 +239,7 @@ void handle_timer() return; } + /** @todo check that timer didn't trigger before scheduled time? */ notify(r, NOTIFY_TIMER); bkl_unlock(); } -- cgit v1.3