From: Willy Tarreau Date: Fri, 25 Sep 2020 10:18:53 +0000 (+0200) Subject: MEDIUM: fd: always wake up one thread when enabling a foreing FD X-Git-Tag: v2.3-dev6~64 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f015887444bb866397e1963457306027cac0e537;p=thirdparty%2Fhaproxy.git 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. --- diff --git a/src/fd.c b/src/fd.c index d05df58752..2c1dcef1b8 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); + } } }