about summary refs log tree commit diff
path: root/sysdeps/s390/bits/atomic.h
diff options
context:
space:
mode:
authorStefan Liebler <stli@linux.vnet.ibm.com>2015-02-20 10:48:06 +0100
committerAndreas Krebbel <krebbel@linux.vnet.ibm.com>2015-02-20 10:48:06 +0100
commit7133957fe856f42c356c6e46c52d2ea8063ae067 (patch)
tree116107f2ba288b25ba66c2623eae02762f88a45b /sysdeps/s390/bits/atomic.h
parent40176158f1bfcf4fd1621169221c1aa8f0c3c300 (diff)
downloadglibc-7133957fe856f42c356c6e46c52d2ea8063ae067.tar.gz
glibc-7133957fe856f42c356c6e46c52d2ea8063ae067.tar.xz
glibc-7133957fe856f42c356c6e46c52d2ea8063ae067.zip
s390: Use generic lowlevellock-futex.h
      * sysdeps/unix/sysv/linux/s390/lowlevellock.h: Include
      <sysdeps/nptl/lowlevellock.h> and remove macros and
      functions that are now defined there.
      (SYS_futex): Remove.
      (lll_compare_and_swap): Remove.
      * sysdeps/s390/bits/atomic.h (atomic_exchange_acq): Define.
Diffstat (limited to 'sysdeps/s390/bits/atomic.h')
-rw-r--r--sysdeps/s390/bits/atomic.h41
1 files changed, 41 insertions, 0 deletions
diff --git a/sysdeps/s390/bits/atomic.h b/sysdeps/s390/bits/atomic.h
index a85288280c..16c8c54b94 100644
--- a/sysdeps/s390/bits/atomic.h
+++ b/sysdeps/s390/bits/atomic.h
@@ -77,3 +77,44 @@ typedef uintmax_t uatomic_max_t;
 # define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \
   (abort (), (__typeof (*mem)) 0)
 #endif
+
+/* Store NEWVALUE in *MEM and return the old value.  */
+/* On s390, the atomic_exchange_acq is different from generic implementation,
+   because the generic one does not use the condition-code of cs-instruction
+   to determine if looping is needed. Instead it saves the old-value and
+   compares it against old-value returned by cs-instruction.  */
+#ifdef __s390x__
+# define atomic_exchange_acq(mem, newvalue)				\
+  ({ __typeof (mem) __atg5_memp = (mem);				\
+    __typeof (*(mem)) __atg5_oldval = *__atg5_memp;			\
+    __typeof (*(mem)) __atg5_value = (newvalue);			\
+    if (sizeof (*mem) == 4)						\
+      __asm __volatile ("0: cs %0,%2,%1\n"				\
+			"   jl 0b"					\
+			: "+d" (__atg5_oldval), "=Q" (*__atg5_memp)	\
+			: "d" (__atg5_value), "m" (*__atg5_memp)	\
+			: "cc", "memory" );				\
+     else if (sizeof (*mem) == 8)					\
+       __asm __volatile ("0: csg %0,%2,%1\n"				\
+			 "   jl 0b"					\
+			 : "+d" ( __atg5_oldval), "=Q" (*__atg5_memp)	\
+			 : "d" ((long) __atg5_value), "m" (*__atg5_memp) \
+			 : "cc", "memory" );				\
+     else								\
+       abort ();							\
+     __atg5_oldval; })
+#else
+# define atomic_exchange_acq(mem, newvalue)				\
+  ({ __typeof (mem) __atg5_memp = (mem);				\
+    __typeof (*(mem)) __atg5_oldval = *__atg5_memp;			\
+    __typeof (*(mem)) __atg5_value = (newvalue);			\
+    if (sizeof (*mem) == 4)						\
+      __asm __volatile ("0: cs %0,%2,%1\n"				\
+			"   jl 0b"					\
+			: "+d" (__atg5_oldval), "=Q" (*__atg5_memp)	\
+			: "d" (__atg5_value), "m" (*__atg5_memp)	\
+			: "cc", "memory" );				\
+    else								\
+      abort ();								\
+    __atg5_oldval; })
+#endif