]> granicus.if.org Git - libatomic_ops/commitdiff
Implement fetch-CAS for s390[x] (gcc)
authorTobias Leich <email@froggs.de>
Thu, 10 Nov 2016 08:02:56 +0000 (09:02 +0100)
committerIvan Maidanski <ivmai@mail.ru>
Thu, 10 Nov 2016 09:34:53 +0000 (12:34 +0300)
* src/atomic_ops/sysdeps/gcc/s390.h (AO_compare_and_swap_full): Do not
define if AO_GENERALIZE_ASM_BOOL_CAS.
* src/atomic_ops/sysdeps/gcc/s390.h (AO_fetch_compare_and_swap_full):
Implement; remove TODO item.

src/atomic_ops/sysdeps/gcc/s390.h

index 36efbac1253e64279f53d2127284cd747eb3dbe0..31886e2b54b245a8cfd009f86ca1268f5cbccceb 100644 (file)
@@ -41,6 +41,7 @@
 /* It appears that certain BCR instructions have that effect.   */
 /* Presumably they're cheaper than CS?                          */
 
+#ifndef AO_GENERALIZE_ASM_BOOL_CAS
 AO_INLINE int AO_compare_and_swap_full(volatile AO_t *addr,
                                        AO_t old, AO_t new_val)
 {
@@ -59,7 +60,23 @@ AO_INLINE int AO_compare_and_swap_full(volatile AO_t *addr,
   return retval == 0;
 }
 #define AO_HAVE_compare_and_swap_full
+#endif /* !AO_GENERALIZE_ASM_BOOL_CAS */
 
-/* TODO: implement AO_fetch_compare_and_swap.   */
+AO_INLINE AO_t
+AO_fetch_compare_and_swap_full(volatile AO_t *addr,
+                               AO_t old, AO_t new_val)
+{
+  __asm__ __volatile__ (
+#   ifndef __s390x__
+      "     cs %0,%2,%1\n"
+#   else
+      "     csg %0,%2,%1\n"
+# endif
+    : "+d" (old), "=Q" (*addr)
+    : "d" (new_val), "m" (*addr)
+    : "cc", "memory");
+  return old;
+}
+#define AO_HAVE_fetch_compare_and_swap_full
 
 /* TODO: Add double-wide operations for 32-bit executables.       */