summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--include/atomic.h19
2 files changed, 17 insertions, 8 deletions
diff --git a/ChangeLog b/ChangeLog
index 6b8763f95a..9c4d06fdc3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2016-10-26 Carlos O'Donell <carlos@redhat.com>
+
+ * include/atomic.h
+ [USE_COMPILER_ATOMIC_BUILTINS && !atomic_fetch_xor_release]
+ (atomic_fetch_xor_release): Use atomic_compare_exchange_weak_release.
+
2016-10-25 Rajalakshmi Srinivasaraghavan <raji@linux.vnet.ibm.com>
* stdlib/Makefile (tests): Add tst-strfrom and tst-strfrom-locale.
diff --git a/include/atomic.h b/include/atomic.h
index 5a8e7e7966..c8b46649c5 100644
--- a/include/atomic.h
+++ b/include/atomic.h
@@ -777,18 +777,21 @@ void __atomic_link_error (void);
# endif
# ifndef atomic_fetch_xor_release
+/* Failing the atomic_compare_exchange_weak_release reloads the value in
+ __atg104_expected, so we need only do the XOR again and retry. */
# define atomic_fetch_xor_release(mem, operand) \
- ({ __typeof (*(mem)) __atg104_old; \
- __typeof (mem) __atg104_memp = (mem); \
+ ({ __typeof (mem) __atg104_memp = (mem); \
+ __typeof (*(mem)) __atg104_expected = (*__atg104_memp); \
+ __typeof (*(mem)) __atg104_desired; \
__typeof (*(mem)) __atg104_op = (operand); \
\
do \
- __atg104_old = (*__atg104_memp); \
- while (__builtin_expect \
- (atomic_compare_and_exchange_bool_rel ( \
- __atg104_memp, __atg104_old ^ __atg104_op, __atg104_old), 0));\
- \
- __atg104_old; })
+ __atg104_desired = __atg104_expected ^ __atg104_op; \
+ while (__glibc_unlikely \
+ (atomic_compare_exchange_weak_release ( \
+ __atg104_memp, &__atg104_expected, __atg104_desired) \
+ == 0)); \
+ __atg104_expected; })
#endif
#endif /* !USE_ATOMIC_COMPILER_BUILTINS */