From f015887444bb866397e1963457306027cac0e537 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Fri, 25 Sep 2020 12:18:53 +0200 Subject: [PATCH] MEDIUM: fd: always wake up one thread when enabling a foreing FD Since 2.2 it's safe to enable/disable another thread's FD but the fd_wake calls will not immediately be considered because nothing wakes the other threads up. This will have an impact on listeners when deciding to resume them after they were paused, so at minima we want to wake up one of their threads, just like the scheduler does on task_kill(). This is what this patch does. --- src/fd.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/fd.c b/src/fd.c index d05df58..2c1dcef 100644 --- a/src/fd.c +++ b/src/fd.c @@ -407,9 +407,19 @@ void updt_fd_polling(const int fd) do { if (update_mask == fdtab[fd].thread_mask) return; - } while (!_HA_ATOMIC_CAS(&fdtab[fd].update_mask, &update_mask, - fdtab[fd].thread_mask)); + } while (!_HA_ATOMIC_CAS(&fdtab[fd].update_mask, &update_mask, fdtab[fd].thread_mask)); + fd_add_to_fd_list(&update_list, fd, offsetof(struct fdtab, update)); + + if (fd_active(fd) && + !(fdtab[fd].thread_mask & tid_bit) && + (fdtab[fd].thread_mask & ~tid_bit & all_threads_mask & ~sleeping_thread_mask) == 0) { + /* we need to wake up one thread to handle it immediately */ + int thr = my_ffsl(fdtab[fd].thread_mask & ~tid_bit & all_threads_mask) - 1; + + _HA_ATOMIC_AND(&sleeping_thread_mask, ~(1UL << thr)); + wake_thread(thr); + } } } -- 1.7.10.4