Chris@102
|
1 /*
|
Chris@102
|
2 * Distributed under the Boost Software License, Version 1.0.
|
Chris@102
|
3 * (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@102
|
4 * http://www.boost.org/LICENSE_1_0.txt)
|
Chris@102
|
5 *
|
Chris@102
|
6 * Copyright (c) 2009 Helge Bahmann
|
Chris@102
|
7 * Copyright (c) 2012 Tim Blechmann
|
Chris@102
|
8 * Copyright (c) 2014 Andrey Semashev
|
Chris@102
|
9 */
|
Chris@102
|
10 /*!
|
Chris@102
|
11 * \file atomic/detail/ops_msvc_x86.hpp
|
Chris@102
|
12 *
|
Chris@102
|
13 * This header contains implementation of the \c operations template.
|
Chris@102
|
14 */
|
Chris@102
|
15
|
Chris@102
|
16 #ifndef BOOST_ATOMIC_DETAIL_OPS_MSVC_X86_HPP_INCLUDED_
|
Chris@102
|
17 #define BOOST_ATOMIC_DETAIL_OPS_MSVC_X86_HPP_INCLUDED_
|
Chris@102
|
18
|
Chris@102
|
19 #include <boost/memory_order.hpp>
|
Chris@102
|
20 #include <boost/type_traits/make_signed.hpp>
|
Chris@102
|
21 #include <boost/atomic/detail/config.hpp>
|
Chris@102
|
22 #include <boost/atomic/detail/interlocked.hpp>
|
Chris@102
|
23 #include <boost/atomic/detail/storage_type.hpp>
|
Chris@102
|
24 #include <boost/atomic/detail/operations_fwd.hpp>
|
Chris@102
|
25 #include <boost/atomic/capabilities.hpp>
|
Chris@102
|
26 #if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B) || defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B)
|
Chris@102
|
27 #include <boost/cstdint.hpp>
|
Chris@102
|
28 #include <boost/atomic/detail/ops_cas_based.hpp>
|
Chris@102
|
29 #endif
|
Chris@102
|
30 #include <boost/atomic/detail/ops_msvc_common.hpp>
|
Chris@102
|
31 #if !defined(_M_IX86) && !(defined(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE8) && defined(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE16))
|
Chris@102
|
32 #include <boost/atomic/detail/ops_extending_cas_based.hpp>
|
Chris@102
|
33 #endif
|
Chris@102
|
34
|
Chris@102
|
35 #ifdef BOOST_HAS_PRAGMA_ONCE
|
Chris@102
|
36 #pragma once
|
Chris@102
|
37 #endif
|
Chris@102
|
38
|
Chris@102
|
39 #if defined(BOOST_MSVC)
|
Chris@102
|
40 #pragma warning(push)
|
Chris@102
|
41 // frame pointer register 'ebx' modified by inline assembly code. See the note below.
|
Chris@102
|
42 #pragma warning(disable: 4731)
|
Chris@102
|
43 #endif
|
Chris@102
|
44
|
Chris@102
|
45 #if defined(_MSC_VER) && (defined(_M_AMD64) || (defined(_M_IX86) && defined(_M_IX86_FP) && _M_IX86_FP >= 2))
|
Chris@102
|
46 extern "C" void _mm_mfence(void);
|
Chris@102
|
47 #if defined(BOOST_MSVC)
|
Chris@102
|
48 #pragma intrinsic(_mm_mfence)
|
Chris@102
|
49 #endif
|
Chris@102
|
50 #endif
|
Chris@102
|
51
|
Chris@102
|
52 namespace boost {
|
Chris@102
|
53 namespace atomics {
|
Chris@102
|
54 namespace detail {
|
Chris@102
|
55
|
Chris@102
|
56 /*
|
Chris@102
|
57 * Implementation note for asm blocks.
|
Chris@102
|
58 *
|
Chris@102
|
59 * http://msdn.microsoft.com/en-us/data/k1a8ss06%28v=vs.105%29
|
Chris@102
|
60 *
|
Chris@102
|
61 * Some SSE types require eight-byte stack alignment, forcing the compiler to emit dynamic stack-alignment code.
|
Chris@102
|
62 * To be able to access both the local variables and the function parameters after the alignment, the compiler
|
Chris@102
|
63 * maintains two frame pointers. If the compiler performs frame pointer omission (FPO), it will use EBP and ESP.
|
Chris@102
|
64 * If the compiler does not perform FPO, it will use EBX and EBP. To ensure code runs correctly, do not modify EBX
|
Chris@102
|
65 * in asm code if the function requires dynamic stack alignment as it could modify the frame pointer.
|
Chris@102
|
66 * Either move the eight-byte aligned types out of the function, or avoid using EBX.
|
Chris@102
|
67 *
|
Chris@102
|
68 * Since we have no way of knowing that the compiler uses FPO, we have to always save and restore ebx
|
Chris@102
|
69 * whenever we have to clobber it. Additionally, we disable warning C4731 above so that the compiler
|
Chris@102
|
70 * doesn't spam about ebx use.
|
Chris@102
|
71 */
|
Chris@102
|
72
|
Chris@102
|
73 struct msvc_x86_operations_base
|
Chris@102
|
74 {
|
Chris@102
|
75 static BOOST_FORCEINLINE void hardware_full_fence() BOOST_NOEXCEPT
|
Chris@102
|
76 {
|
Chris@102
|
77 #if defined(_MSC_VER) && (defined(_M_AMD64) || (defined(_M_IX86) && defined(_M_IX86_FP) && _M_IX86_FP >= 2))
|
Chris@102
|
78 // Use mfence only if SSE2 is available
|
Chris@102
|
79 _mm_mfence();
|
Chris@102
|
80 #else
|
Chris@102
|
81 long tmp;
|
Chris@102
|
82 BOOST_ATOMIC_INTERLOCKED_EXCHANGE(&tmp, 0);
|
Chris@102
|
83 #endif
|
Chris@102
|
84 }
|
Chris@102
|
85
|
Chris@102
|
86 static BOOST_FORCEINLINE void fence_before(memory_order) BOOST_NOEXCEPT
|
Chris@102
|
87 {
|
Chris@102
|
88 BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
|
Chris@102
|
89 }
|
Chris@102
|
90
|
Chris@102
|
91 static BOOST_FORCEINLINE void fence_after(memory_order) BOOST_NOEXCEPT
|
Chris@102
|
92 {
|
Chris@102
|
93 BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
|
Chris@102
|
94 }
|
Chris@102
|
95
|
Chris@102
|
96 static BOOST_FORCEINLINE void fence_after_load(memory_order) BOOST_NOEXCEPT
|
Chris@102
|
97 {
|
Chris@102
|
98 BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
|
Chris@102
|
99
|
Chris@102
|
100 // On x86 and x86_64 there is no need for a hardware barrier,
|
Chris@102
|
101 // even if seq_cst memory order is requested, because all
|
Chris@102
|
102 // seq_cst writes are implemented with lock-prefixed operations
|
Chris@102
|
103 // or xchg which has implied lock prefix. Therefore normal loads
|
Chris@102
|
104 // are already ordered with seq_cst stores on these architectures.
|
Chris@102
|
105 }
|
Chris@102
|
106 };
|
Chris@102
|
107
|
Chris@102
|
108 template< typename T, typename Derived >
|
Chris@102
|
109 struct msvc_x86_operations :
|
Chris@102
|
110 public msvc_x86_operations_base
|
Chris@102
|
111 {
|
Chris@102
|
112 typedef T storage_type;
|
Chris@102
|
113
|
Chris@102
|
114 static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
Chris@102
|
115 {
|
Chris@102
|
116 if (order != memory_order_seq_cst)
|
Chris@102
|
117 {
|
Chris@102
|
118 fence_before(order);
|
Chris@102
|
119 storage = v;
|
Chris@102
|
120 fence_after(order);
|
Chris@102
|
121 }
|
Chris@102
|
122 else
|
Chris@102
|
123 {
|
Chris@102
|
124 Derived::exchange(storage, v, order);
|
Chris@102
|
125 }
|
Chris@102
|
126 }
|
Chris@102
|
127
|
Chris@102
|
128 static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
|
Chris@102
|
129 {
|
Chris@102
|
130 storage_type v = storage;
|
Chris@102
|
131 fence_after_load(order);
|
Chris@102
|
132 return v;
|
Chris@102
|
133 }
|
Chris@102
|
134
|
Chris@102
|
135 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
Chris@102
|
136 {
|
Chris@102
|
137 typedef typename make_signed< storage_type >::type signed_storage_type;
|
Chris@102
|
138 return Derived::fetch_add(storage, static_cast< storage_type >(-static_cast< signed_storage_type >(v)), order);
|
Chris@102
|
139 }
|
Chris@102
|
140
|
Chris@102
|
141 static BOOST_FORCEINLINE bool compare_exchange_weak(
|
Chris@102
|
142 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
|
Chris@102
|
143 {
|
Chris@102
|
144 return Derived::compare_exchange_strong(storage, expected, desired, success_order, failure_order);
|
Chris@102
|
145 }
|
Chris@102
|
146
|
Chris@102
|
147 static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
Chris@102
|
148 {
|
Chris@102
|
149 return !!Derived::exchange(storage, (storage_type)1, order);
|
Chris@102
|
150 }
|
Chris@102
|
151
|
Chris@102
|
152 static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
|
Chris@102
|
153 {
|
Chris@102
|
154 store(storage, (storage_type)0, order);
|
Chris@102
|
155 }
|
Chris@102
|
156
|
Chris@102
|
157 static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
|
Chris@102
|
158 {
|
Chris@102
|
159 return true;
|
Chris@102
|
160 }
|
Chris@102
|
161 };
|
Chris@102
|
162
|
Chris@102
|
163 template< bool Signed >
|
Chris@102
|
164 struct operations< 4u, Signed > :
|
Chris@102
|
165 public msvc_x86_operations< typename make_storage_type< 4u, Signed >::type, operations< 4u, Signed > >
|
Chris@102
|
166 {
|
Chris@102
|
167 typedef msvc_x86_operations< typename make_storage_type< 4u, Signed >::type, operations< 4u, Signed > > base_type;
|
Chris@102
|
168 typedef typename base_type::storage_type storage_type;
|
Chris@102
|
169
|
Chris@102
|
170 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
|
Chris@102
|
171 {
|
Chris@102
|
172 return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD(&storage, v));
|
Chris@102
|
173 }
|
Chris@102
|
174
|
Chris@102
|
175 static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
|
Chris@102
|
176 {
|
Chris@102
|
177 return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE(&storage, v));
|
Chris@102
|
178 }
|
Chris@102
|
179
|
Chris@102
|
180 static BOOST_FORCEINLINE bool compare_exchange_strong(
|
Chris@102
|
181 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT
|
Chris@102
|
182 {
|
Chris@102
|
183 storage_type previous = expected;
|
Chris@102
|
184 storage_type old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE(&storage, desired, previous));
|
Chris@102
|
185 expected = old_val;
|
Chris@102
|
186 return (previous == old_val);
|
Chris@102
|
187 }
|
Chris@102
|
188
|
Chris@102
|
189 #if defined(BOOST_ATOMIC_INTERLOCKED_AND)
|
Chris@102
|
190 static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
|
Chris@102
|
191 {
|
Chris@102
|
192 return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND(&storage, v));
|
Chris@102
|
193 }
|
Chris@102
|
194 #else
|
Chris@102
|
195 static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
Chris@102
|
196 {
|
Chris@102
|
197 storage_type res = storage;
|
Chris@102
|
198 while (!compare_exchange_strong(storage, res, res & v, order, memory_order_relaxed)) {}
|
Chris@102
|
199 return res;
|
Chris@102
|
200 }
|
Chris@102
|
201 #endif
|
Chris@102
|
202
|
Chris@102
|
203 #if defined(BOOST_ATOMIC_INTERLOCKED_OR)
|
Chris@102
|
204 static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
|
Chris@102
|
205 {
|
Chris@102
|
206 return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR(&storage, v));
|
Chris@102
|
207 }
|
Chris@102
|
208 #else
|
Chris@102
|
209 static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
Chris@102
|
210 {
|
Chris@102
|
211 storage_type res = storage;
|
Chris@102
|
212 while (!compare_exchange_strong(storage, res, res | v, order, memory_order_relaxed)) {}
|
Chris@102
|
213 return res;
|
Chris@102
|
214 }
|
Chris@102
|
215 #endif
|
Chris@102
|
216
|
Chris@102
|
217 #if defined(BOOST_ATOMIC_INTERLOCKED_XOR)
|
Chris@102
|
218 static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
|
Chris@102
|
219 {
|
Chris@102
|
220 return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR(&storage, v));
|
Chris@102
|
221 }
|
Chris@102
|
222 #else
|
Chris@102
|
223 static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
Chris@102
|
224 {
|
Chris@102
|
225 storage_type res = storage;
|
Chris@102
|
226 while (!compare_exchange_strong(storage, res, res ^ v, order, memory_order_relaxed)) {}
|
Chris@102
|
227 return res;
|
Chris@102
|
228 }
|
Chris@102
|
229 #endif
|
Chris@102
|
230 };
|
Chris@102
|
231
|
Chris@102
|
232 #if defined(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE8)
|
Chris@102
|
233
|
Chris@102
|
234 template< bool Signed >
|
Chris@102
|
235 struct operations< 1u, Signed > :
|
Chris@102
|
236 public msvc_x86_operations< typename make_storage_type< 1u, Signed >::type, operations< 1u, Signed > >
|
Chris@102
|
237 {
|
Chris@102
|
238 typedef msvc_x86_operations< typename make_storage_type< 1u, Signed >::type, operations< 1u, Signed > > base_type;
|
Chris@102
|
239 typedef typename base_type::storage_type storage_type;
|
Chris@102
|
240
|
Chris@102
|
241 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
|
Chris@102
|
242 {
|
Chris@102
|
243 return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD8(&storage, v));
|
Chris@102
|
244 }
|
Chris@102
|
245
|
Chris@102
|
246 static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
|
Chris@102
|
247 {
|
Chris@102
|
248 return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE8(&storage, v));
|
Chris@102
|
249 }
|
Chris@102
|
250
|
Chris@102
|
251 static BOOST_FORCEINLINE bool compare_exchange_strong(
|
Chris@102
|
252 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT
|
Chris@102
|
253 {
|
Chris@102
|
254 storage_type previous = expected;
|
Chris@102
|
255 storage_type old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE8(&storage, desired, previous));
|
Chris@102
|
256 expected = old_val;
|
Chris@102
|
257 return (previous == old_val);
|
Chris@102
|
258 }
|
Chris@102
|
259
|
Chris@102
|
260 static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
|
Chris@102
|
261 {
|
Chris@102
|
262 return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND8(&storage, v));
|
Chris@102
|
263 }
|
Chris@102
|
264
|
Chris@102
|
265 static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
|
Chris@102
|
266 {
|
Chris@102
|
267 return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR8(&storage, v));
|
Chris@102
|
268 }
|
Chris@102
|
269
|
Chris@102
|
270 static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
|
Chris@102
|
271 {
|
Chris@102
|
272 return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR8(&storage, v));
|
Chris@102
|
273 }
|
Chris@102
|
274 };
|
Chris@102
|
275
|
Chris@102
|
276 #elif defined(_M_IX86)
|
Chris@102
|
277
|
Chris@102
|
278 template< bool Signed >
|
Chris@102
|
279 struct operations< 1u, Signed > :
|
Chris@102
|
280 public msvc_x86_operations< typename make_storage_type< 1u, Signed >::type, operations< 1u, Signed > >
|
Chris@102
|
281 {
|
Chris@102
|
282 typedef msvc_x86_operations< typename make_storage_type< 1u, Signed >::type, operations< 1u, Signed > > base_type;
|
Chris@102
|
283 typedef typename base_type::storage_type storage_type;
|
Chris@102
|
284
|
Chris@102
|
285 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
Chris@102
|
286 {
|
Chris@102
|
287 base_type::fence_before(order);
|
Chris@102
|
288 __asm
|
Chris@102
|
289 {
|
Chris@102
|
290 mov edx, storage
|
Chris@102
|
291 movzx eax, v
|
Chris@102
|
292 lock xadd byte ptr [edx], al
|
Chris@102
|
293 mov v, al
|
Chris@102
|
294 };
|
Chris@102
|
295 base_type::fence_after(order);
|
Chris@102
|
296 return v;
|
Chris@102
|
297 }
|
Chris@102
|
298
|
Chris@102
|
299 static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
Chris@102
|
300 {
|
Chris@102
|
301 base_type::fence_before(order);
|
Chris@102
|
302 __asm
|
Chris@102
|
303 {
|
Chris@102
|
304 mov edx, storage
|
Chris@102
|
305 movzx eax, v
|
Chris@102
|
306 xchg byte ptr [edx], al
|
Chris@102
|
307 mov v, al
|
Chris@102
|
308 };
|
Chris@102
|
309 base_type::fence_after(order);
|
Chris@102
|
310 return v;
|
Chris@102
|
311 }
|
Chris@102
|
312
|
Chris@102
|
313 static BOOST_FORCEINLINE bool compare_exchange_strong(
|
Chris@102
|
314 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order) BOOST_NOEXCEPT
|
Chris@102
|
315 {
|
Chris@102
|
316 base_type::fence_before(success_order);
|
Chris@102
|
317 bool success;
|
Chris@102
|
318 __asm
|
Chris@102
|
319 {
|
Chris@102
|
320 mov esi, expected
|
Chris@102
|
321 mov edi, storage
|
Chris@102
|
322 movzx eax, byte ptr [esi]
|
Chris@102
|
323 movzx edx, desired
|
Chris@102
|
324 lock cmpxchg byte ptr [edi], dl
|
Chris@102
|
325 mov byte ptr [esi], al
|
Chris@102
|
326 sete success
|
Chris@102
|
327 };
|
Chris@102
|
328 // The success and failure fences are equivalent anyway
|
Chris@102
|
329 base_type::fence_after(success_order);
|
Chris@102
|
330 return success;
|
Chris@102
|
331 }
|
Chris@102
|
332
|
Chris@102
|
333 static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
Chris@102
|
334 {
|
Chris@102
|
335 base_type::fence_before(order);
|
Chris@102
|
336 int backup;
|
Chris@102
|
337 __asm
|
Chris@102
|
338 {
|
Chris@102
|
339 mov backup, ebx
|
Chris@102
|
340 xor edx, edx
|
Chris@102
|
341 mov edi, storage
|
Chris@102
|
342 movzx ebx, v
|
Chris@102
|
343 movzx eax, byte ptr [edi]
|
Chris@102
|
344 align 16
|
Chris@102
|
345 again:
|
Chris@102
|
346 mov dl, al
|
Chris@102
|
347 and dl, bl
|
Chris@102
|
348 lock cmpxchg byte ptr [edi], dl
|
Chris@102
|
349 jne again
|
Chris@102
|
350 mov v, al
|
Chris@102
|
351 mov ebx, backup
|
Chris@102
|
352 };
|
Chris@102
|
353 base_type::fence_after(order);
|
Chris@102
|
354 return v;
|
Chris@102
|
355 }
|
Chris@102
|
356
|
Chris@102
|
357 static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
Chris@102
|
358 {
|
Chris@102
|
359 base_type::fence_before(order);
|
Chris@102
|
360 int backup;
|
Chris@102
|
361 __asm
|
Chris@102
|
362 {
|
Chris@102
|
363 mov backup, ebx
|
Chris@102
|
364 xor edx, edx
|
Chris@102
|
365 mov edi, storage
|
Chris@102
|
366 movzx ebx, v
|
Chris@102
|
367 movzx eax, byte ptr [edi]
|
Chris@102
|
368 align 16
|
Chris@102
|
369 again:
|
Chris@102
|
370 mov dl, al
|
Chris@102
|
371 or dl, bl
|
Chris@102
|
372 lock cmpxchg byte ptr [edi], dl
|
Chris@102
|
373 jne again
|
Chris@102
|
374 mov v, al
|
Chris@102
|
375 mov ebx, backup
|
Chris@102
|
376 };
|
Chris@102
|
377 base_type::fence_after(order);
|
Chris@102
|
378 return v;
|
Chris@102
|
379 }
|
Chris@102
|
380
|
Chris@102
|
381 static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
Chris@102
|
382 {
|
Chris@102
|
383 base_type::fence_before(order);
|
Chris@102
|
384 int backup;
|
Chris@102
|
385 __asm
|
Chris@102
|
386 {
|
Chris@102
|
387 mov backup, ebx
|
Chris@102
|
388 xor edx, edx
|
Chris@102
|
389 mov edi, storage
|
Chris@102
|
390 movzx ebx, v
|
Chris@102
|
391 movzx eax, byte ptr [edi]
|
Chris@102
|
392 align 16
|
Chris@102
|
393 again:
|
Chris@102
|
394 mov dl, al
|
Chris@102
|
395 xor dl, bl
|
Chris@102
|
396 lock cmpxchg byte ptr [edi], dl
|
Chris@102
|
397 jne again
|
Chris@102
|
398 mov v, al
|
Chris@102
|
399 mov ebx, backup
|
Chris@102
|
400 };
|
Chris@102
|
401 base_type::fence_after(order);
|
Chris@102
|
402 return v;
|
Chris@102
|
403 }
|
Chris@102
|
404 };
|
Chris@102
|
405
|
Chris@102
|
406 #else
|
Chris@102
|
407
|
Chris@102
|
408 template< bool Signed >
|
Chris@102
|
409 struct operations< 1u, Signed > :
|
Chris@102
|
410 public extending_cas_based_operations< operations< 4u, Signed >, 1u, Signed >
|
Chris@102
|
411 {
|
Chris@102
|
412 };
|
Chris@102
|
413
|
Chris@102
|
414 #endif
|
Chris@102
|
415
|
Chris@102
|
416 #if defined(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE16)
|
Chris@102
|
417
|
Chris@102
|
418 template< bool Signed >
|
Chris@102
|
419 struct operations< 2u, Signed > :
|
Chris@102
|
420 public msvc_x86_operations< typename make_storage_type< 2u, Signed >::type, operations< 2u, Signed > >
|
Chris@102
|
421 {
|
Chris@102
|
422 typedef msvc_x86_operations< typename make_storage_type< 2u, Signed >::type, operations< 2u, Signed > > base_type;
|
Chris@102
|
423 typedef typename base_type::storage_type storage_type;
|
Chris@102
|
424
|
Chris@102
|
425 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
|
Chris@102
|
426 {
|
Chris@102
|
427 return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD16(&storage, v));
|
Chris@102
|
428 }
|
Chris@102
|
429
|
Chris@102
|
430 static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
|
Chris@102
|
431 {
|
Chris@102
|
432 return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE16(&storage, v));
|
Chris@102
|
433 }
|
Chris@102
|
434
|
Chris@102
|
435 static BOOST_FORCEINLINE bool compare_exchange_strong(
|
Chris@102
|
436 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT
|
Chris@102
|
437 {
|
Chris@102
|
438 storage_type previous = expected;
|
Chris@102
|
439 storage_type old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE16(&storage, desired, previous));
|
Chris@102
|
440 expected = old_val;
|
Chris@102
|
441 return (previous == old_val);
|
Chris@102
|
442 }
|
Chris@102
|
443
|
Chris@102
|
444 static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
|
Chris@102
|
445 {
|
Chris@102
|
446 return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND16(&storage, v));
|
Chris@102
|
447 }
|
Chris@102
|
448
|
Chris@102
|
449 static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
|
Chris@102
|
450 {
|
Chris@102
|
451 return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR16(&storage, v));
|
Chris@102
|
452 }
|
Chris@102
|
453
|
Chris@102
|
454 static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
|
Chris@102
|
455 {
|
Chris@102
|
456 return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR16(&storage, v));
|
Chris@102
|
457 }
|
Chris@102
|
458 };
|
Chris@102
|
459
|
Chris@102
|
460 #elif defined(_M_IX86)
|
Chris@102
|
461
|
Chris@102
|
462 template< bool Signed >
|
Chris@102
|
463 struct operations< 2u, Signed > :
|
Chris@102
|
464 public msvc_x86_operations< typename make_storage_type< 2u, Signed >::type, operations< 2u, Signed > >
|
Chris@102
|
465 {
|
Chris@102
|
466 typedef msvc_x86_operations< typename make_storage_type< 2u, Signed >::type, operations< 2u, Signed > > base_type;
|
Chris@102
|
467 typedef typename base_type::storage_type storage_type;
|
Chris@102
|
468
|
Chris@102
|
469 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
Chris@102
|
470 {
|
Chris@102
|
471 base_type::fence_before(order);
|
Chris@102
|
472 __asm
|
Chris@102
|
473 {
|
Chris@102
|
474 mov edx, storage
|
Chris@102
|
475 movzx eax, v
|
Chris@102
|
476 lock xadd word ptr [edx], ax
|
Chris@102
|
477 mov v, ax
|
Chris@102
|
478 };
|
Chris@102
|
479 base_type::fence_after(order);
|
Chris@102
|
480 return v;
|
Chris@102
|
481 }
|
Chris@102
|
482
|
Chris@102
|
483 static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
Chris@102
|
484 {
|
Chris@102
|
485 base_type::fence_before(order);
|
Chris@102
|
486 __asm
|
Chris@102
|
487 {
|
Chris@102
|
488 mov edx, storage
|
Chris@102
|
489 movzx eax, v
|
Chris@102
|
490 xchg word ptr [edx], ax
|
Chris@102
|
491 mov v, ax
|
Chris@102
|
492 };
|
Chris@102
|
493 base_type::fence_after(order);
|
Chris@102
|
494 return v;
|
Chris@102
|
495 }
|
Chris@102
|
496
|
Chris@102
|
497 static BOOST_FORCEINLINE bool compare_exchange_strong(
|
Chris@102
|
498 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order) BOOST_NOEXCEPT
|
Chris@102
|
499 {
|
Chris@102
|
500 base_type::fence_before(success_order);
|
Chris@102
|
501 bool success;
|
Chris@102
|
502 __asm
|
Chris@102
|
503 {
|
Chris@102
|
504 mov esi, expected
|
Chris@102
|
505 mov edi, storage
|
Chris@102
|
506 movzx eax, word ptr [esi]
|
Chris@102
|
507 movzx edx, desired
|
Chris@102
|
508 lock cmpxchg word ptr [edi], dx
|
Chris@102
|
509 mov word ptr [esi], ax
|
Chris@102
|
510 sete success
|
Chris@102
|
511 };
|
Chris@102
|
512 // The success and failure fences are equivalent anyway
|
Chris@102
|
513 base_type::fence_after(success_order);
|
Chris@102
|
514 return success;
|
Chris@102
|
515 }
|
Chris@102
|
516
|
Chris@102
|
517 static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
Chris@102
|
518 {
|
Chris@102
|
519 base_type::fence_before(order);
|
Chris@102
|
520 int backup;
|
Chris@102
|
521 __asm
|
Chris@102
|
522 {
|
Chris@102
|
523 mov backup, ebx
|
Chris@102
|
524 xor edx, edx
|
Chris@102
|
525 mov edi, storage
|
Chris@102
|
526 movzx ebx, v
|
Chris@102
|
527 movzx eax, word ptr [edi]
|
Chris@102
|
528 align 16
|
Chris@102
|
529 again:
|
Chris@102
|
530 mov dx, ax
|
Chris@102
|
531 and dx, bx
|
Chris@102
|
532 lock cmpxchg word ptr [edi], dx
|
Chris@102
|
533 jne again
|
Chris@102
|
534 mov v, ax
|
Chris@102
|
535 mov ebx, backup
|
Chris@102
|
536 };
|
Chris@102
|
537 base_type::fence_after(order);
|
Chris@102
|
538 return v;
|
Chris@102
|
539 }
|
Chris@102
|
540
|
Chris@102
|
541 static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
Chris@102
|
542 {
|
Chris@102
|
543 base_type::fence_before(order);
|
Chris@102
|
544 int backup;
|
Chris@102
|
545 __asm
|
Chris@102
|
546 {
|
Chris@102
|
547 mov backup, ebx
|
Chris@102
|
548 xor edx, edx
|
Chris@102
|
549 mov edi, storage
|
Chris@102
|
550 movzx ebx, v
|
Chris@102
|
551 movzx eax, word ptr [edi]
|
Chris@102
|
552 align 16
|
Chris@102
|
553 again:
|
Chris@102
|
554 mov dx, ax
|
Chris@102
|
555 or dx, bx
|
Chris@102
|
556 lock cmpxchg word ptr [edi], dx
|
Chris@102
|
557 jne again
|
Chris@102
|
558 mov v, ax
|
Chris@102
|
559 mov ebx, backup
|
Chris@102
|
560 };
|
Chris@102
|
561 base_type::fence_after(order);
|
Chris@102
|
562 return v;
|
Chris@102
|
563 }
|
Chris@102
|
564
|
Chris@102
|
565 static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
|
Chris@102
|
566 {
|
Chris@102
|
567 base_type::fence_before(order);
|
Chris@102
|
568 int backup;
|
Chris@102
|
569 __asm
|
Chris@102
|
570 {
|
Chris@102
|
571 mov backup, ebx
|
Chris@102
|
572 xor edx, edx
|
Chris@102
|
573 mov edi, storage
|
Chris@102
|
574 movzx ebx, v
|
Chris@102
|
575 movzx eax, word ptr [edi]
|
Chris@102
|
576 align 16
|
Chris@102
|
577 again:
|
Chris@102
|
578 mov dx, ax
|
Chris@102
|
579 xor dx, bx
|
Chris@102
|
580 lock cmpxchg word ptr [edi], dx
|
Chris@102
|
581 jne again
|
Chris@102
|
582 mov v, ax
|
Chris@102
|
583 mov ebx, backup
|
Chris@102
|
584 };
|
Chris@102
|
585 base_type::fence_after(order);
|
Chris@102
|
586 return v;
|
Chris@102
|
587 }
|
Chris@102
|
588 };
|
Chris@102
|
589
|
Chris@102
|
590 #else
|
Chris@102
|
591
|
Chris@102
|
592 template< bool Signed >
|
Chris@102
|
593 struct operations< 2u, Signed > :
|
Chris@102
|
594 public extending_cas_based_operations< operations< 4u, Signed >, 2u, Signed >
|
Chris@102
|
595 {
|
Chris@102
|
596 };
|
Chris@102
|
597
|
Chris@102
|
598 #endif
|
Chris@102
|
599
|
Chris@102
|
600
|
Chris@102
|
601 #if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B)
|
Chris@102
|
602
|
Chris@102
|
603 template< bool Signed >
|
Chris@102
|
604 struct msvc_dcas_x86
|
Chris@102
|
605 {
|
Chris@102
|
606 typedef typename make_storage_type< 8u, Signed >::type storage_type;
|
Chris@102
|
607
|
Chris@102
|
608 // Intel 64 and IA-32 Architectures Software Developer's Manual, Volume 3A, 8.1.1. Guaranteed Atomic Operations:
|
Chris@102
|
609 //
|
Chris@102
|
610 // The Pentium processor (and newer processors since) guarantees that the following additional memory operations will always be carried out atomically:
|
Chris@102
|
611 // * Reading or writing a quadword aligned on a 64-bit boundary
|
Chris@102
|
612 //
|
Chris@102
|
613 // Luckily, the memory is almost always 8-byte aligned in our case because atomic<> uses 64 bit native types for storage and dynamic memory allocations
|
Chris@102
|
614 // have at least 8 byte alignment. The only unfortunate case is when atomic is placeod on the stack and it is not 8-byte aligned (like on 32 bit Windows).
|
Chris@102
|
615
|
Chris@102
|
616 static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
|
Chris@102
|
617 {
|
Chris@102
|
618 storage_type volatile* p = &storage;
|
Chris@102
|
619 if (((uint32_t)p & 0x00000007) == 0)
|
Chris@102
|
620 {
|
Chris@102
|
621 #if defined(_M_IX86_FP) && _M_IX86_FP >= 2
|
Chris@102
|
622 #if defined(__AVX__)
|
Chris@102
|
623 __asm
|
Chris@102
|
624 {
|
Chris@102
|
625 mov edx, p
|
Chris@102
|
626 vmovq xmm4, v
|
Chris@102
|
627 vmovq qword ptr [edx], xmm4
|
Chris@102
|
628 };
|
Chris@102
|
629 #else
|
Chris@102
|
630 __asm
|
Chris@102
|
631 {
|
Chris@102
|
632 mov edx, p
|
Chris@102
|
633 movq xmm4, v
|
Chris@102
|
634 movq qword ptr [edx], xmm4
|
Chris@102
|
635 };
|
Chris@102
|
636 #endif
|
Chris@102
|
637 #else
|
Chris@102
|
638 __asm
|
Chris@102
|
639 {
|
Chris@102
|
640 mov edx, p
|
Chris@102
|
641 fild v
|
Chris@102
|
642 fistp qword ptr [edx]
|
Chris@102
|
643 };
|
Chris@102
|
644 #endif
|
Chris@102
|
645 }
|
Chris@102
|
646 else
|
Chris@102
|
647 {
|
Chris@102
|
648 int backup;
|
Chris@102
|
649 __asm
|
Chris@102
|
650 {
|
Chris@102
|
651 mov backup, ebx
|
Chris@102
|
652 mov edi, p
|
Chris@102
|
653 mov ebx, dword ptr [v]
|
Chris@102
|
654 mov ecx, dword ptr [v + 4]
|
Chris@102
|
655 mov eax, dword ptr [edi]
|
Chris@102
|
656 mov edx, dword ptr [edi + 4]
|
Chris@102
|
657 align 16
|
Chris@102
|
658 again:
|
Chris@102
|
659 lock cmpxchg8b qword ptr [edi]
|
Chris@102
|
660 jne again
|
Chris@102
|
661 mov ebx, backup
|
Chris@102
|
662 };
|
Chris@102
|
663 }
|
Chris@102
|
664 }
|
Chris@102
|
665
|
Chris@102
|
666 static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order) BOOST_NOEXCEPT
|
Chris@102
|
667 {
|
Chris@102
|
668 storage_type const volatile* p = &storage;
|
Chris@102
|
669 storage_type value;
|
Chris@102
|
670
|
Chris@102
|
671 if (((uint32_t)p & 0x00000007) == 0)
|
Chris@102
|
672 {
|
Chris@102
|
673 #if defined(_M_IX86_FP) && _M_IX86_FP >= 2
|
Chris@102
|
674 #if defined(__AVX__)
|
Chris@102
|
675 __asm
|
Chris@102
|
676 {
|
Chris@102
|
677 mov edx, p
|
Chris@102
|
678 vmovq xmm4, qword ptr [edx]
|
Chris@102
|
679 vmovq value, xmm4
|
Chris@102
|
680 };
|
Chris@102
|
681 #else
|
Chris@102
|
682 __asm
|
Chris@102
|
683 {
|
Chris@102
|
684 mov edx, p
|
Chris@102
|
685 movq xmm4, qword ptr [edx]
|
Chris@102
|
686 movq value, xmm4
|
Chris@102
|
687 };
|
Chris@102
|
688 #endif
|
Chris@102
|
689 #else
|
Chris@102
|
690 __asm
|
Chris@102
|
691 {
|
Chris@102
|
692 mov edx, p
|
Chris@102
|
693 fild qword ptr [edx]
|
Chris@102
|
694 fistp value
|
Chris@102
|
695 };
|
Chris@102
|
696 #endif
|
Chris@102
|
697 }
|
Chris@102
|
698 else
|
Chris@102
|
699 {
|
Chris@102
|
700 // We don't care for comparison result here; the previous value will be stored into value anyway.
|
Chris@102
|
701 // Also we don't care for ebx and ecx values, they just have to be equal to eax and edx before cmpxchg8b.
|
Chris@102
|
702 __asm
|
Chris@102
|
703 {
|
Chris@102
|
704 mov edi, p
|
Chris@102
|
705 mov eax, ebx
|
Chris@102
|
706 mov edx, ecx
|
Chris@102
|
707 lock cmpxchg8b qword ptr [edi]
|
Chris@102
|
708 mov dword ptr [value], eax
|
Chris@102
|
709 mov dword ptr [value + 4], edx
|
Chris@102
|
710 };
|
Chris@102
|
711 }
|
Chris@102
|
712
|
Chris@102
|
713 return value;
|
Chris@102
|
714 }
|
Chris@102
|
715
|
Chris@102
|
716 static BOOST_FORCEINLINE bool compare_exchange_strong(
|
Chris@102
|
717 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT
|
Chris@102
|
718 {
|
Chris@102
|
719 storage_type volatile* p = &storage;
|
Chris@102
|
720 #if defined(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE64)
|
Chris@102
|
721 const storage_type old_val = (storage_type)BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE64(p, desired, expected);
|
Chris@102
|
722 const bool result = (old_val == expected);
|
Chris@102
|
723 expected = old_val;
|
Chris@102
|
724 return result;
|
Chris@102
|
725 #else
|
Chris@102
|
726 bool result;
|
Chris@102
|
727 int backup;
|
Chris@102
|
728 __asm
|
Chris@102
|
729 {
|
Chris@102
|
730 mov backup, ebx
|
Chris@102
|
731 mov edi, p
|
Chris@102
|
732 mov esi, expected
|
Chris@102
|
733 mov ebx, dword ptr [desired]
|
Chris@102
|
734 mov ecx, dword ptr [desired + 4]
|
Chris@102
|
735 mov eax, dword ptr [esi]
|
Chris@102
|
736 mov edx, dword ptr [esi + 4]
|
Chris@102
|
737 lock cmpxchg8b qword ptr [edi]
|
Chris@102
|
738 mov dword ptr [esi], eax
|
Chris@102
|
739 mov dword ptr [esi + 4], edx
|
Chris@102
|
740 mov ebx, backup
|
Chris@102
|
741 sete result
|
Chris@102
|
742 };
|
Chris@102
|
743 return result;
|
Chris@102
|
744 #endif
|
Chris@102
|
745 }
|
Chris@102
|
746
|
Chris@102
|
747 static BOOST_FORCEINLINE bool compare_exchange_weak(
|
Chris@102
|
748 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
|
Chris@102
|
749 {
|
Chris@102
|
750 return compare_exchange_strong(storage, expected, desired, success_order, failure_order);
|
Chris@102
|
751 }
|
Chris@102
|
752
|
Chris@102
|
753 static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
|
Chris@102
|
754 {
|
Chris@102
|
755 return true;
|
Chris@102
|
756 }
|
Chris@102
|
757 };
|
Chris@102
|
758
|
Chris@102
|
759 template< bool Signed >
|
Chris@102
|
760 struct operations< 8u, Signed > :
|
Chris@102
|
761 public cas_based_operations< msvc_dcas_x86< Signed > >
|
Chris@102
|
762 {
|
Chris@102
|
763 };
|
Chris@102
|
764
|
Chris@102
|
765 #elif defined(_M_AMD64)
|
Chris@102
|
766
|
Chris@102
|
767 template< bool Signed >
|
Chris@102
|
768 struct operations< 8u, Signed > :
|
Chris@102
|
769 public msvc_x86_operations< typename make_storage_type< 8u, Signed >::type, operations< 8u, Signed > >
|
Chris@102
|
770 {
|
Chris@102
|
771 typedef msvc_x86_operations< typename make_storage_type< 8u, Signed >::type, operations< 8u, Signed > > base_type;
|
Chris@102
|
772 typedef typename base_type::storage_type storage_type;
|
Chris@102
|
773
|
Chris@102
|
774 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
|
Chris@102
|
775 {
|
Chris@102
|
776 return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64(&storage, v));
|
Chris@102
|
777 }
|
Chris@102
|
778
|
Chris@102
|
779 static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
|
Chris@102
|
780 {
|
Chris@102
|
781 return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE64(&storage, v));
|
Chris@102
|
782 }
|
Chris@102
|
783
|
Chris@102
|
784 static BOOST_FORCEINLINE bool compare_exchange_strong(
|
Chris@102
|
785 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT
|
Chris@102
|
786 {
|
Chris@102
|
787 storage_type previous = expected;
|
Chris@102
|
788 storage_type old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE64(&storage, desired, previous));
|
Chris@102
|
789 expected = old_val;
|
Chris@102
|
790 return (previous == old_val);
|
Chris@102
|
791 }
|
Chris@102
|
792
|
Chris@102
|
793 static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
|
Chris@102
|
794 {
|
Chris@102
|
795 return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND64(&storage, v));
|
Chris@102
|
796 }
|
Chris@102
|
797
|
Chris@102
|
798 static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
|
Chris@102
|
799 {
|
Chris@102
|
800 return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR64(&storage, v));
|
Chris@102
|
801 }
|
Chris@102
|
802
|
Chris@102
|
803 static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
|
Chris@102
|
804 {
|
Chris@102
|
805 return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR64(&storage, v));
|
Chris@102
|
806 }
|
Chris@102
|
807 };
|
Chris@102
|
808
|
Chris@102
|
809 #endif
|
Chris@102
|
810
|
Chris@102
|
811 #if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B)
|
Chris@102
|
812
|
Chris@102
|
813 template< bool Signed >
|
Chris@102
|
814 struct msvc_dcas_x86_64
|
Chris@102
|
815 {
|
Chris@102
|
816 typedef typename make_storage_type< 16u, Signed >::type storage_type;
|
Chris@102
|
817
|
Chris@102
|
818 static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
|
Chris@102
|
819 {
|
Chris@102
|
820 storage_type value = const_cast< storage_type& >(storage);
|
Chris@102
|
821 while (!BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE128(&storage, v, &value)) {}
|
Chris@102
|
822 }
|
Chris@102
|
823
|
Chris@102
|
824 static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order) BOOST_NOEXCEPT
|
Chris@102
|
825 {
|
Chris@102
|
826 storage_type value = storage_type();
|
Chris@102
|
827 BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE128(&storage, value, &value);
|
Chris@102
|
828 return value;
|
Chris@102
|
829 }
|
Chris@102
|
830
|
Chris@102
|
831 static BOOST_FORCEINLINE bool compare_exchange_strong(
|
Chris@102
|
832 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT
|
Chris@102
|
833 {
|
Chris@102
|
834 return !!BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE128(&storage, desired, &expected);
|
Chris@102
|
835 }
|
Chris@102
|
836
|
Chris@102
|
837 static BOOST_FORCEINLINE bool compare_exchange_weak(
|
Chris@102
|
838 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
|
Chris@102
|
839 {
|
Chris@102
|
840 return compare_exchange_strong(storage, expected, desired, success_order, failure_order);
|
Chris@102
|
841 }
|
Chris@102
|
842
|
Chris@102
|
843 static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
|
Chris@102
|
844 {
|
Chris@102
|
845 return true;
|
Chris@102
|
846 }
|
Chris@102
|
847 };
|
Chris@102
|
848
|
Chris@102
|
849 template< bool Signed >
|
Chris@102
|
850 struct operations< 16u, Signed > :
|
Chris@102
|
851 public cas_based_operations< msvc_dcas_x86_64< Signed > >
|
Chris@102
|
852 {
|
Chris@102
|
853 };
|
Chris@102
|
854
|
Chris@102
|
855 #endif // defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B)
|
Chris@102
|
856
|
Chris@102
|
857 BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
|
Chris@102
|
858 {
|
Chris@102
|
859 BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
|
Chris@102
|
860 if (order == memory_order_seq_cst)
|
Chris@102
|
861 msvc_x86_operations_base::hardware_full_fence();
|
Chris@102
|
862 BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
|
Chris@102
|
863 }
|
Chris@102
|
864
|
Chris@102
|
865 BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
|
Chris@102
|
866 {
|
Chris@102
|
867 if (order != memory_order_relaxed)
|
Chris@102
|
868 BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
|
Chris@102
|
869 }
|
Chris@102
|
870
|
Chris@102
|
871 } // namespace detail
|
Chris@102
|
872 } // namespace atomics
|
Chris@102
|
873 } // namespace boost
|
Chris@102
|
874
|
Chris@102
|
875 #if defined(BOOST_MSVC)
|
Chris@102
|
876 #pragma warning(pop)
|
Chris@102
|
877 #endif
|
Chris@102
|
878
|
Chris@102
|
879 #endif // BOOST_ATOMIC_DETAIL_OPS_MSVC_X86_HPP_INCLUDED_
|