]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: fd: always wake up one thread when enabling a foreing FD
authorWilly Tarreau <w@1wt.eu>
Fri, 25 Sep 2020 10:18:53 +0000 (12:18 +0200)
committerWilly Tarreau <w@1wt.eu>
Fri, 9 Oct 2020 09:27:29 +0000 (11:27 +0200)
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

index d05df58752b5cce1144869f3eb93cd93940c5e03..2c1dcef1b8493d008576bad750fd47879fc7c995 100644 (file)
--- 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);
+               }
        }
 }