Le 09/04/2018 à 11:52, Christopher Faulet a écrit :
Hi,

This patch fixes a bug affecting HAProxy compiled with gcc < 4.7 (with
threads). It must be merged in 1.8.


Sorry, I sent the patch I used for HAProxy 1.8. Here is the right patch, for the upstream. But good news for you Willy, it will be easier to backport it in 1.8 now :)

--
Christopher Faulet
>From 8a4f5982f4bb8daaf264938df9fed6f5458f0b33 Mon Sep 17 00:00:00 2001
From: Christopher Faulet <cfau...@haproxy.com>
Date: Mon, 9 Apr 2018 08:45:43 +0200
Subject: [PATCH] BUG/MEDIUM: threads: Fix the max/min calculation because of
 name clashes
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

With gcc < 4.7, when HAProxy is built with threads, the macros
HA_ATOMOC_CAS/XCHG/STORE relies on the legacy ‘__sync’ builtins. These macros
are slightly complicated than the versions relying on the '_atomic'
builtins. Internally, some local variables are defined, prefixed with '__' to
avoid name clashes with the caller.

On the other hand, the macros HA_ATOMIC_UPDATE_MIN/MAX call HA_ATOMIC_CAS. Some
local variables are also definied in these macros, following the same naming
rule as below. The problem is that '__new' variable is used in
HA_ATOMIC_MIN/_MAX and in HA_ATOMIC_CAS. Obviously, the behaviour is undefined
because '__new' in HA_ATOMIC_CAS is left uninitialized. Unfortunatly gcc fails
to detect this error.

To fix the problem, all internal variables to macros are now suffixed with name
of the macros to avoid clashes (for instance, '__new_cas' in HA_ATOMIC_CAS).

This patch must be backported in 1.8.
---
 include/common/hathreads.h | 132 +++++++++++++++++++++++----------------------
 1 file changed, 67 insertions(+), 65 deletions(-)

diff --git a/include/common/hathreads.h b/include/common/hathreads.h
index 15b8ce2c1..0f10b48ca 100644
--- a/include/common/hathreads.h
+++ b/include/common/hathreads.h
@@ -41,44 +41,44 @@ extern THREAD_LOCAL unsigned long tid_bit; /* The bit corresponding to the threa
 #define HA_ATOMIC_OR(val, flags)     ({*(val) |= (flags);})
 #define HA_ATOMIC_XCHG(val, new)					\
 	({								\
-		typeof(*(val)) __old = *(val);				\
+		typeof(*(val)) __old_xchg = *(val);			\
 		*(val) = new;						\
-		__old;							\
+		__old_xchg;						\
 	})
 #define HA_ATOMIC_BTS(val, bit)						\
 	({								\
-		typeof((val)) __p = (val);				\
-		typeof(*__p)  __b = (1UL << (bit));			\
-		typeof(*__p)  __t = *__p & __b;				\
-		if (!__t)						\
-			*__p |= __b;					\
-		__t;							\
+		typeof((val)) __p_bts = (val);				\
+		typeof(*__p_bts)  __b_bts = (1UL << (bit));		\
+		typeof(*__p_bts)  __t_bts = *__p_bts & __b_bts;		\
+		if (!__t_bts)						\
+			*__p_bts |= __b_bts;				\
+		__t_bts;						\
 	})
 #define HA_ATOMIC_BTR(val, bit)						\
 	({								\
-		typeof((val)) __p = (val);				\
-		typeof(*__p)  __b = (1UL << (bit));			\
-		typeof(*__p)  __t = *__p & __b;				\
-		if (__t)						\
-			*__p &= ~__b;					\
-		__t;							\
+		typeof((val)) __p_btr = (val);				\
+		typeof(*__p_btr)  __b_btr = (1UL << (bit));		\
+		typeof(*__p_btr)  __t_btr = *__p_btr & __b_btr;		\
+		if (__t_btr)						\
+			*__p_btr &= ~__b_btr;				\
+		__t_btr;						\
 	})
 #define HA_ATOMIC_STORE(val, new)    ({*(val) = new;})
 #define HA_ATOMIC_UPDATE_MAX(val, new)					\
 	({								\
-		typeof(*(val)) __new = (new);				\
+		typeof(*(val)) __new_max = (new);			\
 									\
-		if (*(val) < __new)					\
-			*(val) = __new;					\
+		if (*(val) < __new_max)					\
+			*(val) = __new_max;				\
 		*(val);							\
 	})
 
 #define HA_ATOMIC_UPDATE_MIN(val, new)					\
 	({								\
-		typeof(*(val)) __new = (new);				\
+		typeof(*(val)) __new_min = (new);			\
 									\
-		if (*(val) > __new)					\
-			*(val) = __new;					\
+		if (*(val) > __new_min)					\
+			*(val) = __new_min;				\
 		*(val);							\
 	})
 
@@ -150,51 +150,51 @@ static inline void __ha_barrier_full(void)
  * but only if it differs from the expected one. If it's the same it's a race
  * thus we try again to avoid confusing a possibly sensitive caller.
  */
-#define HA_ATOMIC_CAS(val, old, new)					       \
-	({								       \
-		typeof((val)) __val = (val);				       \
-		typeof((old)) __oldp = (old);				       \
-		typeof(*(old)) __oldv;					       \
-		typeof((new)) __new = (new);				       \
-		int __ret;						       \
-		do {							       \
-			__oldv = *__val;				       \
-			__ret = __sync_bool_compare_and_swap(__val, *__oldp, __new); \
-		} while (!__ret && *__oldp == __oldv);			       \
-		if (!__ret)						       \
-			*__oldp = __oldv;				       \
-		__ret;							       \
+#define HA_ATOMIC_CAS(val, old, new)					\
+	({								\
+		typeof((val)) __val_cas = (val);			\
+		typeof((old)) __oldp_cas = (old);			\
+		typeof(*(old)) __oldv_cas;				\
+		typeof((new)) __new_cas = (new);			\
+		int __ret_cas;						\
+		do {							\
+			__oldv_cas = *__val_cas;			\
+			__ret_cas = __sync_bool_compare_and_swap(__val_cas, *__oldp_cas, __new_cas); \
+		} while (!__ret_cas && *__oldp_cas == __oldv_cas);	\
+		if (!__ret_cas)						\
+			*__oldp_cas = __oldv_cas;			\
+		__ret_cas;						\
 	})
 
-#define HA_ATOMIC_XCHG(val, new)					       \
-	({								       \
-		typeof((val)) __val = (val);				       \
-		typeof(*(val)) __old;					       \
-		typeof((new)) __new = (new);				       \
-		do { __old = *__val;					       \
-		} while (!__sync_bool_compare_and_swap(__val, __old, __new));  \
-		__old;							       \
+#define HA_ATOMIC_XCHG(val, new)					\
+	({								\
+		typeof((val)) __val_xchg = (val);			\
+		typeof(*(val)) __old_xchg;				\
+		typeof((new)) __new_xchg = (new);			\
+		do { __old_xchg = *__val_xchg;				\
+		} while (!__sync_bool_compare_and_swap(__val_xchg, __old_xchg, __new_xchg)); \
+		__old_xchg;						\
 	})
 
 #define HA_ATOMIC_BTS(val, bit)						\
 	({								\
-		typeof(*(val)) __b = (1UL << (bit));			\
-		__sync_fetch_and_or((val), __b) & __b;			\
+		typeof(*(val)) __b_bts = (1UL << (bit));		\
+		__sync_fetch_and_or((val), __b_bts) & __b_bts;		\
 	})
 
 #define HA_ATOMIC_BTR(val, bit)						\
 	({								\
-		typeof(*(val)) __b = (1UL << (bit));			\
-		__sync_fetch_and_and((val), ~__b) & __b;		\
+		typeof(*(val)) __b_btr = (1UL << (bit));		\
+		__sync_fetch_and_and((val), ~__b_btr) & __b_btr;	\
 	})
 
-#define HA_ATOMIC_STORE(val, new)					     \
-	({								       \
-		typeof((val)) __val = (val);				       \
-		typeof(*(val)) __old;					       \
-		typeof((new)) __new = (new);				       \
-		do { __old = *__val;					       \
-		} while (!__sync_bool_compare_and_swap(__val, __old, __new));  \
+#define HA_ATOMIC_STORE(val, new)					\
+	({								\
+		typeof((val)) __val_store = (val);			\
+		typeof(*(val)) __old_store;				\
+		typeof((new)) __new_store = (new);			\
+		do { __old_store = *__val_store;			\
+		} while (!__sync_bool_compare_and_swap(__val_store, __old_store, __new_store));	\
 	})
 #else
 /* gcc >= 4.7 */
@@ -205,14 +205,14 @@ static inline void __ha_barrier_full(void)
 #define HA_ATOMIC_OR(val, flags)     __atomic_or_fetch(val,  flags, 0)
 #define HA_ATOMIC_BTS(val, bit)						\
 	({								\
-		typeof(*(val)) __b = (1UL << (bit));			\
-		__sync_fetch_and_or((val), __b) & __b;			\
+		typeof(*(val)) __b_bts = (1UL << (bit));		\
+		__sync_fetch_and_or((val), __b_bts) & __b_bts;		\
 	})
 
 #define HA_ATOMIC_BTR(val, bit)						\
 	({								\
-		typeof(*(val)) __b = (1UL << (bit));			\
-		__sync_fetch_and_and((val), ~__b) & __b;		\
+		typeof(*(val)) __b_btr = (1UL << (bit));		\
+		__sync_fetch_and_and((val), ~__b_btr) & __b_btr;	\
 	})
 
 #define HA_ATOMIC_XCHG(val, new)     __atomic_exchange_n(val, new, 0)
@@ -221,19 +221,21 @@ static inline void __ha_barrier_full(void)
 
 #define HA_ATOMIC_UPDATE_MAX(val, new)					\
 	({								\
-		typeof(*(val)) __old = *(val);				\
-		typeof(*(val)) __new = (new);				\
+		typeof(*(val)) __old_max = *(val);			\
+		typeof(*(val)) __new_max = (new);			\
 									\
-		while (__old < __new && !HA_ATOMIC_CAS(val, &__old, __new)); \
-		(*val);							\
+		while (__old_max < __new_max &&				\
+		       !HA_ATOMIC_CAS(val, &__old_max, __new_max));	\
+		*(val);							\
 	})
 #define HA_ATOMIC_UPDATE_MIN(val, new)					\
 	({								\
-		typeof((*val)) __old = *(val);				\
-		typeof((*val)) __new = (new);				\
+		typeof(*(val)) __old_min = *(val);			\
+		typeof(*(val)) __new_min = (new);			\
 									\
-		while (__old > __new && !HA_ATOMIC_CAS(val, &__old, __new)); \
-		(*val);							\
+		while (__old_min > __new_min &&				\
+		       !HA_ATOMIC_CAS(val, &__old_min, __new_min));	\
+		*(val);							\
 	})
 
 #define HA_BARRIER() pl_barrier()
-- 
2.14.3

Reply via email to