From 5fc9e5a4e36b3db234382289d81604df4d6c328b Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 20 Nov 2025 12:07:14 +1030 Subject: [PATCH] ccan: update to get io_loop fairness. This rotates through fds explicitly, to avoid unfairness. This doesn't really make a difference until we start using it. Signed-off-by: Rusty Russell --- ccan/README | 2 +- ccan/ccan/io/poll.c | 35 +++++++++++++++++++++++++---------- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/ccan/README b/ccan/README index 022df6bf6..8b589bc9e 100644 --- a/ccan/README +++ b/ccan/README @@ -1,3 +1,3 @@ CCAN imported from http://ccodearchive.net. -CCAN version: init-2605-gc47bf0d9 +CCAN version: init-2606-g5f219f03 diff --git a/ccan/ccan/io/poll.c b/ccan/ccan/io/poll.c index 7fe9e2c5e..656cc0e3a 100644 --- a/ccan/ccan/io/poll.c +++ b/ccan/ccan/io/poll.c @@ -373,6 +373,8 @@ static void restore_pollfds(void) void *io_loop(struct timers *timers, struct timer **expired) { void *ret; + /* This ensures we don't always service lower fds first */ + static int fairness_counter; /* if timers is NULL, expired must be. If not, not. */ assert(!timers == !expired); @@ -384,17 +386,12 @@ void *io_loop(struct timers *timers, struct timer **expired) while (!io_loop_return) { int i, r, ms_timeout = -1; - if (handle_always()) { - /* Could have started/finished more. */ - continue; - } - /* Everything closed? */ if (num_fds == 0) break; /* You can't tell them all to go to sleep! */ - assert(num_waiting); + assert(num_waiting || num_always); if (timers) { struct timemono now, first; @@ -417,6 +414,10 @@ void *io_loop(struct timers *timers, struct timer **expired) } } + /* Don't wait if we have always requests pending! */ + if (num_always != 0) + ms_timeout = 0; + /* We do this temporarily, assuming exclusive is unusual */ exclude_pollfds(); r = pollfn(pollfds, num_fds, ms_timeout); @@ -430,15 +431,29 @@ void *io_loop(struct timers *timers, struct timer **expired) break; } - for (i = 0; i < num_fds && !io_loop_return; i++) { - struct io_conn *c = (void *)fds[i]; - int events = pollfds[i].revents; + fairness_counter++; + for (size_t rotation = 0; rotation < num_fds && !io_loop_return; rotation++) { + struct io_conn *c; + int events; + + i = (rotation + fairness_counter) % num_fds; + c = (void *)fds[i]; /* Clear so we don't get confused if exclusive next time */ + events = pollfds[i].revents; pollfds[i].revents = 0; - if (r == 0) + /* Timeout? */ + if (r == 0) { + handle_always(); break; + } + + /* We interleave always before the first fd */ + if (i == 0 && handle_always()) { + /* Could have started/finished more. */ + break; + } if (fds[i]->listener) { struct io_listener *l = (void *)fds[i];