summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTobias Leich <email@froggs.de>2016-11-10 09:02:56 +0100
committerIvan Maidanski <ivmai@mail.ru>2016-11-10 12:34:53 +0300
commitc2edeab8dc0931ccc219da1831895d7d0f44c38b (patch)
tree9734459464ec79d8e008253861270a9dd0f0c6d1
parent033e273ff2e40868256fa3ed231798a998c7699e (diff)
downloadlibatomic_ops-c2edeab8dc0931ccc219da1831895d7d0f44c38b.tar.gz
Implement fetch-CAS for s390[x] (gcc)
* 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.
-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. */