MINOR: hathreads: add support for gcc < 4.7
Till now the use of __atomic_* gcc builtins required gcc >= 4.7. Since some supported and quite common operating systems like CentOS 6 still come with older versions (4.4) and the mapping to the older builtins is reasonably simple, let's implement it. This code is only used for gcc < 4.7. It has been quickly tested on a machine using gcc 4.4.4 and provided expected results. This patch should be backported to 1.8.
This commit is contained in:
parent
29f690c945
commit
1a69af6d38
@ -99,6 +99,58 @@ extern THREAD_LOCAL unsigned long tid_bit; /* The bit corresponding to the threa
|
||||
|
||||
/* TODO: thread: For now, we rely on GCC builtins but it could be a good idea to
|
||||
* have a header file regrouping all functions dealing with threads. */
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ < 4 || __GNUC__ == 4 && __GNUC_MINOR__ < 7)
|
||||
/* gcc < 4.7 */
|
||||
|
||||
#define HA_ATOMIC_ADD(val, i) __sync_add_and_fetch(val, i)
|
||||
#define HA_ATOMIC_SUB(val, i) __sync_sub_and_fetch(val, i)
|
||||
#define HA_ATOMIC_AND(val, flags) __sync_and_and_fetch(val, flags)
|
||||
#define HA_ATOMIC_OR(val, flags) __sync_or_and_fetch(val, flags)
|
||||
|
||||
/* the CAS is a bit complicated. The older API doesn't support returning the
|
||||
* value and the swap's result at the same time. So here we take what looks
|
||||
* like the safest route, consisting in using the boolean version guaranteeing
|
||||
* that the operation was performed or not, and we snoop a previous value. If
|
||||
* the compare succeeds, we return. If it fails, we return the previous value,
|
||||
* 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_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_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)); \
|
||||
})
|
||||
#else
|
||||
/* gcc >= 4.7 */
|
||||
#define HA_ATOMIC_CAS(val, old, new) __atomic_compare_exchange_n(val, old, new, 0, 0, 0)
|
||||
#define HA_ATOMIC_ADD(val, i) __atomic_add_fetch(val, i, 0)
|
||||
#define HA_ATOMIC_SUB(val, i) __atomic_sub_fetch(val, i, 0)
|
||||
@ -106,6 +158,8 @@ extern THREAD_LOCAL unsigned long tid_bit; /* The bit corresponding to the threa
|
||||
#define HA_ATOMIC_OR(val, flags) __atomic_or_fetch(val, flags, 0)
|
||||
#define HA_ATOMIC_XCHG(val, new) __atomic_exchange_n(val, new, 0)
|
||||
#define HA_ATOMIC_STORE(val, new) __atomic_store_n(val, new, 0)
|
||||
#endif
|
||||
|
||||
#define HA_ATOMIC_UPDATE_MAX(val, new) \
|
||||
({ \
|
||||
typeof(*(val)) __old = *(val); \
|
||||
|
Loading…
x
Reference in New Issue
Block a user