diff options
author | Nicholas Piggin <npiggin@gmail.com> | 2025-03-31 22:46:31 +1000 |
---|---|---|
committer | Reza Arbab <arbab@linux.ibm.com> | 2025-04-18 09:42:50 -0500 |
commit | 9659d1293dda992ade58b9a5ed04405581758841 (patch) | |
tree | 7b11d4169947942445a79e18e8b6746141762529 /core | |
parent | 19222e56ae4eb9a1f8f62a3236dc71fde529eb07 (diff) | |
download | skiboot-9659d1293dda992ade58b9a5ed04405581758841.zip skiboot-9659d1293dda992ade58b9a5ed04405581758841.tar.gz skiboot-9659d1293dda992ade58b9a5ed04405581758841.tar.bz2 |
core/timers: Try to process all poll timers
Poll timers are not delay based and have no kind of ordering, so
processing does not have to stop if a busy timer is encountered.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Reza Arbab <arbab@linux.ibm.com>
Diffstat (limited to 'core')
-rw-r--r-- | core/timer.c | 20 |
1 files changed, 12 insertions, 8 deletions
diff --git a/core/timer.c b/core/timer.c index 21e7f5a..ecdcbb5 100644 --- a/core/timer.c +++ b/core/timer.c @@ -32,7 +32,6 @@ static struct lock timer_lock = LOCK_UNLOCKED; static LIST_HEAD(timer_list); static LIST_HEAD(timer_poll_list); static bool timer_in_poll; -static uint64_t timer_poll_gen; static inline bool this_cpu_is_running_timer(void) { @@ -128,7 +127,6 @@ static void __schedule_timer_at(struct timer *t, uint64_t when) if (when == TIMER_POLL) { /* It's a poller, add it to the poller list */ - t->gen = timer_poll_gen; list_add_tail(&timer_poll_list, &t->link); } else { /* It's a real timer, add it in the right spot in the @@ -174,12 +172,17 @@ uint64_t schedule_timer(struct timer *t, uint64_t how_long) static void __check_poll_timers(uint64_t now) { struct timer *t; + struct list_head list; /* Don't call this from multiple CPUs at once */ if (timer_in_poll) return; timer_in_poll = true; + /* Move all poll timers to a private list */ + list_head_init(&list); + list_append_list(&list, &timer_poll_list); + /* * Poll timers might re-enqueue themselves and don't have an * expiry so we can't do like normal timers and just run until @@ -191,22 +194,23 @@ static void __check_poll_timers(uint64_t now) * because at boot, this can be called quite quickly and I want * to be safe vs. wraps. */ - timer_poll_gen++; for (;;) { - t = list_top(&timer_poll_list, struct timer, link); + t = list_top(&list, struct timer, link); /* Top timer has a different generation than current ? Must * be older, we are done. */ - if (!t || t->gen == timer_poll_gen) + if (!t) break; - /* Top of list still running, we have to delay handling * it. Just skip until the next poll. */ - if (t->running) - break; + if (t->running) { + list_del(&t->link); + list_add_tail(&timer_poll_list, &t->link); + continue; + } /* Allright, first remove it and mark it running */ __remove_timer(t); |