about summary refs log tree commit diff
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  */