BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bsls_atomicoperations_x86_win_msvc.h
Go to the documentation of this file.
1/// @file bsls_atomicoperations_x86_win_msvc.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bsls_atomicoperations_x86_win_msvc.h -*-C++-*-
8#ifndef INCLUDED_BSLS_ATOMICOPERATIONS_X86_WIN_MSVC
9#define INCLUDED_BSLS_ATOMICOPERATIONS_X86_WIN_MSVC
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bsls_atomicoperations_x86_win_msvc bsls_atomicoperations_x86_win_msvc
15/// @brief Provide implementations of atomic operations for X86/MSVC/Windows.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bsls
19/// @{
20/// @addtogroup bsls_atomicoperations_x86_win_msvc
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bsls_atomicoperations_x86_win_msvc-purpose"> Purpose</a>
25/// * <a href="#bsls_atomicoperations_x86_win_msvc-classes"> Classes </a>
26/// * <a href="#bsls_atomicoperations_x86_win_msvc-description"> Description </a>
27///
28/// # Purpose {#bsls_atomicoperations_x86_win_msvc-purpose}
29/// Provide implementations of atomic operations for X86/MSVC/Windows.
30///
31/// # Classes {#bsls_atomicoperations_x86_win_msvc-classes}
32///
33/// - bsls::AtomicOperations_X86_WIN_MSVC: atomics for X86/MSVC/Windows
34///
35/// # Description {#bsls_atomicoperations_x86_win_msvc-description}
36/// This component provides classes necessary to implement atomics
37/// on the Windows X86 platform with MSVC compiler. The classes are for private
38/// use only. See @ref bsls_atomicoperations and @ref bsls_atomic for the public
39/// interface to atomics.
40/// @}
41/** @} */
42/** @} */
43
44/** @addtogroup bsl
45 * @{
46 */
47/** @addtogroup bsls
48 * @{
49 */
50/** @addtogroup bsls_atomicoperations_x86_win_msvc
51 * @{
52 */
53
54#include <bsls_atomicoperations_default.h>
55#include <bsls_platform.h>
56#include <bsls_types.h>
57
58#if defined(BSLS_PLATFORM_CPU_X86) && defined(BSLS_PLATFORM_CMP_MSVC)
59#include <intrin.h>
60
61// Visual C++ implementation exploits the fact that 'volatile' loads and stores
62// have acquire and release semantics (load - acquire, store - release). So
63// these memory ordering guarantees come for free (and accidentally they are
64// no-op on x86). However the implementation of operations providing
65// the sequential consistency guarantee still requires a memory barrier.
66//
67// As for interlocked intrinsics, they provide the sequential consistency
68// guarantee, so no additional memory barrier is needed.
69//
70// For some explanations, see
71// http://blogs.msdn.com/b/kangsu/archive/2007/07/16/
72// volatile-acquire-release-memory-fences-and-vc2005.aspx
73// and also MSDN documentation for 'volatile' and interlocked intrinsics in
74// VC++ 2005 and later.
75
76
77
78namespace bsls {
79
80struct AtomicOperations_X86_WIN_MSVC;
81typedef AtomicOperations_X86_WIN_MSVC AtomicOperations_Imp;
82
83 // =======================================================
84 // struct Atomic_TypeTraits<AtomicOperations_X86_WIN_MSVC>
85 // =======================================================
86
87template<>
88struct Atomic_TypeTraits<AtomicOperations_X86_WIN_MSVC>
89{
90 struct Int
91 {
92 __declspec(align(4))
93 volatile int d_value;
94 };
95
96 struct Int64
97 {
98 __declspec(align(8))
99 volatile Types::Int64 d_value;
100 };
101
102 struct Uint
103 {
104 __declspec(align(4))
105 volatile unsigned int d_value;
106 };
107
108 struct Uint64
109 {
110 __declspec(align(8))
111 volatile Types::Uint64 d_value;
112 };
113
114 struct Pointer
115 {
116 __declspec(align(4))
117 void * volatile d_value;
118 };
119};
120
121 // ====================================
122 // struct AtomicOperations_X86_WIN_MSVC
123 // ====================================
124
125struct AtomicOperations_X86_WIN_MSVC
126 : AtomicOperations_Default32<AtomicOperations_X86_WIN_MSVC>
127{
128 typedef Atomic_TypeTraits<AtomicOperations_X86_WIN_MSVC> AtomicTypes;
129
130 // *** atomic functions for int ***
131
132 static int getInt(const AtomicTypes::Int *atomicInt);
133
134 static int getIntAcquire(const AtomicTypes::Int *atomicInt);
135
136 static void setInt(AtomicTypes::Int *atomicInt, int value);
137
138 static void setIntRelease(AtomicTypes::Int *atomicInt, int value);
139
140 static int swapInt(AtomicTypes::Int *atomicInt, int swapValue);
141
142 static int testAndSwapInt(AtomicTypes::Int *atomicInt,
143 int compareValue,
144 int swapValue);
145
146 static int addIntNv(AtomicTypes::Int *atomicInt, int value);
147
148 // *** atomic functions for Int64 ***
149
150 static Types::Int64 getInt64(const AtomicTypes::Int64 *atomicInt);
151
152 static void setInt64(AtomicTypes::Int64 *atomicInt, Types::Int64 value);
153
154 static Types::Int64 swapInt64(AtomicTypes::Int64 *atomicInt,
155 Types::Int64 swapValue);
156
157 static Types::Int64 testAndSwapInt64(AtomicTypes::Int64 *atomicInt,
158 Types::Int64 compareValue,
159 Types::Int64 swapValue);
160
161 static Types::Int64 addInt64Nv(AtomicTypes::Int64 *atomicInt,
162 Types::Int64 value);
163};
164
165// ===========================================================================
166// INLINE FUNCTION DEFINITIONS
167// ===========================================================================
168
169 // ------------------------------------
170 // struct AtomicOperations_X86_WIN_MSVC
171 // ------------------------------------
172
173// Memory barrier for atomic operations with sequential consistency.
174#define BSLS_ATOMIC_FENCE() \
175 __asm lock add dword ptr [esp], 0
176
177inline
178int AtomicOperations_X86_WIN_MSVC::
179 getInt(const AtomicTypes::Int *atomicInt)
180{
181 BSLS_ATOMIC_FENCE();
182 return atomicInt->d_value;
183}
184
185inline
186int AtomicOperations_X86_WIN_MSVC::
187 getIntAcquire(const AtomicTypes::Int *atomicInt)
188{
189 return atomicInt->d_value;
190}
191
192inline
193void AtomicOperations_X86_WIN_MSVC::
194 setInt(AtomicTypes::Int *atomicInt, int value)
195{
196 atomicInt->d_value = value;
197 BSLS_ATOMIC_FENCE();
198}
199
200inline
201void AtomicOperations_X86_WIN_MSVC::
202 setIntRelease(AtomicTypes::Int *atomicInt, int value)
203{
204 atomicInt->d_value = value;
205}
206
207inline
208int AtomicOperations_X86_WIN_MSVC::
209 swapInt(AtomicTypes::Int *atomicInt, int swapValue)
210{
211 return _InterlockedExchange(
212 reinterpret_cast<long volatile *>(&atomicInt->d_value),
213 swapValue);
214}
215
216inline
217int AtomicOperations_X86_WIN_MSVC::
218 testAndSwapInt(AtomicTypes::Int *atomicInt,
219 int compareValue,
220 int swapValue)
221{
222 return _InterlockedCompareExchange(
223 reinterpret_cast<long volatile *>(&atomicInt->d_value),
224 swapValue,
225 compareValue);
226}
227
228inline
229int AtomicOperations_X86_WIN_MSVC::
230 addIntNv(AtomicTypes::Int *atomicInt, int value)
231{
232 return static_cast<unsigned>(_InterlockedExchangeAdd(
233 reinterpret_cast<long volatile *>(
234 &atomicInt->d_value),
235 value))
236 + value;
237}
238
239 // *** atomic functions for Int64 ***
240
241inline
242Types::Int64 AtomicOperations_X86_WIN_MSVC::
243 getInt64(const AtomicTypes::Int64 *atomicInt)
244{
245 return _InterlockedCompareExchange64(
246 const_cast<Types::Int64 volatile *>(&atomicInt->d_value),
247 0,
248 0);
249}
250
251inline
252void AtomicOperations_X86_WIN_MSVC::
253 setInt64(AtomicTypes::Int64 *atomicInt, Types::Int64 value)
254{
255 swapInt64(atomicInt, value);
256}
257
258inline
259Types::Int64 AtomicOperations_X86_WIN_MSVC::
260 swapInt64(AtomicTypes::Int64 *atomicInt,
261 Types::Int64 swapValue)
262{
263 Types::Int64 actual = atomicInt->d_value;
264 Types::Int64 expected;
265
266 do
267 {
268 expected = actual;
269 actual = testAndSwapInt64(atomicInt, expected, swapValue);
270 } while (actual != expected);
271
272 return expected;
273}
274
275inline
276Types::Int64 AtomicOperations_X86_WIN_MSVC::
277 testAndSwapInt64(AtomicTypes::Int64 *atomicInt,
278 Types::Int64 compareValue,
279 Types::Int64 swapValue)
280{
281 return _InterlockedCompareExchange64(
282 &atomicInt->d_value,
283 swapValue,
284 compareValue);
285}
286
287inline
288Types::Int64 AtomicOperations_X86_WIN_MSVC::
289 addInt64Nv(AtomicTypes::Int64 *atomicInt,
290 Types::Int64 value)
291{
292 Types::Int64 actual = atomicInt->d_value;
293 Types::Int64 expected;
294
295 do
296 {
297 expected = actual;
298 actual = testAndSwapInt64(atomicInt, expected, expected + value);
299 } while (actual != expected);
300
301 return expected + value;
302}
303
304#undef BSLS_ATOMIC_FENCE
305
306} // close package namespace
307
308
309
310#endif // X86 && MSVC
311
312#endif
313
314// ----------------------------------------------------------------------------
315// Copyright 2013 Bloomberg Finance L.P.
316//
317// Licensed under the Apache License, Version 2.0 (the "License");
318// you may not use this file except in compliance with the License.
319// You may obtain a copy of the License at
320//
321// http://www.apache.org/licenses/LICENSE-2.0
322//
323// Unless required by applicable law or agreed to in writing, software
324// distributed under the License is distributed on an "AS IS" BASIS,
325// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
326// See the License for the specific language governing permissions and
327// limitations under the License.
328// ----------------------------- END-OF-FILE ----------------------------------
329
330/** @} */
331/** @} */
332/** @} */
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bdlt_iso8601util.h:691