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