BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bsls_atomicoperations_x64_all_gcc.h
Go to the documentation of this file.
1/// @file bsls_atomicoperations_x64_all_gcc.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bsls_atomicoperations_x64_all_gcc.h -*-C++-*-
8#ifndef INCLUDED_BSLS_ATOMICOPERATIONS_X64_ALL_GCC
9#define INCLUDED_BSLS_ATOMICOPERATIONS_X64_ALL_GCC
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bsls_atomicoperations_x64_all_gcc bsls_atomicoperations_x64_all_gcc
15/// @brief Provide implementations of atomic operations for X86_64/GCC.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bsls
19/// @{
20/// @addtogroup bsls_atomicoperations_x64_all_gcc
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bsls_atomicoperations_x64_all_gcc-purpose"> Purpose</a>
25/// * <a href="#bsls_atomicoperations_x64_all_gcc-classes"> Classes </a>
26/// * <a href="#bsls_atomicoperations_x64_all_gcc-description"> Description </a>
27/// * <a href="#bsls_atomicoperations_x64_all_gcc-notes"> Notes </a>
28///
29/// # Purpose {#bsls_atomicoperations_x64_all_gcc-purpose}
30/// Provide implementations of atomic operations for X86_64/GCC.
31///
32/// # Classes {#bsls_atomicoperations_x64_all_gcc-classes}
33///
34/// - bsls::AtomicOperations_X64_ALL_GCC: implementation of atomics for X86_64/GCC
35///
36/// # Description {#bsls_atomicoperations_x64_all_gcc-description}
37/// This component provides classes necessary to implement atomics
38/// on the Linux X86_64 platform with GCC. The classes are for private use
39/// only. See @ref bsls_atomicoperations and @ref bsls_atomic for the public
40/// interface to atomics.
41///
42/// ## Notes {#bsls_atomicoperations_x64_all_gcc-notes}
43///
44///
45/// * GCC atomic intrinsics are used where possible instead of the assembly
46/// code,
47/// * "+m" constraint may cause an `inconsistent operand constraint` error in
48/// GCC 3.x in optimized builds, therefore sometimes a combination of output
49/// "=m" and input "m" constraints is used.
50/// @}
51/** @} */
52/** @} */
53
54/** @addtogroup bsl
55 * @{
56 */
57/** @addtogroup bsls
58 * @{
59 */
60/** @addtogroup bsls_atomicoperations_x64_all_gcc
61 * @{
62 */
63
64#include <bsls_atomicoperations_default.h>
65#include <bsls_platform.h>
66#include <bsls_types.h>
67
68#if defined(BSLS_PLATFORM_CPU_X86_64) \
69 && (defined(BSLS_PLATFORM_CMP_GNU) || defined(BSLS_PLATFORM_CMP_CLANG))
70
71
72
73namespace bsls {
74
75struct AtomicOperations_X64_ALL_GCC;
76typedef AtomicOperations_X64_ALL_GCC AtomicOperations_Imp;
77
78 // ===============================================
79 // Atomic_TypeTraits<AtomicOperations_X64_ALL_GCC>
80 // ===============================================
81
82template <>
83struct Atomic_TypeTraits<AtomicOperations_X64_ALL_GCC>
84{
85 struct Int
86 {
87 volatile int d_value __attribute__((__aligned__(sizeof(int))));
88 };
89
90 struct Int64
91 {
92 volatile Types::Int64 d_value
93 __attribute__((__aligned__(sizeof(Types::Int64))));
94 };
95
96 struct Uint
97 {
98 volatile unsigned int d_value
99 __attribute__((__aligned__(sizeof(unsigned int))));
100 };
101
102 struct Uint64
103 {
104 volatile Types::Uint64 d_value
105 __attribute__((__aligned__(sizeof(Types::Uint64))));
106 };
107
108 struct Pointer
109 {
110 void * volatile d_value __attribute__((__aligned__(sizeof(void *))));
111 };
112};
113
114 // ===================================
115 // struct AtomicOperations_X64_ALL_GCC
116 // ===================================
117
118struct AtomicOperations_X64_ALL_GCC
119 : AtomicOperations_Default64<AtomicOperations_X64_ALL_GCC>
120{
121 typedef Atomic_TypeTraits<AtomicOperations_X64_ALL_GCC> AtomicTypes;
122
123 // *** atomic functions for int ***
124
125 static int getInt(const AtomicTypes::Int *atomicInt);
126
127 static void setInt(AtomicTypes::Int *atomicInt, int value);
128
129 static void setIntRelease(AtomicTypes::Int *atomicInt, int value);
130
131 static int swapInt(AtomicTypes::Int *atomicInt, int swapValue);
132
133 static int testAndSwapInt(AtomicTypes::Int *atomicInt,
134 int compareValue,
135 int swapValue);
136
137 static int addIntNv(AtomicTypes::Int *atomicInt, int value);
138
139 // *** atomic functions for Int64 ***
140
141 static Types::Int64 getInt64(const AtomicTypes::Int64 *atomicInt);
142
143 static void setInt64(AtomicTypes::Int64 *atomicInt, Types::Int64 value);
144
145 static void setInt64Release(AtomicTypes::Int64 *atomicInt,
146 Types::Int64 value);
147
148 static Types::Int64 swapInt64(AtomicTypes::Int64 *atomicInt,
149 Types::Int64 swapValue);
150
151 static Types::Int64 testAndSwapInt64(AtomicTypes::Int64 *atomicInt,
152 Types::Int64 compareValue,
153 Types::Int64 swapValue);
154
155 static Types::Int64 addInt64Nv(AtomicTypes::Int64 *atomicInt,
156 Types::Int64 value);
157};
158
159// ============================================================================
160// INLINE FUNCTION DEFINITIONS
161// ============================================================================
162
163 // -----------------------------------
164 // struct AtomicOperations_X64_ALL_GCC
165 // -----------------------------------
166
167inline
168int AtomicOperations_X64_ALL_GCC::
169 getInt(const AtomicTypes::Int *atomicInt)
170{
171 int ret;
172
173 asm volatile (
174 " movl %[obj], %[ret] \n\t"
175
176 : [ret] "=r" (ret)
177 : [obj] "m" (*atomicInt)
178 : "memory");
179
180 return ret;
181}
182
183inline
184void AtomicOperations_X64_ALL_GCC::
185 setInt(AtomicTypes::Int *atomicInt, int value)
186{
187 asm volatile (
188 " movl %[val], %[obj] \n\t"
189 " mfence \n\t"
190
191 : [obj] "=m" (*atomicInt)
192 : [val] "r" (value)
193 : "memory");
194}
195
196inline
197void AtomicOperations_X64_ALL_GCC::
198 setIntRelease(AtomicTypes::Int *atomicInt, int value)
199{
200 asm volatile (
201 " movl %[val], %[obj] \n\t"
202
203 : [obj] "=m" (*atomicInt)
204 : [val] "r" (value)
205 : "memory");
206}
207
208inline
209int AtomicOperations_X64_ALL_GCC::
210 swapInt(AtomicTypes::Int *atomicInt, int swapValue)
211{
212 asm volatile (
213 " lock xchgl %[val], %[obj] \n\t"
214
215 : [obj] "=m" (*atomicInt),
216 [val] "=r" (swapValue)
217 : "1" (swapValue), "m" (*atomicInt)
218 : "memory");
219
220 return swapValue;
221}
222
223inline
224int AtomicOperations_X64_ALL_GCC::
225 testAndSwapInt(AtomicTypes::Int *atomicInt,
226 int compareValue,
227 int swapValue)
228{
229 return __sync_val_compare_and_swap(&atomicInt->d_value,
230 compareValue,
231 swapValue);
232}
233
234inline
235int AtomicOperations_X64_ALL_GCC::
236 addIntNv(AtomicTypes::Int *atomicInt, int value)
237{
238 return __sync_add_and_fetch(&atomicInt->d_value, value);
239}
240
241inline
242Types::Int64 AtomicOperations_X64_ALL_GCC::
243 getInt64(const AtomicTypes::Int64 *atomicInt)
244{
245 Types::Int64 result;
246
247 asm volatile (
248 " movq %[obj], %[res] \n\t"
249
250 : [res] "=r" (result)
251 : [obj] "m" (*atomicInt)
252 : "memory");
253
254 return result;
255}
256
257inline
258void AtomicOperations_X64_ALL_GCC::
259 setInt64(AtomicTypes::Int64 *atomicInt, Types::Int64 value)
260{
261 asm volatile (
262 " movq %[val], %[obj] \n\t"
263 " mfence \n\t"
264
265 : [obj] "=m" (*atomicInt)
266 : [val] "r" (value)
267 : "memory");
268}
269
270inline
271void AtomicOperations_X64_ALL_GCC::
272 setInt64Release(AtomicTypes::Int64 *atomicInt,
273 Types::Int64 value)
274{
275 asm volatile (
276 " movq %[val], %[obj] \n\t"
277
278 : [obj] "=m" (*atomicInt)
279 : [val] "r" (value)
280 : "memory");
281}
282
283inline
284Types::Int64 AtomicOperations_X64_ALL_GCC::
285 swapInt64(AtomicTypes::Int64 *atomicInt,
286 Types::Int64 swapValue)
287{
288 asm volatile (
289 " lock xchgq %[val], %[obj] \n\t"
290
291 : [val] "+r" (swapValue),
292 [obj] "=m" (*atomicInt)
293 : "m" (*atomicInt)
294 : "memory");
295
296 return swapValue;
297}
298
299inline
300Types::Int64 AtomicOperations_X64_ALL_GCC::
301 testAndSwapInt64(AtomicTypes::Int64 *atomicInt,
302 Types::Int64 compareValue,
303 Types::Int64 swapValue)
304{
305 return __sync_val_compare_and_swap(&atomicInt->d_value,
306 compareValue,
307 swapValue);
308}
309
310inline
311Types::Int64 AtomicOperations_X64_ALL_GCC::
312 addInt64Nv(AtomicTypes::Int64 *atomicInt,
313 Types::Int64 value)
314{
315 return __sync_add_and_fetch(&atomicInt->d_value, value);
316}
317
318} // close package namespace
319
320
321
322#endif // defined(BSLS_PLATFORM_CPU_X86_64) && (CMP_GNU || CMP_CLANG)
323
324#endif
325
326// ----------------------------------------------------------------------------
327// Copyright 2013 Bloomberg Finance L.P.
328//
329// Licensed under the Apache License, Version 2.0 (the "License");
330// you may not use this file except in compliance with the License.
331// You may obtain a copy of the License at
332//
333// http://www.apache.org/licenses/LICENSE-2.0
334//
335// Unless required by applicable law or agreed to in writing, software
336// distributed under the License is distributed on an "AS IS" BASIS,
337// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
338// See the License for the specific language governing permissions and
339// limitations under the License.
340// ----------------------------- END-OF-FILE ----------------------------------
341
342/** @} */
343/** @} */
344/** @} */
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bdlt_iso8601util.h:691
long long Int64
Definition bsls_types.h:132