From bf1898e2e6ae8461d4fd2ce5036d60ff095fd38e Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sat, 15 Mar 2014 16:11:03 +0400 Subject: [PATCH] Added a workaround for clang 3.4 bug: the compiler does not implement __atomic intrinsics even though it defines __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 macro. --- include/boost/atomic/detail/gcc-atomic.hpp | 72 +++++++++++++++++++++- 1 file changed, 70 insertions(+), 2 deletions(-) diff --git a/include/boost/atomic/detail/gcc-atomic.hpp b/include/boost/atomic/detail/gcc-atomic.hpp index 4af99a1..5b70a2c 100644 --- a/include/boost/atomic/detail/gcc-atomic.hpp +++ b/include/boost/atomic/detail/gcc-atomic.hpp @@ -32,6 +32,12 @@ namespace detail { #define BOOST_ATOMIC_X86_HAS_CMPXCHG16B 1 #endif +#if defined(BOOST_ATOMIC_X86_HAS_CMPXCHG16B) && defined(__clang__) +// Worraround for bug: http://llvm.org/bugs/show_bug.cgi?id=19149 +// Clang 3.4 does not implement 128-bit __atomic* intrinsics even though it defines __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 +#define BOOST_ATOMIC_X86_NO_GCC_128_BIT_ATOMIC_INTRINSICS +#endif + BOOST_FORCEINLINE BOOST_CONSTEXPR int convert_memory_order_to_gcc(memory_order order) BOOST_NOEXCEPT { return (order == memory_order_relaxed ? __ATOMIC_RELAXED : (order == memory_order_consume ? __ATOMIC_CONSUME : @@ -830,7 +836,7 @@ private: #endif // defined(BOOST_ATOMIC_LLONG_LOCK_FREE) && BOOST_ATOMIC_LLONG_LOCK_FREE > 0 -#if defined(BOOST_ATOMIC_INT128_LOCK_FREE) && BOOST_ATOMIC_INT128_LOCK_FREE > 0 +#if defined(BOOST_ATOMIC_INT128_LOCK_FREE) && BOOST_ATOMIC_INT128_LOCK_FREE > 0 && !defined(BOOST_ATOMIC_X86_NO_GCC_128_BIT_ATOMIC_INTRINSICS) template class base_atomic @@ -1041,7 +1047,7 @@ private: storage_type v_; }; -#endif // defined(BOOST_ATOMIC_INT128_LOCK_FREE) && BOOST_ATOMIC_INT128_LOCK_FREE > 0 +#endif // defined(BOOST_ATOMIC_INT128_LOCK_FREE) && BOOST_ATOMIC_INT128_LOCK_FREE > 0 && !defined(BOOST_ATOMIC_X86_NO_GCC_128_BIT_ATOMIC_INTRINSICS) /* pointers */ @@ -1202,10 +1208,72 @@ private: #endif // defined(BOOST_ATOMIC_POINTER_LOCK_FREE) && BOOST_ATOMIC_POINTER_LOCK_FREE > 0 +#if defined(BOOST_ATOMIC_INT128_LOCK_FREE) && BOOST_ATOMIC_INT128_LOCK_FREE > 0 && defined(BOOST_ATOMIC_X86_NO_GCC_128_BIT_ATOMIC_INTRINSICS) + +template +inline bool platform_cmpxchg128_strong(T& expected, T desired, volatile T* ptr) BOOST_NOEXCEPT +{ + uint64_t const* p_desired = (uint64_t const*)&desired; + bool success; + __asm__ __volatile__ + ( + "lock; cmpxchg16b %[dest]\n\t" + "sete %[success]" + : "+A,A" (expected), [dest] "+m,m" (*ptr), [success] "=q,m" (success) + : "b,b" (p_desired[0]), "c,c" (p_desired[1]) + : "memory", "cc" + ); + return success; +} + +template +inline void platform_store128(T value, volatile T* ptr) BOOST_NOEXCEPT +{ + uint64_t const* p_value = (uint64_t const*)&value; + __asm__ __volatile__ + ( + "movq 0(%[dest]), %%rax\n\t" + "movq 8(%[dest]), %%rdx\n\t" + ".align 16\n\t" + "1: lock; cmpxchg16b 0(%[dest])\n\t" + "jne 1b" + : + : "b" (p_value[0]), "c" (p_value[1]), [dest] "r" (ptr) + : "memory", "cc", "rax", "rdx" + ); +} + +template +inline T platform_load128(const volatile T* ptr) BOOST_NOEXCEPT +{ + T value; + + // We don't care for comparison result here; the previous value will be stored into value anyway. + // Also we don't care for rbx and rcx values, they just have to be equal to rax and rdx before cmpxchg16b. + __asm__ __volatile__ + ( + "movq %%rbx, %%rax\n\t" + "movq %%rcx, %%rdx\n\t" + "lock; cmpxchg16b %[dest]" + : "=&A" (value) + : [dest] "m" (*ptr) + : "cc" + ); + + return value; +} + +#endif // defined(BOOST_ATOMIC_INT128_LOCK_FREE) && BOOST_ATOMIC_INT128_LOCK_FREE > 0 && defined(BOOST_ATOMIC_X86_NO_GCC_128_BIT_ATOMIC_INTRINSICS) + } // namespace detail } // namespace atomics } // namespace boost +#if defined(BOOST_ATOMIC_INT128_LOCK_FREE) && BOOST_ATOMIC_INT128_LOCK_FREE > 0 && defined(BOOST_ATOMIC_X86_NO_GCC_128_BIT_ATOMIC_INTRINSICS) +#undef BOOST_ATOMIC_X86_NO_GCC_128_BIT_ATOMIC_INTRINSICS +#include +#endif // defined(BOOST_ATOMIC_INT128_LOCK_FREE) && BOOST_ATOMIC_INT128_LOCK_FREE > 0 && defined(BOOST_ATOMIC_X86_NO_GCC_128_BIT_ATOMIC_INTRINSICS) + #endif // !defined(BOOST_ATOMIC_FORCE_FALLBACK) #endif // BOOST_ATOMIC_DETAIL_GCC_ATOMIC_HPP