2 This file is a part of libcds - Concurrent Data Structures library
4 (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
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_AMD64_CXX11_ATOMIC_H
32 #define CDSLIB_COMPILER_GCC_AMD64_CXX11_ATOMIC_H
35 #include <cds/compiler/gcc/x86/cxx11_atomic32.h>
38 namespace cds { namespace cxx11_atomic {
39 namespace platform { inline namespace gcc { inline namespace amd64 {
41 //-----------------------------------------------------------------------------
43 //-----------------------------------------------------------------------------
46 static inline bool cas64_strong( T volatile * pDest, T& expected, T desired, memory_order mo_success, memory_order mo_fail ) noexcept
48 static_assert( sizeof(T) == 8, "Illegal size of operand" );
49 assert( cds::details::is_aligned( pDest, 8 ));
52 fence_before(mo_success);
53 __asm__ __volatile__ (
54 "lock ; cmpxchgq %[desired], %[pDest]"
55 : [prev] "+a" (prev), [pDest] "+m" (*pDest)
56 : [desired] "r" (desired)
58 bool success = (prev == expected);
61 fence_after(mo_success);
68 static inline bool cas64_weak( T volatile * pDest, T& expected, T desired, memory_order mo_success, memory_order mo_fail ) noexcept
70 return cas64_strong( pDest, expected, desired, mo_success, mo_fail );
74 static inline T load64( T volatile const * pSrc, memory_order order ) noexcept
76 static_assert( sizeof(T) == 8, "Illegal size of operand" );
77 assert( order == memory_order_relaxed
78 || order == memory_order_consume
79 || order == memory_order_acquire
80 || order == memory_order_seq_cst
83 assert( cds::details::is_aligned( pSrc, 8 ));
86 fence_after_load( order );
92 static inline T exchange64( T volatile * pDest, T v, memory_order order ) noexcept
94 static_assert( sizeof(T) == 8, "Illegal size of operand" );
95 assert( cds::details::is_aligned( pDest, 8 ));
98 __asm__ __volatile__ (
99 "xchgq %[v], %[pDest]"
100 : [v] "+r" (v), [pDest] "+m" (*pDest)
106 template <typename T>
107 static inline void store64( T volatile * pDest, T val, memory_order order ) noexcept
109 static_assert( sizeof(T) == 8, "Illegal size of operand" );
110 assert( order == memory_order_relaxed
111 || order == memory_order_release
112 || order == memory_order_seq_cst
115 assert( cds::details::is_aligned( pDest, 8 ));
117 if (order != memory_order_seq_cst) {
122 exchange64( pDest, val, order);
126 # define CDS_ATOMIC_fetch64_add_defined
127 template <typename T>
128 static inline T fetch64_add( T volatile * pDest, T v, memory_order order) noexcept
130 static_assert( sizeof(T) == 8, "Illegal size of operand" );
131 assert( cds::details::is_aligned( pDest, 8 ));
134 __asm__ __volatile__ (
135 "lock ; xaddq %[v], %[pDest]"
136 : [v] "+r" (v), [pDest] "+m" (*pDest)
142 # define CDS_ATOMIC_fetch64_sub_defined
143 template <typename T>
144 static inline T fetch64_sub( T volatile * pDest, T v, memory_order order) noexcept
146 static_assert( sizeof(T) == 8, "Illegal size of operand" );
147 assert( cds::details::is_aligned( pDest, 8 ));
150 __asm__ __volatile__ (
152 "lock ; xaddq %[v], %[pDest]"
153 : [v] "+r" (v), [pDest] "+m" (*pDest)
160 //-----------------------------------------------------------------------------
161 // pointer primitives
162 //-----------------------------------------------------------------------------
164 template <typename T>
165 static inline T * exchange_ptr( T * volatile * pDest, T * v, memory_order order ) noexcept
167 static_assert( sizeof(T *) == sizeof(void *), "Illegal size of operand" );
169 return (T *) exchange64( (uint64_t volatile *) pDest, (uint64_t) v, order );
172 template <typename T>
173 static inline void store_ptr( T * volatile * pDest, T * src, memory_order order ) noexcept
175 static_assert( sizeof(T *) == sizeof(void *), "Illegal size of operand" );
176 assert( order == memory_order_relaxed
177 || order == memory_order_release
178 || order == memory_order_seq_cst
182 if ( order != memory_order_seq_cst ) {
183 fence_before( order );
187 exchange_ptr( pDest, src, order );
191 template <typename T>
192 static inline T * load_ptr( T * volatile const * pSrc, memory_order order ) noexcept
194 static_assert( sizeof(T *) == sizeof(void *), "Illegal size of operand" );
195 assert( order == memory_order_relaxed
196 || order == memory_order_consume
197 || order == memory_order_acquire
198 || order == memory_order_seq_cst
203 fence_after_load( order );
207 template <typename T>
208 static inline bool cas_ptr_strong( T * volatile * pDest, T *& expected, T * desired, memory_order mo_success, memory_order mo_fail ) noexcept
210 static_assert( sizeof(T *) == sizeof(void *), "Illegal size of operand" );
212 return cas64_strong( (uint64_t volatile *) pDest, *reinterpret_cast<uint64_t *>( &expected ), (uint64_t) desired, mo_success, mo_fail );
215 template <typename T>
216 static inline bool cas_ptr_weak( T * volatile * pDest, T *& expected, T * desired, memory_order mo_success, memory_order mo_fail ) noexcept
218 return cas_ptr_strong( pDest, expected, desired, mo_success, mo_fail );
221 }} // namespace gcc::amd64
223 } // namespace platform
225 }} // namespace cds::cxx11_atomic
228 #endif // #ifndef CDSLIB_COMPILER_GCC_AMD64_CXX11_ATOMIC_H