8#ifndef INCLUDED_BSLS_ATOMICOPERATIONS_ARM_ALL_GCC
9#define INCLUDED_BSLS_ATOMICOPERATIONS_ARM_ALL_GCC
71#include <bsls_atomicoperations_default.h>
75#if defined(BSLS_PLATFORM_CPU_ARM) \
76 && (defined(BSLS_PLATFORM_CMP_GNU) || defined(BSLS_PLATFORM_CMP_CLANG))
82struct AtomicOperations_ARM_ALL_GCC;
83typedef AtomicOperations_ARM_ALL_GCC AtomicOperations_Imp;
90struct Atomic_TypeTraits<AtomicOperations_ARM_ALL_GCC>
94 volatile int d_value __attribute__((__aligned__(
sizeof(
int))));
99 volatile Types::Int64 d_value
100 __attribute__((__aligned__(
sizeof(Types::Int64))));
105 volatile unsigned int d_value
106 __attribute__((__aligned__(
sizeof(
unsigned int))));
111 volatile Types::Uint64 d_value
112 __attribute__((__aligned__(
sizeof(Types::Uint64))));
117 void *
volatile d_value __attribute__((__aligned__(
sizeof(
void *))));
125struct AtomicOperations_ARM_ALL_GCC
126 : AtomicOperations_Default32<AtomicOperations_ARM_ALL_GCC>
136 typedef Atomic_TypeTraits<AtomicOperations_ARM_ALL_GCC> AtomicTypes;
140 static int getInt(
const AtomicTypes::Int *atomicInt);
142 static int getIntAcquire(
const AtomicTypes::Int *atomicInt);
144 static void setInt(AtomicTypes::Int *atomicInt,
int value);
146 static void setIntRelease(AtomicTypes::Int *atomicInt,
int value);
148 static int swapInt(AtomicTypes::Int *atomicInt,
int swapValue);
150 static int testAndSwapInt(AtomicTypes::Int *atomicInt,
154 static int addIntNv(AtomicTypes::Int *atomicInt,
int value);
158 static Types::Int64 getInt64(
const AtomicTypes::Int64 *atomicInt);
160 static void setInt64(AtomicTypes::Int64 *atomicInt, Types::Int64 value);
162 static Types::Int64 swapInt64(AtomicTypes::Int64 *atomicInt,
163 Types::Int64 swapValue);
165 static Types::Int64 testAndSwapInt64(AtomicTypes::Int64 *atomicInt,
166 Types::Int64 compareValue,
167 Types::Int64 swapValue);
169 static Types::Int64 addInt64Nv(AtomicTypes::Int64 *atomicInt,
181#if BSLS_PLATFORM_CMP_VERSION < 40700
182# if defined(BSLS_PLATFORM_CPU_ARM_V7)
184# define BSLS_ATOMICOPERATIONS_BARRIER() \
185 asm volatile ("dmb" ::: "memory") \
187# define BSLS_ATOMICOPERATIONS_INSTR_BARRIER() \
188 asm volatile ("isb") \
192# define BSLS_ATOMICOPERATIONS_BARRIER() \
196 "mcr p15, 0, %[temp_reg], c7, c10, 5 \n\t" \
198 : [temp_reg] "r" (temp_reg) \
202# define BSLS_ATOMICOPERATIONS_INSTR_BARRIER() \
206 "mcr p15, 0, %[temp_reg], c7, c5, 4 \n\t" \
208 : [temp_reg] "r" (temp_reg)); \
213# define BSLS_ATOMICOPERATIONS_USE_CPP11_INTRINSICS
217int AtomicOperations_ARM_ALL_GCC::
218 getInt(
const AtomicTypes::Int *atomicInt)
220#ifdef BSLS_ATOMICOPERATIONS_USE_CPP11_INTRINSICS
221 return __atomic_load_n(&atomicInt->d_value, __ATOMIC_SEQ_CST);
223 int result = atomicInt->d_value;
224 BSLS_ATOMICOPERATIONS_BARRIER();
232int AtomicOperations_ARM_ALL_GCC::
233 getIntAcquire(
const AtomicTypes::Int *atomicInt)
235#ifdef BSLS_ATOMICOPERATIONS_USE_CPP11_INTRINSICS
236 return __atomic_load_n(&atomicInt->d_value, __ATOMIC_ACQUIRE);
238 return getInt(atomicInt);
243void AtomicOperations_ARM_ALL_GCC::
244 setInt(AtomicTypes::Int *atomicInt,
int value)
246#ifdef BSLS_ATOMICOPERATIONS_USE_CPP11_INTRINSICS
247 __atomic_store_n(&atomicInt->d_value, value, __ATOMIC_SEQ_CST);
249 BSLS_ATOMICOPERATIONS_BARRIER();
250 atomicInt->d_value = value;
251 BSLS_ATOMICOPERATIONS_BARRIER();
256void AtomicOperations_ARM_ALL_GCC::
257 setIntRelease(AtomicTypes::Int *atomicInt,
int value)
259#ifdef BSLS_ATOMICOPERATIONS_USE_CPP11_INTRINSICS
260 __atomic_store_n(&atomicInt->d_value, value, __ATOMIC_RELEASE);
262 BSLS_ATOMICOPERATIONS_BARRIER();
263 setInt(atomicInt, value);
268int AtomicOperations_ARM_ALL_GCC::
269 swapInt(AtomicTypes::Int *atomicInt,
int swapValue)
271#ifdef BSLS_ATOMICOPERATIONS_USE_CPP11_INTRINSICS
272 return __atomic_exchange_n(&atomicInt->d_value,
279 BSLS_ATOMICOPERATIONS_BARRIER();
282 "1: ldrex %[old], [%3] \n\t"
283 " strex %[tmp], %[val], [%3] \n\t"
284 " teq %[tmp], #0 \n\t"
287 : [old]
"=&r" (oldValue),
291 [val]
"r" (swapValue)
294 BSLS_ATOMICOPERATIONS_INSTR_BARRIER();
301int AtomicOperations_ARM_ALL_GCC::
302 testAndSwapInt(AtomicTypes::Int *atomicInt,
306#ifdef BSLS_ATOMICOPERATIONS_USE_CPP11_INTRINSICS
307 __atomic_compare_exchange_n(&atomicInt->d_value, &compareValue, swapValue,
308 false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
311 return __sync_val_compare_and_swap(&atomicInt->d_value,
318int AtomicOperations_ARM_ALL_GCC::
319 addIntNv(AtomicTypes::Int *atomicInt,
int value)
321#ifdef BSLS_ATOMICOPERATIONS_USE_CPP11_INTRINSICS
322 return __atomic_add_fetch(&atomicInt->d_value, value, __ATOMIC_SEQ_CST);
324 return __sync_add_and_fetch(&atomicInt->d_value, value);
330 getInt64(
const AtomicTypes::Int64 *atomicInt)
332#ifdef BSLS_ATOMICOPERATIONS_USE_CPP11_INTRINSICS
333 return __atomic_load_n(&atomicInt->d_value, __ATOMIC_SEQ_CST);
338 " ldrexd r2, r3, [%2] \n\t"
339 " mov %[res1], r2 \n\t"
340 " mov %[res2], r3 \n\t"
342 : [res1]
"=&r" (((Int64_Words &) result).w1),
343 [res2]
"=&r" (((Int64_Words &) result).w2)
348 BSLS_ATOMICOPERATIONS_BARRIER();
355void AtomicOperations_ARM_ALL_GCC::
356 setInt64(AtomicTypes::Int64 *atomicInt,
Types::Int64 value)
358#ifdef BSLS_ATOMICOPERATIONS_USE_CPP11_INTRINSICS
359 return __atomic_store_n(&atomicInt->d_value, value, __ATOMIC_SEQ_CST);
361 swapInt64(atomicInt, value);
367 swapInt64(AtomicTypes::Int64 *atomicInt,
370#ifdef BSLS_ATOMICOPERATIONS_USE_CPP11_INTRINSICS
371 return __atomic_exchange_n(&atomicInt->d_value,
378 BSLS_ATOMICOPERATIONS_BARRIER();
381 "1: ldrexd r2, r3, [%4] \n\t"
382 " mov %[old1], r2 \n\t"
383 " mov %[old2], r3 \n\t"
384 " mov r2, %[val1] \n\t"
385 " mov r3, %[val2] \n\t"
386 " strexd %[rc], r2, r3, [%4] \n\t"
387 " teq %[rc], #0 \n\t"
391 [old1]
"=&r" (((Int64_Words &) oldValue).w1),
392 [old2]
"=&r" (((Int64_Words &) oldValue).w2),
395 [val1]
"r" (((Int64_Words &) swapValue).w1),
396 [val2]
"r" (((Int64_Words &) swapValue).w2)
397 :
"r2",
"r3",
"cc",
"memory");
399 BSLS_ATOMICOPERATIONS_INSTR_BARRIER();
407 testAndSwapInt64(AtomicTypes::Int64 *atomicInt,
411#ifdef BSLS_ATOMICOPERATIONS_USE_CPP11_INTRINSICS
412 __atomic_compare_exchange_n(&atomicInt->d_value,
423 BSLS_ATOMICOPERATIONS_BARRIER();
426 "1: ldrexd r2, r3, [%4] \n\t"
427 " mov %[old1], r2 \n\t"
428 " mov %[old2], r3 \n\t"
429 " mov r2, %[val1] \n\t"
430 " mov r3, %[val2] \n\t"
431 " mov %[rc], #0 \n\t"
432 " teq %[old1], %[cmp1] \n\t"
434 " teqeq %[old2], %[cmp2] \n\t"
435 " strexdeq %[rc], r2, r3, [%4] \n\t"
436 " teq %[rc], #0 \n\t"
440 [old1]
"=&r" (((Int64_Words &) oldValue).w1),
441 [old2]
"=&r" (((Int64_Words &) oldValue).w2),
444 [cmp1]
"r" (((Int64_Words &) compareValue).w1),
445 [cmp2]
"r" (((Int64_Words &) compareValue).w2),
446 [val1]
"r" (((Int64_Words &) swapValue).w1),
447 [val2]
"r" (((Int64_Words &) swapValue).w2)
448 :
"r2",
"r3",
"cc",
"memory");
450 BSLS_ATOMICOPERATIONS_INSTR_BARRIER();
458 addInt64Nv(AtomicTypes::Int64 *atomicInt,
461#ifdef BSLS_ATOMICOPERATIONS_USE_CPP11_INTRINSICS
462 return __atomic_add_fetch(&atomicInt->d_value, value, __ATOMIC_SEQ_CST);
470 newVal = old + value;
471 }
while (old != (prev = testAndSwapInt64(atomicInt, old, newVal)));
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bdlt_iso8601util.h:691
long long Int64
Definition bsls_types.h:132