2 This file is a part of libcds - Concurrent Data Structures library
4 (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
6 Source code repo: http://github.com/khizmax/libcds/
7 Download: http://sourceforge.net/projects/libcds/files/
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions are met:
12 * Redistributions of source code must retain the above copyright notice, this
13 list of conditions and the following disclaimer.
15 * Redistributions in binary form must reproduce the above copyright notice,
16 this list of conditions and the following disclaimer in the documentation
17 and/or other materials provided with the distribution.
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #ifndef CDSLIB_COMPILER_GCC_X86_CXX11_ATOMIC_H
32 #define CDSLIB_COMPILER_GCC_X86_CXX11_ATOMIC_H
35 #include <cds/compiler/gcc/x86/cxx11_atomic32.h>
38 namespace cds { namespace cxx11_atomic {
39 namespace platform { CDS_CXX11_INLINE_NAMESPACE namespace gcc { CDS_CXX11_INLINE_NAMESPACE namespace x86 {
41 //-----------------------------------------------------------------------------
43 //-----------------------------------------------------------------------------
46 static inline bool cas64_strong( T volatile * pDest, T& expected, T desired, memory_order mo_success, memory_order mo_fail ) CDS_NOEXCEPT
48 static_assert( sizeof(T) == 8, "Illegal size of operand" );
49 assert( cds::details::is_aligned( pDest, 8 ));
54 fence_before(mo_success);
56 // We must save EBX in PIC mode
57 __asm__ __volatile__ (
58 "movl %%ebx, %[ebxStore]\n"
59 "movl %[desiredLo], %%ebx\n"
60 "lock; cmpxchg8b 0(%[pDest])\n"
61 "movl %[ebxStore], %%ebx\n"
62 : [prev] "=A" (prev), [ebxStore] "=m" (ebxStore)
63 : [desiredLo] "D" ((int)desired), [desiredHi] "c" ((int)(desired >> 32)), [pDest] "S" (pDest), "0" (prev)
65 bool success = (prev == expected);
67 fence_after(mo_success);
76 static inline bool cas64_weak( T volatile * pDest, T& expected, T desired, memory_order mo_success, memory_order mo_fail ) CDS_NOEXCEPT
78 return cas64_strong( pDest, expected, desired, mo_success, mo_fail );
82 static inline T load64( T volatile const * pSrc, memory_order order ) CDS_NOEXCEPT
84 static_assert( sizeof(T) == 8, "Illegal size of operand" );
85 assert( order == memory_order_relaxed
86 || order == memory_order_consume
87 || order == memory_order_acquire
88 || order == memory_order_seq_cst
91 assert( cds::details::is_aligned( pSrc, 8 ));
94 T CDS_DATA_ALIGNMENT(8) v;
96 "movq (%[pSrc]), %[v] ; \n\t"
105 template <typename T>
106 static inline T exchange64( T volatile * pDest, T v, memory_order order ) CDS_NOEXCEPT
108 static_assert( sizeof(T) == 8, "Illegal size of operand" );
109 assert( cds::details::is_aligned( pDest, 8 ));
111 T cur = load64( pDest, memory_order_relaxed );
113 } while (!cas64_weak( pDest, cur, v, order, memory_order_relaxed ));
117 template <typename T>
118 static inline void store64( T volatile * pDest, T val, memory_order order ) CDS_NOEXCEPT
120 static_assert( sizeof(T) == 8, "Illegal size of operand" );
121 assert( order == memory_order_relaxed
122 || order == memory_order_release
123 || order == memory_order_seq_cst
126 assert( cds::details::is_aligned( pDest, 8 ));
128 if ( order != memory_order_seq_cst ) {
129 fence_before( order );
130 // Atomically stores 64bit value by SSE instruction
131 __asm__ __volatile__(
132 "movq %[val], (%[pDest]) ; \n\t"
134 : [val] "x" (val), [pDest] "r" (pDest)
139 exchange64( pDest, val, order );
144 //-----------------------------------------------------------------------------
145 // pointer primitives
146 //-----------------------------------------------------------------------------
148 template <typename T>
149 static inline T * exchange_ptr( T * volatile * pDest, T * v, memory_order order ) CDS_NOEXCEPT
151 static_assert( sizeof(T *) == sizeof(void *), "Illegal size of operand" );
153 return (T *) exchange32( (uint32_t volatile *) pDest, (uint32_t) v, order );
156 template <typename T>
157 static inline void store_ptr( T * volatile * pDest, T * src, memory_order order ) CDS_NOEXCEPT
159 static_assert( sizeof(T *) == sizeof(void *), "Illegal size of operand" );
160 assert( order == memory_order_relaxed
161 || order == memory_order_release
162 || order == memory_order_seq_cst
166 if ( order != memory_order_seq_cst ) {
167 fence_before( order );
171 exchange_ptr( pDest, src, order );
175 template <typename T>
176 static inline T * load_ptr( T * volatile const * pSrc, memory_order order ) CDS_NOEXCEPT
178 static_assert( sizeof(T *) == sizeof(void *), "Illegal size of operand" );
179 assert( order == memory_order_relaxed
180 || order == memory_order_consume
181 || order == memory_order_acquire
182 || order == memory_order_seq_cst
187 fence_after_load( order );
191 template <typename T>
192 static inline bool cas_ptr_strong( T * volatile * pDest, T *& expected, T * desired, memory_order mo_success, memory_order mo_fail ) CDS_NOEXCEPT
194 static_assert( sizeof(T *) == sizeof(void *), "Illegal size of operand" );
196 return cas32_strong( (uint32_t volatile *) pDest, *reinterpret_cast<uint32_t *>( &expected ), (uint32_t) desired, mo_success, mo_fail );
199 template <typename T>
200 static inline bool cas_ptr_weak( T * volatile * pDest, T *& expected, T * desired, memory_order mo_success, memory_order mo_fail ) CDS_NOEXCEPT
202 return cas_ptr_strong( pDest, expected, desired, mo_success, mo_fail );
204 }} // namespace gcc::x86
206 #ifndef CDS_CXX11_INLINE_NAMESPACE_SUPPORT
207 using namespace gcc::x86;
209 } // namespace platform
210 }} // namespace cds::cxx11_atomic
213 #endif // #ifndef CDSLIB_COMPILER_GCC_X86_CXX11_ATOMIC_H