diff options
author | Ivan Maidanski <ivmai@mail.ru> | 2013-05-26 17:08:27 +0400 |
---|---|---|
committer | Ivan Maidanski <ivmai@mail.ru> | 2013-05-26 17:08:27 +0400 |
commit | 25e83ad7a05407142af78ef4e9155ba3ba07176b (patch) | |
tree | 3f11e4bc69d32d1af4cf03cdd39113239f117dd8 | |
parent | 6e7a0f7f75b46a5980ca711a8fc674c64c9567dd (diff) |
Add non-generalized double-CAS-full implementation for AArch64
* src/atomic_ops/sysdeps/gcc/aarch64.h
(AO_double_compare_and_swap_full): New function.
-rw-r--r-- | src/atomic_ops/sysdeps/gcc/aarch64.h | 25 |
1 files changed, 24 insertions, 1 deletions
diff --git a/src/atomic_ops/sysdeps/gcc/aarch64.h b/src/atomic_ops/sysdeps/gcc/aarch64.h index 6ae26f3..54e6d7f 100644 --- a/src/atomic_ops/sysdeps/gcc/aarch64.h +++ b/src/atomic_ops/sysdeps/gcc/aarch64.h @@ -171,6 +171,29 @@ return !result; } # define AO_HAVE_double_compare_and_swap_release -#endif + + AO_INLINE int + AO_double_compare_and_swap_full(volatile AO_double_t *addr, + AO_double_t old_val, AO_double_t new_val) + { + AO_double_t tmp; + int result = 1; + + do { + __asm__ __volatile__("//AO_double_compare_and_swap_full\n" + " ldaxp %0, %1, %2\n" + : "=&r" (tmp.AO_val1), "=&r" (tmp.AO_val2) + : "Q" (*addr)); + if (tmp.AO_val1 != old_val.AO_val1 || tmp.AO_val2 != old_val.AO_val2) + break; + __asm__ __volatile__( + " stlxp %w0, %2, %3, %1\n" + : "=&r" (result), "=Q" (*addr) + : "r" (new_val.AO_val1), "r" (new_val.AO_val2)); + } while (AO_EXPECT_FALSE(result)); + return !result; + } +# define AO_HAVE_double_compare_and_swap_full +#endif /* __GNUC__ == 4 */ #include "generic.h" |