]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: threads: Fix the exit condition of the thread barrier
authorChristopher Faulet <cfaulet@haproxy.com>
Fri, 20 Jul 2018 07:31:53 +0000 (09:31 +0200)
committerWilly Tarreau <w@1wt.eu>
Fri, 20 Jul 2018 12:24:41 +0000 (14:24 +0200)
In thread_sync_barrier, we exit when all threads have set their own bit in the
barrier mask. It is done by comparing it to all_threads_mask. But we must not
use a simple equality to do so, becaue all_threads_mask may change. Since commit
ba86c6c25 ("MINOR: threads: Be sure to remove threads from all_threads_mask on
exit"), when a thread exit, its bit is removed from all_threads_mask. Instead,
we must use a bitwise AND to test is all bits of all_threads_mask are set.

This also requires that all_threads_mask is set to volatile if we want to
catch changes.

This patch must be backported in 1.8.

include/common/hathreads.h
src/hathreads.c

index 5c4ceca7c1383ef1a539f63d08f8187425b69494..274f9882be8bcc04aacc09c931b2e7cfb249ccc9 100644 (file)
@@ -260,7 +260,7 @@ void thread_exit_sync(void);
 int  thread_no_sync(void);
 int  thread_need_sync(void);
 
-extern unsigned long all_threads_mask;
+extern volatile unsigned long all_threads_mask;
 
 #define ha_sigmask(how, set, oldset)  pthread_sigmask(how, set, oldset)
 
index 5db3c2197851bb726f9d6028c4a5e07d60f02acd..a3bca7d0249ef1c1efbc3a3315eb5583cd4b1222 100644 (file)
@@ -31,7 +31,7 @@ void thread_sync_io_handler(int fd)
 static HA_SPINLOCK_T sync_lock;
 static int           threads_sync_pipe[2];
 static unsigned long threads_want_sync = 0;
-unsigned long all_threads_mask  = 0;
+volatile unsigned long all_threads_mask  = 0;
 
 #if defined(DEBUG_THREAD) || defined(DEBUG_FULL)
 struct lock_stat lock_stats[LOCK_LABELS];
@@ -106,7 +106,7 @@ static inline void thread_sync_barrier(volatile unsigned long *barrier)
 
        HA_ATOMIC_CAS(barrier, &old, 0);
        HA_ATOMIC_OR(barrier, tid_bit);
-       while (*barrier != all_threads_mask)
+       while ((*barrier & all_threads_mask) != all_threads_mask)
                pl_cpu_relax();
 }