summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/atomic_ops/sysdeps/gcc/s390.h19
1 files changed, 18 insertions, 1 deletions
diff --git a/src/atomic_ops/sysdeps/gcc/s390.h b/src/atomic_ops/sysdeps/gcc/s390.h
index 36efbac..31886e2 100644
--- a/src/atomic_ops/sysdeps/gcc/s390.h
+++ b/src/atomic_ops/sysdeps/gcc/s390.h
@@ -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. */