diff options
author | Ivan Maidanski <ivmai@mail.ru> | 2016-08-20 18:39:25 +0300 |
---|---|---|
committer | Ivan Maidanski <ivmai@mail.ru> | 2016-08-20 18:39:25 +0300 |
commit | eb6d4fd97ea93729bc36f4a5df33cf63f8dcc4e3 (patch) | |
tree | b6d8dcd1a882991b23062ac27e292bcfa2367c2b | |
parent | f6a1b686f03aa801ebed7a1799e62849a31b1d37 (diff) | |
download | libatomic_ops-eb6d4fd97ea93729bc36f4a5df33cf63f8dcc4e3.tar.gz |
Workaround a bug in double-wide CAS intrinsic of Apple clang-600/x64
The bug causes test_stack failure.
* src/atomic_ops/sysdeps/gcc/x86.h
[AO_GCC_ATOMIC_TEST_AND_SET && __APPLE_CC__ && __x86_64__]: Fall-back
to asm-based implementation of double-wide CAS
(AO_compare_double_and_swap_double_full); add comment explaining the
reason.
* src/atomic_ops/sysdeps/gcc/x86.h
[__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 && AO_GCC_ATOMIC_TEST_AND_SET
&& __APPLE_CC__] (AO_SKIPATOMIC_double_compare_and_swap_ANY): Define.
-rw-r--r-- | src/atomic_ops/sysdeps/gcc/x86.h | 8 |
1 files changed, 7 insertions, 1 deletions
diff --git a/src/atomic_ops/sysdeps/gcc/x86.h b/src/atomic_ops/sysdeps/gcc/x86.h index 344b78a..041b75a 100644 --- a/src/atomic_ops/sysdeps/gcc/x86.h +++ b/src/atomic_ops/sysdeps/gcc/x86.h @@ -293,11 +293,15 @@ AO_fetch_compare_and_swap_full(volatile AO_t *addr, AO_t old_val, #if (defined(AO_PREFER_BUILTIN_ATOMICS) || !defined(__clang__) \ || defined(__x86_64__) || defined(__APPLE_CC__) || defined(__CYGWIN__)) \ - && defined(AO_GCC_ATOMIC_TEST_AND_SET) + && defined(AO_GCC_ATOMIC_TEST_AND_SET) \ + && !(defined(__APPLE_CC__) && defined(__x86_64__) && !defined(__ILP32__) \ + && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16)) /* As of clang-3.8 i686 (NDK r11c), it requires -latomic for all the */ /* double-wide operations. For now, we fall back to the */ /* non-intrinsic implementation if clang/x86. */ + /* As of Apple clang-600 (based on LLVM 3.5svn), it has some bug in */ + /* double-wide CAS implementation for x64 target. */ /* TODO: Refine for newer clang releases. */ # if defined(__ILP32__) || !defined(__x86_64__) /* 32-bit AO_t */ \ @@ -436,6 +440,8 @@ AO_fetch_compare_and_swap_full(volatile AO_t *addr, AO_t old_val, /* doesn't work. And the emulation is unsafe by our usual rules. */ /* However both are clearly useful in certain cases. */ +# define AO_SKIPATOMIC_double_compare_and_swap_ANY + AO_INLINE int AO_compare_double_and_swap_double_full(volatile AO_double_t *addr, AO_t old_val1, AO_t old_val2, |