[Skiboot] [PATCH 5/9] core/timers: Try to process all poll timers

Nicholas Piggin npiggin at gmail.com
Mon Mar 31 23:46:31 AEDT 2025


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 at gmail.com>
---
 core/timer.c    | 22 +++++++++++++---------
 include/timer.h |  1 -
 2 files changed, 13 insertions(+), 10 deletions(-)

diff --git a/core/timer.c b/core/timer.c
index 21e7f5a83..3e888effa 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)
-			break;
-
+		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);
diff --git a/include/timer.h b/include/timer.h
index d19053277..7c5a7cf5b 100644
--- a/include/timer.h
+++ b/include/timer.h
@@ -27,7 +27,6 @@ struct timer {
 	timer_func_t		expiry;
 	void *			user_data;
 	void *			running;
-	uint64_t		gen;
 };
 
 extern void init_timer(struct timer *t, timer_func_t expiry, void *data);
-- 
2.47.1



More information about the Skiboot mailing list