]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /* |
2 | * Distributed under the Boost Software License, Version 1.0. | |
3 | * (See accompanying file LICENSE_1_0.txt or copy at | |
4 | * http://www.boost.org/LICENSE_1_0.txt) | |
5 | * | |
6 | * Copyright (c) 2014 Andrey Semashev | |
7 | */ | |
8 | /*! | |
9 | * \file atomic/detail/ops_gcc_atomic.hpp | |
10 | * | |
11 | * This header contains implementation of the \c operations template. | |
12 | */ | |
13 | ||
14 | #ifndef BOOST_ATOMIC_DETAIL_OPS_GCC_ATOMIC_HPP_INCLUDED_ | |
15 | #define BOOST_ATOMIC_DETAIL_OPS_GCC_ATOMIC_HPP_INCLUDED_ | |
16 | ||
17 | #include <boost/memory_order.hpp> | |
18 | #include <boost/atomic/detail/config.hpp> | |
19 | #include <boost/atomic/detail/storage_type.hpp> | |
20 | #include <boost/atomic/detail/operations_fwd.hpp> | |
21 | #include <boost/atomic/capabilities.hpp> | |
22 | #if defined(__clang__) && (defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B) || defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B)) | |
23 | #include <boost/atomic/detail/ops_gcc_x86_dcas.hpp> | |
24 | #include <boost/atomic/detail/ops_cas_based.hpp> | |
25 | #endif | |
26 | ||
27 | #if __GCC_ATOMIC_LLONG_LOCK_FREE != BOOST_ATOMIC_LLONG_LOCK_FREE || __GCC_ATOMIC_LONG_LOCK_FREE != BOOST_ATOMIC_LONG_LOCK_FREE ||\ | |
28 | __GCC_ATOMIC_INT_LOCK_FREE != BOOST_ATOMIC_INT_LOCK_FREE || __GCC_ATOMIC_SHORT_LOCK_FREE != BOOST_ATOMIC_SHORT_LOCK_FREE ||\ | |
29 | __GCC_ATOMIC_CHAR_LOCK_FREE != BOOST_ATOMIC_CHAR_LOCK_FREE || __GCC_ATOMIC_BOOL_LOCK_FREE != BOOST_ATOMIC_BOOL_LOCK_FREE ||\ | |
30 | __GCC_ATOMIC_WCHAR_T_LOCK_FREE != BOOST_ATOMIC_WCHAR_T_LOCK_FREE | |
31 | // There are platforms where we need to use larger storage types | |
32 | #include <boost/atomic/detail/int_sizes.hpp> | |
33 | #include <boost/atomic/detail/ops_extending_cas_based.hpp> | |
34 | #endif | |
35 | ||
36 | #ifdef BOOST_HAS_PRAGMA_ONCE | |
37 | #pragma once | |
38 | #endif | |
39 | ||
40 | #if defined(__INTEL_COMPILER) | |
41 | // This is used to suppress warning #32013 described below for Intel Compiler. | |
42 | // In debug builds the compiler does not inline any functions, so basically | |
43 | // every atomic function call results in this warning. I don't know any other | |
44 | // way to selectively disable just this one warning. | |
45 | #pragma system_header | |
46 | #endif | |
47 | ||
48 | namespace boost { | |
49 | namespace atomics { | |
50 | namespace detail { | |
51 | ||
52 | /*! | |
53 | * The function converts \c boost::memory_order values to the compiler-specific constants. | |
54 | * | |
55 | * NOTE: The intention is that the function is optimized away by the compiler, and the | |
56 | * compiler-specific constants are passed to the intrinsics. I know constexpr doesn't | |
57 | * work in this case because the standard atomics interface require memory ordering | |
58 | * constants to be passed as function arguments, at which point they stop being constexpr. | |
59 | * However it is crucial that the compiler sees constants and not runtime values, | |
60 | * because otherwise it just ignores the ordering value and always uses seq_cst. | |
61 | * This is the case with Intel C++ Compiler 14.0.3 (Composer XE 2013 SP1, update 3) and | |
62 | * gcc 4.8.2. Intel Compiler issues a warning in this case: | |
63 | * | |
64 | * warning #32013: Invalid memory order specified. Defaulting to seq_cst memory order. | |
65 | * | |
66 | * while gcc acts silently. | |
67 | * | |
68 | * To mitigate the problem ALL functions, including the atomic<> members must be | |
69 | * declared with BOOST_FORCEINLINE. In this case the compilers are able to see that | |
70 | * all functions are called with constant orderings and call intrinstcts properly. | |
71 | * | |
72 | * Unfortunately, this still doesn't work in debug mode as the compiler doesn't | |
73 | * inline functions even when marked with BOOST_FORCEINLINE. In this case all atomic | |
74 | * operaions will be executed with seq_cst semantics. | |
75 | */ | |
76 | BOOST_FORCEINLINE BOOST_CONSTEXPR int convert_memory_order_to_gcc(memory_order order) BOOST_NOEXCEPT | |
77 | { | |
78 | return (order == memory_order_relaxed ? __ATOMIC_RELAXED : (order == memory_order_consume ? __ATOMIC_CONSUME : | |
79 | (order == memory_order_acquire ? __ATOMIC_ACQUIRE : (order == memory_order_release ? __ATOMIC_RELEASE : | |
80 | (order == memory_order_acq_rel ? __ATOMIC_ACQ_REL : __ATOMIC_SEQ_CST))))); | |
81 | } | |
82 | ||
83 | template< typename T > | |
84 | struct gcc_atomic_operations | |
85 | { | |
86 | typedef T storage_type; | |
87 | ||
88 | // Note: In the current implementation, gcc_atomic_operations are used onlu when the particularly sized __atomic | |
89 | // intrinsics are always lock-free (i.e. the corresponding LOCK_FREE macro is 2). Therefore it is safe to | |
90 | // always set is_always_lock_free to true here. | |
91 | static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true; | |
92 | ||
93 | static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT | |
94 | { | |
95 | __atomic_store_n(&storage, v, atomics::detail::convert_memory_order_to_gcc(order)); | |
96 | } | |
97 | ||
98 | static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT | |
99 | { | |
100 | return __atomic_load_n(&storage, atomics::detail::convert_memory_order_to_gcc(order)); | |
101 | } | |
102 | ||
103 | static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT | |
104 | { | |
105 | return __atomic_fetch_add(&storage, v, atomics::detail::convert_memory_order_to_gcc(order)); | |
106 | } | |
107 | ||
108 | static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT | |
109 | { | |
110 | return __atomic_fetch_sub(&storage, v, atomics::detail::convert_memory_order_to_gcc(order)); | |
111 | } | |
112 | ||
113 | static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT | |
114 | { | |
115 | return __atomic_exchange_n(&storage, v, atomics::detail::convert_memory_order_to_gcc(order)); | |
116 | } | |
117 | ||
118 | static BOOST_FORCEINLINE bool compare_exchange_strong( | |
119 | storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT | |
120 | { | |
121 | return __atomic_compare_exchange_n | |
122 | ( | |
123 | &storage, &expected, desired, false, | |
124 | atomics::detail::convert_memory_order_to_gcc(success_order), | |
125 | atomics::detail::convert_memory_order_to_gcc(failure_order) | |
126 | ); | |
127 | } | |
128 | ||
129 | static BOOST_FORCEINLINE bool compare_exchange_weak( | |
130 | storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT | |
131 | { | |
132 | return __atomic_compare_exchange_n | |
133 | ( | |
134 | &storage, &expected, desired, true, | |
135 | atomics::detail::convert_memory_order_to_gcc(success_order), | |
136 | atomics::detail::convert_memory_order_to_gcc(failure_order) | |
137 | ); | |
138 | } | |
139 | ||
140 | static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT | |
141 | { | |
142 | return __atomic_fetch_and(&storage, v, atomics::detail::convert_memory_order_to_gcc(order)); | |
143 | } | |
144 | ||
145 | static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT | |
146 | { | |
147 | return __atomic_fetch_or(&storage, v, atomics::detail::convert_memory_order_to_gcc(order)); | |
148 | } | |
149 | ||
150 | static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT | |
151 | { | |
152 | return __atomic_fetch_xor(&storage, v, atomics::detail::convert_memory_order_to_gcc(order)); | |
153 | } | |
154 | ||
155 | static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT | |
156 | { | |
157 | return __atomic_test_and_set(&storage, atomics::detail::convert_memory_order_to_gcc(order)); | |
158 | } | |
159 | ||
160 | static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT | |
161 | { | |
162 | __atomic_clear(const_cast< storage_type* >(&storage), atomics::detail::convert_memory_order_to_gcc(order)); | |
163 | } | |
164 | ||
165 | static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile& storage) BOOST_NOEXCEPT | |
166 | { | |
167 | return __atomic_is_lock_free(sizeof(storage_type), &storage); | |
168 | } | |
169 | }; | |
170 | ||
171 | #if BOOST_ATOMIC_INT128_LOCK_FREE > 0 | |
172 | #if defined(__clang__) && defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B) | |
173 | ||
174 | // Workaround for clang bug: http://llvm.org/bugs/show_bug.cgi?id=19149 | |
175 | // Clang 3.4 does not implement 128-bit __atomic* intrinsics even though it defines __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 | |
176 | template< bool Signed > | |
177 | struct operations< 16u, Signed > : | |
178 | public cas_based_operations< gcc_dcas_x86_64< Signed > > | |
179 | { | |
180 | }; | |
181 | ||
182 | #else | |
183 | ||
184 | template< bool Signed > | |
185 | struct operations< 16u, Signed > : | |
186 | public gcc_atomic_operations< typename make_storage_type< 16u, Signed >::type > | |
187 | { | |
188 | typedef typename make_storage_type< 16u, Signed >::aligned aligned_storage_type; | |
189 | }; | |
190 | ||
191 | #endif | |
192 | #endif | |
193 | ||
194 | ||
195 | #if BOOST_ATOMIC_INT64_LOCK_FREE > 0 | |
196 | #if defined(__clang__) && defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B) | |
197 | ||
198 | // Workaround for clang bug http://llvm.org/bugs/show_bug.cgi?id=19355 | |
199 | template< bool Signed > | |
200 | struct operations< 8u, Signed > : | |
201 | public cas_based_operations< gcc_dcas_x86< Signed > > | |
202 | { | |
203 | }; | |
204 | ||
205 | #elif (BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 8 && __GCC_ATOMIC_LLONG_LOCK_FREE != BOOST_ATOMIC_LLONG_LOCK_FREE) ||\ | |
206 | (BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 8 && __GCC_ATOMIC_LONG_LOCK_FREE != BOOST_ATOMIC_LONG_LOCK_FREE) ||\ | |
207 | (BOOST_ATOMIC_DETAIL_SIZEOF_INT == 8 && __GCC_ATOMIC_INT_LOCK_FREE != BOOST_ATOMIC_INT_LOCK_FREE) ||\ | |
208 | (BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 8 && __GCC_ATOMIC_SHORT_LOCK_FREE != BOOST_ATOMIC_SHORT_LOCK_FREE) ||\ | |
209 | (BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 8 && __GCC_ATOMIC_WCHAR_T_LOCK_FREE != BOOST_ATOMIC_WCHAR_T_LOCK_FREE) | |
210 | ||
211 | #define BOOST_ATOMIC_DETAIL_INT64_EXTENDED | |
212 | ||
213 | template< bool Signed > | |
214 | struct operations< 8u, Signed > : | |
215 | public extending_cas_based_operations< gcc_atomic_operations< typename make_storage_type< 16u, Signed >::type >, 8u, Signed > | |
216 | { | |
217 | typedef typename make_storage_type< 16u, Signed >::aligned aligned_storage_type; | |
218 | }; | |
219 | ||
220 | #else | |
221 | ||
222 | template< bool Signed > | |
223 | struct operations< 8u, Signed > : | |
224 | public gcc_atomic_operations< typename make_storage_type< 8u, Signed >::type > | |
225 | { | |
226 | typedef typename make_storage_type< 8u, Signed >::aligned aligned_storage_type; | |
227 | }; | |
228 | ||
229 | #endif | |
230 | #endif | |
231 | ||
232 | #if BOOST_ATOMIC_INT32_LOCK_FREE > 0 | |
233 | #if (BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 4 && __GCC_ATOMIC_LLONG_LOCK_FREE != BOOST_ATOMIC_LLONG_LOCK_FREE) ||\ | |
234 | (BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 4 && __GCC_ATOMIC_LONG_LOCK_FREE != BOOST_ATOMIC_LONG_LOCK_FREE) ||\ | |
235 | (BOOST_ATOMIC_DETAIL_SIZEOF_INT == 4 && __GCC_ATOMIC_INT_LOCK_FREE != BOOST_ATOMIC_INT_LOCK_FREE) ||\ | |
236 | (BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 4 && __GCC_ATOMIC_SHORT_LOCK_FREE != BOOST_ATOMIC_SHORT_LOCK_FREE) ||\ | |
237 | (BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 4 && __GCC_ATOMIC_WCHAR_T_LOCK_FREE != BOOST_ATOMIC_WCHAR_T_LOCK_FREE) | |
238 | ||
239 | #define BOOST_ATOMIC_DETAIL_INT32_EXTENDED | |
240 | ||
241 | #if !defined(BOOST_ATOMIC_DETAIL_INT64_EXTENDED) | |
242 | ||
243 | template< bool Signed > | |
244 | struct operations< 4u, Signed > : | |
245 | public extending_cas_based_operations< gcc_atomic_operations< typename make_storage_type< 8u, Signed >::type >, 4u, Signed > | |
246 | { | |
247 | typedef typename make_storage_type< 8u, Signed >::aligned aligned_storage_type; | |
248 | }; | |
249 | ||
250 | #else // !defined(BOOST_ATOMIC_DETAIL_INT64_EXTENDED) | |
251 | ||
252 | template< bool Signed > | |
253 | struct operations< 4u, Signed > : | |
254 | public extending_cas_based_operations< gcc_atomic_operations< typename make_storage_type< 16u, Signed >::type >, 4u, Signed > | |
255 | { | |
256 | typedef typename make_storage_type< 16u, Signed >::aligned aligned_storage_type; | |
257 | }; | |
258 | ||
259 | #endif // !defined(BOOST_ATOMIC_DETAIL_INT64_EXTENDED) | |
260 | ||
261 | #else | |
262 | ||
263 | template< bool Signed > | |
264 | struct operations< 4u, Signed > : | |
265 | public gcc_atomic_operations< typename make_storage_type< 4u, Signed >::type > | |
266 | { | |
267 | typedef typename make_storage_type< 4u, Signed >::aligned aligned_storage_type; | |
268 | }; | |
269 | ||
270 | #endif | |
271 | #endif | |
272 | ||
273 | #if BOOST_ATOMIC_INT16_LOCK_FREE > 0 | |
274 | #if (BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 2 && __GCC_ATOMIC_LLONG_LOCK_FREE != BOOST_ATOMIC_LLONG_LOCK_FREE) ||\ | |
275 | (BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 2 && __GCC_ATOMIC_LONG_LOCK_FREE != BOOST_ATOMIC_LONG_LOCK_FREE) ||\ | |
276 | (BOOST_ATOMIC_DETAIL_SIZEOF_INT == 2 && __GCC_ATOMIC_INT_LOCK_FREE != BOOST_ATOMIC_INT_LOCK_FREE) ||\ | |
277 | (BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 2 && __GCC_ATOMIC_SHORT_LOCK_FREE != BOOST_ATOMIC_SHORT_LOCK_FREE) ||\ | |
278 | (BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 2 && __GCC_ATOMIC_WCHAR_T_LOCK_FREE != BOOST_ATOMIC_WCHAR_T_LOCK_FREE) | |
279 | ||
280 | #define BOOST_ATOMIC_DETAIL_INT16_EXTENDED | |
281 | ||
282 | #if !defined(BOOST_ATOMIC_DETAIL_INT32_EXTENDED) | |
283 | ||
284 | template< bool Signed > | |
285 | struct operations< 2u, Signed > : | |
286 | public extending_cas_based_operations< gcc_atomic_operations< typename make_storage_type< 4u, Signed >::type >, 2u, Signed > | |
287 | { | |
288 | typedef typename make_storage_type< 4u, Signed >::aligned aligned_storage_type; | |
289 | }; | |
290 | ||
291 | #elif !defined(BOOST_ATOMIC_DETAIL_INT64_EXTENDED) | |
292 | ||
293 | template< bool Signed > | |
294 | struct operations< 2u, Signed > : | |
295 | public extending_cas_based_operations< gcc_atomic_operations< typename make_storage_type< 8u, Signed >::type >, 2u, Signed > | |
296 | { | |
297 | typedef typename make_storage_type< 8u, Signed >::aligned aligned_storage_type; | |
298 | }; | |
299 | ||
300 | #else | |
301 | ||
302 | template< bool Signed > | |
303 | struct operations< 2u, Signed > : | |
304 | public extending_cas_based_operations< gcc_atomic_operations< typename make_storage_type< 16u, Signed >::type >, 2u, Signed > | |
305 | { | |
306 | typedef typename make_storage_type< 16u, Signed >::aligned aligned_storage_type; | |
307 | }; | |
308 | ||
309 | #endif | |
310 | ||
311 | #else | |
312 | ||
313 | template< bool Signed > | |
314 | struct operations< 2u, Signed > : | |
315 | public gcc_atomic_operations< typename make_storage_type< 2u, Signed >::type > | |
316 | { | |
317 | typedef typename make_storage_type< 2u, Signed >::aligned aligned_storage_type; | |
318 | }; | |
319 | ||
320 | #endif | |
321 | #endif | |
322 | ||
323 | #if BOOST_ATOMIC_INT8_LOCK_FREE > 0 | |
324 | #if (BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 1 && __GCC_ATOMIC_LLONG_LOCK_FREE != BOOST_ATOMIC_LLONG_LOCK_FREE) ||\ | |
325 | (BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 1 && __GCC_ATOMIC_LONG_LOCK_FREE != BOOST_ATOMIC_LONG_LOCK_FREE) ||\ | |
326 | (BOOST_ATOMIC_DETAIL_SIZEOF_INT == 1 && __GCC_ATOMIC_INT_LOCK_FREE != BOOST_ATOMIC_INT_LOCK_FREE) ||\ | |
327 | (BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 1 && __GCC_ATOMIC_SHORT_LOCK_FREE != BOOST_ATOMIC_SHORT_LOCK_FREE) ||\ | |
328 | (BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 1 && __GCC_ATOMIC_WCHAR_T_LOCK_FREE != BOOST_ATOMIC_WCHAR_T_LOCK_FREE) ||\ | |
329 | (__GCC_ATOMIC_CHAR_LOCK_FREE != BOOST_ATOMIC_CHAR_LOCK_FREE) ||\ | |
330 | (__GCC_ATOMIC_BOOL_LOCK_FREE != BOOST_ATOMIC_BOOL_LOCK_FREE) | |
331 | ||
332 | #if !defined(BOOST_ATOMIC_DETAIL_INT16_EXTENDED) | |
333 | ||
334 | template< bool Signed > | |
335 | struct operations< 1u, Signed > : | |
336 | public extending_cas_based_operations< gcc_atomic_operations< typename make_storage_type< 2u, Signed >::type >, 1u, Signed > | |
337 | { | |
338 | typedef typename make_storage_type< 2u, Signed >::aligned aligned_storage_type; | |
339 | }; | |
340 | ||
341 | #elif !defined(BOOST_ATOMIC_DETAIL_INT32_EXTENDED) | |
342 | ||
343 | template< bool Signed > | |
344 | struct operations< 1u, Signed > : | |
345 | public extending_cas_based_operations< gcc_atomic_operations< typename make_storage_type< 4u, Signed >::type >, 1u, Signed > | |
346 | { | |
347 | typedef typename make_storage_type< 4u, Signed >::aligned aligned_storage_type; | |
348 | }; | |
349 | ||
350 | #elif !defined(BOOST_ATOMIC_DETAIL_INT64_EXTENDED) | |
351 | ||
352 | template< bool Signed > | |
353 | struct operations< 1u, Signed > : | |
354 | public extending_cas_based_operations< gcc_atomic_operations< typename make_storage_type< 8u, Signed >::type >, 1u, Signed > | |
355 | { | |
356 | typedef typename make_storage_type< 8u, Signed >::aligned aligned_storage_type; | |
357 | }; | |
358 | ||
359 | #else | |
360 | ||
361 | template< bool Signed > | |
362 | struct operations< 1u, Signed > : | |
363 | public extending_cas_based_operations< gcc_atomic_operations< typename make_storage_type< 16u, Signed >::type >, 1u, Signed > | |
364 | { | |
365 | typedef typename make_storage_type< 16u, Signed >::aligned aligned_storage_type; | |
366 | }; | |
367 | ||
368 | #endif | |
369 | ||
370 | #else | |
371 | ||
372 | template< bool Signed > | |
373 | struct operations< 1u, Signed > : | |
374 | public gcc_atomic_operations< typename make_storage_type< 1u, Signed >::type > | |
375 | { | |
376 | typedef typename make_storage_type< 1u, Signed >::aligned aligned_storage_type; | |
377 | }; | |
378 | ||
379 | #endif | |
380 | #endif | |
381 | ||
382 | #undef BOOST_ATOMIC_DETAIL_INT16_EXTENDED | |
383 | #undef BOOST_ATOMIC_DETAIL_INT32_EXTENDED | |
384 | #undef BOOST_ATOMIC_DETAIL_INT64_EXTENDED | |
385 | ||
386 | BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT | |
387 | { | |
388 | __atomic_thread_fence(atomics::detail::convert_memory_order_to_gcc(order)); | |
389 | } | |
390 | ||
391 | BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT | |
392 | { | |
393 | __atomic_signal_fence(atomics::detail::convert_memory_order_to_gcc(order)); | |
394 | } | |
395 | ||
396 | } // namespace detail | |
397 | } // namespace atomics | |
398 | } // namespace boost | |
399 | ||
400 | #endif // BOOST_ATOMIC_DETAIL_OPS_GCC_ATOMIC_HPP_INCLUDED_ |