]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: thread: add a new per-thread flag TH_FL_NOTIFIED to remember wakeups
authorWilly Tarreau <w@1wt.eu>
Wed, 22 Jun 2022 13:38:38 +0000 (15:38 +0200)
committerWilly Tarreau <w@1wt.eu>
Fri, 1 Jul 2022 17:15:14 +0000 (19:15 +0200)
Right now when an inter-thread wakeup happens, we preliminary check if the
thread was asleep, and if so we wake the poller up and remove its bit from
the sleeping mask. That's not very clean since the sleeping mask cannot be
entirely trusted since a thread that's about to wake up will already have
its sleeping bit removed.

This patch adds a new per-thread flag (TH_FL_NOTIFIED) to remember that a
thread was notified to wake up. It's cleared before checking the task lists
last, so that new wakeups can be considered again (since wake_thread() is
only used to notify about task wakeups and FD polling changes). This way
we do not need to modify a remote thread's sleeping mask anymore. As such
wake_thread() now only tests and sets the TH_FL_NOTIFIED flag but doesn't
clear sleeping anymore.

include/haproxy/fd.h
include/haproxy/tinfo-t.h
src/haproxy.c

index fa24240568cf76557e8d4d60f36a97aa83b97aa6..29765d82eb270d277511261631279a6ecbef405d 100644 (file)
@@ -370,11 +370,15 @@ static inline unsigned int hap_fd_isset(int fd, unsigned int *evts)
        return evts[fd / (8*sizeof(*evts))] & (1U << (fd & (8*sizeof(*evts) - 1)));
 }
 
+/* send a wake-up event to this thread, only if it's asleep and not notified yet */
 static inline void wake_thread(int thr)
 {
-       if (sleeping_thread_mask & (1UL << thr)) {
+       struct thread_ctx *ctx = &ha_thread_ctx[thr];
+
+       if (sleeping_thread_mask & (1UL << thr) &&
+           (_HA_ATOMIC_LOAD(&ctx->flags) & TH_FL_NOTIFIED) == 0) {
                char c = 'c';
-               _HA_ATOMIC_AND(&sleeping_thread_mask, ~(1UL << thr));
+               _HA_ATOMIC_OR(&ctx->flags, TH_FL_NOTIFIED);
                DISGUISE(write(poller_wr_pipe[thr], &c, 1));
        }
 }
index 81a246c6047f61f29cbab5c31e0c5c32ec5041d9..51a0e275b5e10cda66a0707fb74100ea3853942b 100644 (file)
@@ -42,6 +42,8 @@ enum {
  */
 #define TH_FL_STUCK             0x00000001
 #define TH_FL_TASK_PROFILING    0x00000002
+#define TH_FL_NOTIFIED          0x00000004  /* task was notified about the need to wake up */
+
 
 /* Thread group information. This defines a base and a count of global thread
  * IDs which belong to it, and which can be looked up into thread_info/ctx. It
index 892d821944880b3b16cf30df205a0aa4b22d5a9e..a1addfe7b2476b0625746abe3c4f624404ae5350 100644 (file)
@@ -2805,6 +2805,7 @@ void run_poll_loop()
                        activity[tid].wake_tasks++;
                else {
                        _HA_ATOMIC_OR(&sleeping_thread_mask, tid_bit);
+                       _HA_ATOMIC_AND(&th_ctx->flags, ~TH_FL_NOTIFIED);
                        __ha_barrier_atomic_store();
                        if (thread_has_tasks()) {
                                activity[tid].wake_tasks++;