diff --git a/include/boost/atomic/detail/ops_gcc_atomic.hpp b/include/boost/atomic/detail/ops_gcc_atomic.hpp index 1052754..2297791 100644 --- a/include/boost/atomic/detail/ops_gcc_atomic.hpp +++ b/include/boost/atomic/detail/ops_gcc_atomic.hpp @@ -20,7 +20,7 @@ #include #include #if defined(__clang__) && (defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B) || defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B)) -#include +#include #include #endif @@ -182,123 +182,9 @@ struct operations< 4u, Signed > : #if defined(__clang__) && defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B) // Workaround for clang bug http://llvm.org/bugs/show_bug.cgi?id=19355 -template< bool Signed > -struct clang_dcas_x86 -{ - typedef typename make_storage_type< 8u, Signed >::type storage_type; - - static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT - { - if ((((uint32_t)&storage) & 0x00000007) == 0) - { -#if defined(__SSE2__) - __asm__ __volatile__ - ( -#if defined(__AVX__) - "vmovq %1, %%xmm4\n\t" - "vmovq %%xmm4, %0\n\t" -#else - "movq %1, %%xmm4\n\t" - "movq %%xmm4, %0\n\t" -#endif - : "=m" (storage) - : "m" (v) - : "memory", "xmm4" - ); -#else - __asm__ __volatile__ - ( - "fildll %1\n\t" - "fistpll %0\n\t" - : "=m" (storage) - : "m" (v) - : "memory" - ); -#endif - } - else - { - uint32_t scratch; - __asm__ __volatile__ - ( - "movl %%ebx, %[scratch]\n\t" - "movl %[value_lo], %%ebx\n\t" - "movl 0(%[dest]), %%eax\n\t" - "movl 4(%[dest]), %%edx\n\t" - ".align 16\n\t" - "1: lock; cmpxchg8b 0(%[dest])\n\t" - "jne 1b\n\t" - "movl %[scratch], %%ebx" - : [scratch] "=m,m" (scratch) - : [value_lo] "a,a" ((uint32_t)v), "c,c" ((uint32_t)(v >> 32)), [dest] "D,S" (&storage) - : "memory", "cc", "edx" - ); - } - } - - static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT - { - storage_type value; - - if ((((uint32_t)&storage) & 0x00000007) == 0) - { -#if defined(__SSE2__) - __asm__ __volatile__ - ( -#if defined(__AVX__) - "vmovq %1, %%xmm4\n\t" - "vmovq %%xmm4, %0\n\t" -#else - "movq %1, %%xmm4\n\t" - "movq %%xmm4, %0\n\t" -#endif - : "=m" (value) - : "m" (storage) - : "memory", "xmm4" - ); -#else - __asm__ __volatile__ - ( - "fildll %1\n\t" - "fistpll %0\n\t" - : "=m" (value) - : "m" (storage) - : "memory" - ); -#endif - } - else - { - // We don't care for comparison result here; the previous value will be stored into value anyway. - value = __sync_val_compare_and_swap(&storage, (storage_type)0, (storage_type)0); - } - - return value; - } - - static BOOST_FORCEINLINE bool compare_exchange_strong( - storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT - { - storage_type old_expected = expected; - expected = __sync_val_compare_and_swap(&storage, old_expected, desired); - return expected == old_expected; - } - - static BOOST_FORCEINLINE bool compare_exchange_weak( - storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT - { - return compare_exchange_strong(storage, expected, desired, success_order, failure_order); - } - - static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT - { - return true; - } -}; - template< bool Signed > struct operations< 8u, Signed > : - public cas_based_operations< clang_dcas_x86< Signed > > + public cas_based_operations< gcc_dcas_x86< Signed > > { }; @@ -318,56 +204,9 @@ struct operations< 8u, Signed > : // Workaround for clang 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 -template< bool Signed > -struct clang_dcas_x86_64 -{ - typedef typename make_storage_type< 16u, Signed >::type storage_type; - - static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) 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" (&storage) - : "memory", "cc", "rax", "rdx" - ); - } - - static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT - { - storage_type value = storage_type(); - return __sync_val_compare_and_swap(&storage, value, value); - } - - static BOOST_FORCEINLINE bool compare_exchange_strong( - storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT - { - storage_type old_expected = expected; - expected = __sync_val_compare_and_swap(&storage, old_expected, desired); - return expected == old_expected; - } - - static BOOST_FORCEINLINE bool compare_exchange_weak( - storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT - { - return compare_exchange_strong(storage, expected, desired, success_order, failure_order); - } - - static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT - { - return true; - } -}; - template< bool Signed > struct operations< 16u, Signed > : - public cas_based_operations< clang_dcas_x86_64< Signed > > + public cas_based_operations< gcc_dcas_x86_64< Signed > > { }; diff --git a/include/boost/atomic/detail/ops_gcc_x86.hpp b/include/boost/atomic/detail/ops_gcc_x86.hpp index acbe9bc..c3c87c5 100644 --- a/include/boost/atomic/detail/ops_gcc_x86.hpp +++ b/include/boost/atomic/detail/ops_gcc_x86.hpp @@ -22,7 +22,7 @@ #include #include #if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B) || defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B) -#include +#include #include #endif @@ -369,164 +369,6 @@ struct operations< 4u, Signed > : #if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B) -template< bool Signed > -struct gcc_dcas_x86 -{ - typedef typename make_storage_type< 8u, Signed >::type storage_type; - - static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT - { - if ((((uint32_t)&storage) & 0x00000007) == 0) - { -#if defined(__SSE2__) - __asm__ __volatile__ - ( -#if defined(__AVX__) - "vmovq %1, %%xmm4\n\t" - "vmovq %%xmm4, %0\n\t" -#else - "movq %1, %%xmm4\n\t" - "movq %%xmm4, %0\n\t" -#endif - : "=m" (storage) - : "m" (v) - : "memory", "xmm4" - ); -#else - __asm__ __volatile__ - ( - "fildll %1\n\t" - "fistpll %0\n\t" - : "=m" (storage) - : "m" (v) - : "memory" - ); -#endif - } - else - { - uint32_t scratch; - __asm__ __volatile__ - ( - "movl %%ebx, %[scratch]\n\t" - "movl %[value_lo], %%ebx\n\t" - "movl 0(%[dest]), %%eax\n\t" - "movl 4(%[dest]), %%edx\n\t" - ".align 16\n\t" - "1: lock; cmpxchg8b 0(%[dest])\n\t" - "jne 1b\n\t" - "movl %[scratch], %%ebx" - : [scratch] "=m,m" (scratch) - : [value_lo] "a,a" ((uint32_t)v), "c,c" ((uint32_t)(v >> 32)), [dest] "D,S" (&storage) - : "cc", "edx", "memory" - ); - } - } - - static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order) BOOST_NOEXCEPT - { - storage_type value; - - if ((((uint32_t)&storage) & 0x00000007) == 0) - { -#if defined(__SSE2__) - __asm__ __volatile__ - ( -#if defined(__AVX__) - "vmovq %1, %%xmm4\n\t" - "vmovq %%xmm4, %0\n\t" -#else - "movq %1, %%xmm4\n\t" - "movq %%xmm4, %0\n\t" -#endif - : "=m" (value) - : "m" (storage) - : "memory", "xmm4" - ); -#else - __asm__ __volatile__ - ( - "fildll %1\n\t" - "fistpll %0\n\t" - : "=m" (value) - : "m" (storage) - : "memory" - ); -#endif - } - else - { - // We don't care for comparison result here; the previous value will be stored into value anyway. - // Also we don't care for ebx and ecx values, they just have to be equal to eax and edx before cmpxchg8b. - __asm__ __volatile__ - ( - "movl %%ebx, %%eax\n\t" - "movl %%ecx, %%edx\n\t" - "lock; cmpxchg8b %[storage]" - : "=&A" (value) - : [storage] "m" (storage) - : "cc", "memory" - ); - } - - return value; - } - - static BOOST_FORCEINLINE bool compare_exchange_strong( - storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT - { -#if defined(__PIC__) - // Make sure ebx is saved and restored properly in case - // of position independent code. To make this work - // setup register constraints such that ebx can not be - // used by accident e.g. as base address for the variable - // to be modified. Accessing "scratch" should always be okay, - // as it can only be placed on the stack (and therefore - // accessed through ebp or esp only). - // - // In theory, could push/pop ebx onto/off the stack, but movs - // to a prepared stack slot turn out to be faster. - - uint32_t scratch; - bool success; - __asm__ __volatile__ - ( - "movl %%ebx, %[scratch]\n\t" - "movl %[desired_lo], %%ebx\n\t" - "lock; cmpxchg8b %[dest]\n\t" - "movl %[scratch], %%ebx\n\t" - "sete %[success]" - : "+A,A,A,A,A,A" (expected), [dest] "+m,m,m,m,m,m" (storage), [scratch] "=m,m,m,m,m,m" (scratch), [success] "=q,m,q,m,q,m" (success) - : [desired_lo] "S,S,D,D,m,m" ((uint32_t)desired), "c,c,c,c,c,c" ((uint32_t)(desired >> 32)) - : "cc", "memory" - ); - return success; -#else - bool success; - __asm__ __volatile__ - ( - "lock; cmpxchg8b %[dest]\n\t" - "sete %[success]" - : "+A,A" (expected), [dest] "+m,m" (storage), [scratch] "=m,m" (scratch), [success] "=q,m" (success) - : "b,b" ((uint32_t)desired), "c,c" ((uint32_t)(desired >> 32)) - : "cc", "memory" - ); - return success; -#endif - } - - static BOOST_FORCEINLINE bool compare_exchange_weak( - storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT - { - return compare_exchange_strong(storage, expected, desired, success_order, failure_order); - } - - static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT - { - return true; - } -}; - template< bool Signed > struct operations< 8u, Signed > : public cas_based_operations< gcc_dcas_x86< Signed > > @@ -625,74 +467,6 @@ struct operations< 8u, Signed > : #if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B) -template< bool Signed > -struct gcc_dcas_x86_64 -{ - typedef typename make_storage_type< 16u, Signed >::type storage_type; - - static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT - { - uint64_t const* p_value = (uint64_t const*)&v; - __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" (&storage) - : "cc", "rax", "rdx", "memory" - ); - } - - static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order) BOOST_NOEXCEPT - { - storage_type 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 %[storage]" - : "=&A" (value) - : [storage] "m" (storage) - : "cc", "memory" - ); - - return value; - } - - static BOOST_FORCEINLINE bool compare_exchange_strong( - storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) 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" (storage), [success] "=q,m" (success) - : "b,b" (p_desired[0]), "c,c" (p_desired[1]) - : "cc", "memory" - ); - return success; - } - - static BOOST_FORCEINLINE bool compare_exchange_weak( - storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT - { - return compare_exchange_strong(storage, expected, desired, success_order, failure_order); - } - - static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT - { - return true; - } -}; - template< bool Signed > struct operations< 16u, Signed > : public cas_based_operations< gcc_dcas_x86_64< Signed > > diff --git a/include/boost/atomic/detail/ops_gcc_x86_dcas.hpp b/include/boost/atomic/detail/ops_gcc_x86_dcas.hpp new file mode 100644 index 0000000..4241a87 --- /dev/null +++ b/include/boost/atomic/detail/ops_gcc_x86_dcas.hpp @@ -0,0 +1,308 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2009 Helge Bahmann + * Copyright (c) 2012 Tim Blechmann + * Copyright (c) 2014 Andrey Semashev + */ +/*! + * \file atomic/detail/ops_gcc_x86_dcas.hpp + * + * This header contains implementation of the double-width CAS primitive for x86. + */ + +#ifndef BOOST_ATOMIC_DETAIL_OPS_GCC_X86_DCAS_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_OPS_GCC_X86_DCAS_HPP_INCLUDED_ + +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +#if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B) + +template< bool Signed > +struct gcc_dcas_x86 +{ + typedef typename make_storage_type< 8u, Signed >::type storage_type; + + static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + if ((((uint32_t)&storage) & 0x00000007) == 0) + { +#if defined(__SSE2__) + __asm__ __volatile__ + ( +#if defined(__AVX__) + "vmovq %1, %%xmm4\n\t" + "vmovq %%xmm4, %0\n\t" +#else + "movq %1, %%xmm4\n\t" + "movq %%xmm4, %0\n\t" +#endif + : "=m" (storage) + : "m" (v) + : "memory", "xmm4" + ); +#else + __asm__ __volatile__ + ( + "fildll %1\n\t" + "fistpll %0\n\t" + : "=m" (storage) + : "m" (v) + : "memory" + ); +#endif + } + else + { +#if defined(__PIC__) + uint32_t scratch; + __asm__ __volatile__ + ( + "movl %%ebx, %[scratch]\n\t" + "movl %[value_lo], %%ebx\n\t" + "movl 0(%[dest]), %%eax\n\t" + "movl 4(%[dest]), %%edx\n\t" + ".align 16\n\t" + "1: lock; cmpxchg8b 0(%[dest])\n\t" + "jne 1b\n\t" + "movl %[scratch], %%ebx" + : [scratch] "=m,m" (scratch) + : [value_lo] "a,a" ((uint32_t)v), "c,c" ((uint32_t)(v >> 32)), [dest] "D,S" (&storage) + : "cc", "edx", "memory" + ); +#else + __asm__ __volatile__ + ( + "movl 0(%[dest]), %%eax\n\t" + "movl 4(%[dest]), %%edx\n\t" + ".align 16\n\t" + "1: lock; cmpxchg8b 0(%[dest])\n\t" + "jne 1b\n\t" + : + : [value_lo] "b,b" ((uint32_t)v), "c,c" ((uint32_t)(v >> 32)), [dest] "D,S" (&storage) + : "cc", "eax", "edx", "memory" + ); +#endif + } + } + + static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order) BOOST_NOEXCEPT + { + storage_type value; + + if ((((uint32_t)&storage) & 0x00000007) == 0) + { +#if defined(__SSE2__) + __asm__ __volatile__ + ( +#if defined(__AVX__) + "vmovq %1, %%xmm4\n\t" + "vmovq %%xmm4, %0\n\t" +#else + "movq %1, %%xmm4\n\t" + "movq %%xmm4, %0\n\t" +#endif + : "=m" (value) + : "m" (storage) + : "memory", "xmm4" + ); +#else + __asm__ __volatile__ + ( + "fildll %1\n\t" + "fistpll %0\n\t" + : "=m" (value) + : "m" (storage) + : "memory" + ); +#endif + } + else + { +#if defined(__clang__) + // Clang cannot allocate eax:edx register pairs but it has sync intrinsics + value = __sync_val_compare_and_swap(&storage, (storage_type)0, (storage_type)0); +#else + // We don't care for comparison result here; the previous value will be stored into value anyway. + // Also we don't care for ebx and ecx values, they just have to be equal to eax and edx before cmpxchg8b. + __asm__ __volatile__ + ( + "movl %%ebx, %%eax\n\t" + "movl %%ecx, %%edx\n\t" + "lock; cmpxchg8b %[storage]" + : "=&A" (value) + : [storage] "m" (storage) + : "cc", "memory" + ); +#endif + } + + return value; + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT + { +#if defined(__clang__) + // Clang cannot allocate eax:edx register pairs but it has sync intrinsics + storage_type old_expected = expected; + expected = __sync_val_compare_and_swap(&storage, old_expected, desired); + return expected == old_expected; +#elif defined(__PIC__) + // Make sure ebx is saved and restored properly in case + // of position independent code. To make this work + // setup register constraints such that ebx can not be + // used by accident e.g. as base address for the variable + // to be modified. Accessing "scratch" should always be okay, + // as it can only be placed on the stack (and therefore + // accessed through ebp or esp only). + // + // In theory, could push/pop ebx onto/off the stack, but movs + // to a prepared stack slot turn out to be faster. + + uint32_t scratch; + bool success; + __asm__ __volatile__ + ( + "movl %%ebx, %[scratch]\n\t" + "movl %[desired_lo], %%ebx\n\t" + "lock; cmpxchg8b %[dest]\n\t" + "movl %[scratch], %%ebx\n\t" + "sete %[success]" + : "+A,A,A,A,A,A" (expected), [dest] "+m,m,m,m,m,m" (storage), [scratch] "=m,m,m,m,m,m" (scratch), [success] "=q,m,q,m,q,m" (success) + : [desired_lo] "S,S,D,D,m,m" ((uint32_t)desired), "c,c,c,c,c,c" ((uint32_t)(desired >> 32)) + : "cc", "memory" + ); + return success; +#else + bool success; + __asm__ __volatile__ + ( + "lock; cmpxchg8b %[dest]\n\t" + "sete %[success]" + : "+A,A" (expected), [dest] "+m,m" (storage), [scratch] "=m,m" (scratch), [success] "=q,m" (success) + : "b,b" ((uint32_t)desired), "c,c" ((uint32_t)(desired >> 32)) + : "cc", "memory" + ); + return success; +#endif + } + + static BOOST_FORCEINLINE bool compare_exchange_weak( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + return compare_exchange_strong(storage, expected, desired, success_order, failure_order); + } + + static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT + { + return true; + } +}; + +#endif // defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B) + +#if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B) + +template< bool Signed > +struct gcc_dcas_x86_64 +{ + typedef typename make_storage_type< 16u, Signed >::type storage_type; + + static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + uint64_t const* p_value = (uint64_t const*)&v; + __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" (&storage) + : "cc", "rax", "rdx", "memory" + ); + } + + static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order) BOOST_NOEXCEPT + { +#if defined(__clang__) + // Clang cannot allocate rax:rdx register pairs but it has sync intrinsics + storage_type value = storage_type(); + return __sync_val_compare_and_swap(&storage, value, value); +#else + storage_type 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 %[storage]" + : "=&A" (value) + : [storage] "m" (storage) + : "cc", "memory" + ); + + return value; +#endif + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT + { +#if defined(__clang__) + // Clang cannot allocate rax:rdx register pairs but it has sync intrinsics + storage_type old_expected = expected; + expected = __sync_val_compare_and_swap(&storage, old_expected, desired); + return expected == old_expected; +#else + 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" (storage), [success] "=q,m" (success) + : "b,b" (p_desired[0]), "c,c" (p_desired[1]) + : "cc", "memory" + ); + return success; +#endif + } + + static BOOST_FORCEINLINE bool compare_exchange_weak( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + return compare_exchange_strong(storage, expected, desired, success_order, failure_order); + } + + static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT + { + return true; + } +}; + +#endif // defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B) + +} // namespace detail +} // namespace atomics +} // namespace boost + +#endif // BOOST_ATOMIC_DETAIL_OPS_GCC_X86_DCAS_HPP_INCLUDED_ diff --git a/include/boost/atomic/detail/platform.hpp b/include/boost/atomic/detail/platform.hpp index 50609ac..f60eec4 100644 --- a/include/boost/atomic/detail/platform.hpp +++ b/include/boost/atomic/detail/platform.hpp @@ -26,7 +26,6 @@ #define BOOST_ATOMIC_DETAIL_PLATFORM emulated #define BOOST_ATOMIC_EMULATED -// Intel compiler does not support __atomic* intrinsics properly, although defines them (tested with 13.0.1 and 13.1.1 on Linux) #elif (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 407))\ || (defined(BOOST_CLANG) && ((__clang_major__ * 100 + __clang_minor__) >= 302))