summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Maidanski <ivmai@mail.ru>2016-04-01 20:34:30 +0300
committerIvan Maidanski <ivmai@mail.ru>2016-04-01 20:34:30 +0300
commit03a0465f80632c408204eaa9272e6ec42d3d474f (patch)
treeb0652544803cc8a9283f5adaf7b58103b572a943
parent01d2509c13f3aa7e03cb4cbf50fda08f98725ce4 (diff)
downloadlibatomic_ops-03a0465f80632c408204eaa9272e6ec42d3d474f.tar.gz
New macro AO_PREFER_BUILTIN_ATOMICS to rely on C11 atomics fully (AArch64)
If AO_PREFER_BUILTIN_ATOMICS is defined then inline assembly implementation is not used. * src/atomic_ops/sysdeps/gcc/aarch64.h (AO_SKIPATOMIC_double_load, AO_SKIPATOMIC_double_load_acquire): Define if AO_PREFER_BUILTIN_ATOMICS. * src/atomic_ops/sysdeps/gcc/aarch64.h (AO_nop_write, AO_double_load, AO_double_load_acquire, AO_double_store, AO_double_store_release, AO_double_compare_and_swap, AO_double_compare_and_swap_acquire, AO_double_compare_and_swap_release, AO_double_compare_and_swap_full): Do not define if AO_PREFER_BUILTIN_ATOMICS. * src/atomic_ops/sysdeps/gcc/aarch64.h (AO_nop_write): Add comment; remove TODO. * src/atomic_ops/sysdeps/gcc/generic.h: Remove TODO about including this header for other targets. * src/atomic_ops/sysdeps/gcc/generic.h (AO_double_load): Do not define if AO_SKIPATOMIC_double_load. * src/atomic_ops/sysdeps/gcc/generic.h (AO_double_load_acquire): Do not define if AO_SKIPATOMIC_double_load_acquire.
-rw-r--r--src/atomic_ops/sysdeps/gcc/aarch64.h35
-rw-r--r--src/atomic_ops/sysdeps/gcc/generic.h7
2 files changed, 25 insertions, 17 deletions
diff --git a/src/atomic_ops/sysdeps/gcc/aarch64.h b/src/atomic_ops/sysdeps/gcc/aarch64.h
index b7f2ef0..612bc18 100644
--- a/src/atomic_ops/sysdeps/gcc/aarch64.h
+++ b/src/atomic_ops/sysdeps/gcc/aarch64.h
@@ -19,18 +19,23 @@
#include "../standard_ao_double_t.h"
-#ifndef AO_UNIPROCESSOR
- AO_INLINE void
- AO_nop_write(void)
- {
- /* TODO: Use C++11 primitive. */
- __asm__ __volatile__("dmb ishst" : : : "memory");
- }
-# define AO_HAVE_nop_write
-#endif
-
-/* TODO: Adjust version check on fixing double-wide AO support in GCC. */
-#if __GNUC__ >= 4
+#ifdef AO_PREFER_BUILTIN_ATOMICS
+ /* As of clang 3.6 (and gcc 5.0), load atomics for double word are */
+ /* translated to incorrect code lacking STXP (see the note below). */
+# define AO_SKIPATOMIC_double_load
+# define AO_SKIPATOMIC_double_load_acquire
+#else
+
+ /* As of clang 3.6 (and gcc 4.9), __atomic_thread_fence is always */
+ /* translated to DMB (which is inefficient for AO_nop_write). */
+# ifndef AO_UNIPROCESSOR
+ AO_INLINE void
+ AO_nop_write(void)
+ {
+ __asm__ __volatile__("dmb ishst" : : : "memory");
+ }
+# define AO_HAVE_nop_write
+# endif
AO_INLINE AO_double_t
AO_double_load(const volatile AO_double_t *addr)
@@ -68,6 +73,9 @@
}
# define AO_HAVE_double_load_acquire
+ /* As of gcc 5.0, all built-in store and CAS atomics for double */
+ /* word require -latomic, so use asm-based implementation by default. */
+
AO_INLINE void
AO_double_store(volatile AO_double_t *addr, AO_double_t value)
{
@@ -195,6 +203,7 @@
return !result;
}
# define AO_HAVE_double_compare_and_swap_full
-#endif /* __GNUC__ >= 4 */
+
+#endif /* !AO_PREFER_BUILTIN_ATOMICS */
#include "generic.h"
diff --git a/src/atomic_ops/sysdeps/gcc/generic.h b/src/atomic_ops/sysdeps/gcc/generic.h
index de79edb..1df2914 100644
--- a/src/atomic_ops/sysdeps/gcc/generic.h
+++ b/src/atomic_ops/sysdeps/gcc/generic.h
@@ -19,8 +19,6 @@
/* For the details, see GNU Manual, chapter 6.52 (Built-in functions */
/* for memory model aware atomic operations). */
-/* TODO: Include this file for other targets if gcc 4.7+ */
-
#ifdef AO_UNIPROCESSOR
/* If only a single processor (core) is used, AO_UNIPROCESSOR could */
/* be defined by the client to avoid unnecessary memory barrier. */
@@ -93,7 +91,7 @@
#ifdef AO_HAVE_DOUBLE_PTR_STORAGE
-# ifndef AO_HAVE_double_load
+# if !defined(AO_HAVE_double_load) && !defined(AO_SKIPATOMIC_double_load)
AO_INLINE AO_double_t
AO_double_load(const volatile AO_double_t *addr)
{
@@ -105,7 +103,8 @@
# define AO_HAVE_double_load
# endif
-# ifndef AO_HAVE_double_load_acquire
+# if !defined(AO_HAVE_double_load_acquire) \
+ && !defined(AO_SKIPATOMIC_double_load_acquire)
AO_INLINE AO_double_t
AO_double_load_acquire(const volatile AO_double_t *addr)
{