19#if (AO_GNUC_PREREQ(4, 8) || AO_CLANG_PREREQ(3, 4)) \
20 && !defined(__INTEL_COMPILER) \
21 && !defined(AO_DISABLE_GCC_ATOMICS)
22# define AO_GCC_ATOMIC_TEST_AND_SET
24# if defined(__APPLE_CC__)
27# define AO_GCC_FORCE_HAVE_CAS
30# if !AO_CLANG_PREREQ(9, 0)
33# define AO_SKIPATOMIC_double_compare_and_swap_ANY
36# elif defined(__MACH__)
39# ifndef MAC_OS_X_VERSION_MIN_REQUIRED
41# include <AvailabilityMacros.h>
43# if MAC_OS_X_VERSION_MIN_REQUIRED < 1090
44# define AO_SKIPATOMIC_DOUBLE_LOAD_STORE_ANY
48# elif defined(__clang__)
49# if !defined(__x86_64__)
50# if !defined(AO_PREFER_BUILTIN_ATOMICS) && !defined(__CYGWIN__) \
51 && !AO_CLANG_PREREQ(5, 0)
54# define AO_SKIPATOMIC_double_compare_and_swap_ANY
55# define AO_SKIPATOMIC_DOUBLE_LOAD_STORE_ANY
58# elif !defined(__ILP32__)
59# if (!AO_CLANG_PREREQ(3, 5) && !defined(AO_PREFER_BUILTIN_ATOMICS)) \
60 || (!AO_CLANG_PREREQ(4, 0) && defined(AO_ADDRESS_SANITIZER)) \
61 || defined(AO_THREAD_SANITIZER)
66# define AO_SKIPATOMIC_double_compare_and_swap_ANY
67# define AO_SKIPATOMIC_DOUBLE_LOAD_STORE_ANY
71# elif AO_GNUC_PREREQ(7, 0) && !defined(AO_PREFER_BUILTIN_ATOMICS) \
72 && !defined(AO_THREAD_SANITIZER) && !defined(__MINGW32__)
76# define AO_SKIPATOMIC_double_compare_and_swap_ANY
77# define AO_SKIPATOMIC_DOUBLE_LOAD_STORE_ANY
80# ifdef AO_SKIPATOMIC_DOUBLE_LOAD_STORE_ANY
81# define AO_SKIPATOMIC_double_load
82# define AO_SKIPATOMIC_double_load_acquire
83# define AO_SKIPATOMIC_double_store
84# define AO_SKIPATOMIC_double_store_release
85# undef AO_SKIPATOMIC_DOUBLE_LOAD_STORE_ANY
95#include "../all_aligned_atomic_load_store.h"
97#include "../test_and_set_t_is_char.h"
99#if defined(__SSE2__) && !defined(AO_USE_PENTIUM4_INSTRS)
101# define AO_USE_PENTIUM4_INSTRS
104#if defined(AO_USE_PENTIUM4_INSTRS)
108 __asm__ __volatile__(
"mfence" : : :
"memory");
110# define AO_HAVE_nop_full
122#ifndef AO_PREFER_GENERALIZED
128 __asm__ __volatile__ (
"lock; xadd %0, %1"
129 :
"=r" (
result),
"+m" (*p)
134# define AO_HAVE_fetch_and_add_full
142 __asm__ __volatile__ (
"lock; xaddb %0, %1"
143 :
"=q" (
result),
"+m" (*p)
148#define AO_HAVE_char_fetch_and_add_full
155 __asm__ __volatile__ (
"lock; xaddw %0, %1"
156 :
"=r" (
result),
"+m" (*p)
161#define AO_HAVE_short_fetch_and_add_full
163#ifndef AO_PREFER_GENERALIZED
167 __asm__ __volatile__ (
"lock; and %1, %0"
172# define AO_HAVE_and_full
177 __asm__ __volatile__ (
"lock; or %1, %0"
182# define AO_HAVE_or_full
187 __asm__ __volatile__ (
"lock; xor %1, %0"
192# define AO_HAVE_xor_full
201 __asm__ __volatile__ (
"lock; andb %1, %0"
206#define AO_HAVE_char_and_full
211 __asm__ __volatile__ (
"lock; orb %1, %0"
216#define AO_HAVE_char_or_full
221 __asm__ __volatile__ (
"lock; xorb %1, %0"
226#define AO_HAVE_char_xor_full
231 __asm__ __volatile__ (
"lock; andw %1, %0"
236#define AO_HAVE_short_and_full
241 __asm__ __volatile__ (
"lock; orw %1, %0"
246#define AO_HAVE_short_or_full
251 __asm__ __volatile__ (
"lock; xorw %1, %0"
256#define AO_HAVE_short_xor_full
262 unsigned char oldval;
264 __asm__ __volatile__ (
"xchgb %0, %1"
265 :
"=q" (oldval),
"+m" (*addr)
266 :
"0" ((
unsigned char)0xff)
270#define AO_HAVE_test_and_set_full
272#ifndef AO_GENERALIZE_ASM_BOOL_CAS
277# ifdef AO_USE_SYNC_CAS_BUILTIN
278 return (
int)__sync_bool_compare_and_swap(addr, old, new_val
285# if defined(__GCC_ASM_FLAG_OUTPUTS__)
288 __asm__ __volatile__ (
"lock; cmpxchg %3, %0"
290 :
"r" (new_val),
"a" (old)
293 __asm__ __volatile__ (
"lock; cmpxchg %2, %0; setz %1"
294 :
"+m" (*addr),
"=a" (
result)
295 :
"r" (new_val),
"a" (old)
301# define AO_HAVE_compare_and_swap_full
308# ifdef AO_USE_SYNC_CAS_BUILTIN
309 return __sync_val_compare_and_swap(addr, old_val, new_val
313 __asm__ __volatile__ (
"lock; cmpxchg %3, %1"
314 :
"=a" (fetched_val),
"+m" (*addr)
315 :
"a" (old_val),
"r" (new_val)
320#define AO_HAVE_fetch_compare_and_swap_full
324 unsigned char old_val,
325 unsigned char new_val)
327# ifdef AO_USE_SYNC_CAS_BUILTIN
328 return __sync_val_compare_and_swap(addr, old_val, new_val
331 unsigned char fetched_val;
333 __asm__ __volatile__ (
"lock; cmpxchgb %3, %1"
334 :
"=a" (fetched_val),
"+m" (*addr)
335 :
"a" (old_val),
"q" (new_val)
340# define AO_HAVE_char_fetch_compare_and_swap_full
344 unsigned short old_val,
345 unsigned short new_val)
347# ifdef AO_USE_SYNC_CAS_BUILTIN
348 return __sync_val_compare_and_swap(addr, old_val, new_val
351 unsigned short fetched_val;
353 __asm__ __volatile__ (
"lock; cmpxchgw %3, %1"
354 :
"=a" (fetched_val),
"+m" (*addr)
355 :
"a" (old_val),
"r" (new_val)
360# define AO_HAVE_short_fetch_compare_and_swap_full
362# if defined(__x86_64__) && !defined(__ILP32__)
365 unsigned int old_val,
366 unsigned int new_val)
368# ifdef AO_USE_SYNC_CAS_BUILTIN
369 return __sync_val_compare_and_swap(addr, old_val, new_val
372 unsigned int fetched_val;
374 __asm__ __volatile__ (
"lock; cmpxchgl %3, %1"
375 :
"=a" (fetched_val),
"+m" (*addr)
376 :
"a" (old_val),
"r" (new_val)
381# define AO_HAVE_int_fetch_compare_and_swap_full
383# ifndef AO_PREFER_GENERALIZED
389 __asm__ __volatile__ (
"lock; xaddl %0, %1"
390 :
"=r" (
result),
"+m" (*p)
395# define AO_HAVE_int_fetch_and_add_full
400 __asm__ __volatile__ (
"lock; andl %1, %0"
405# define AO_HAVE_int_and_full
410 __asm__ __volatile__ (
"lock; orl %1, %0"
415# define AO_HAVE_int_or_full
420 __asm__ __volatile__ (
"lock; xorl %1, %0"
425# define AO_HAVE_int_xor_full
438# include "../ordered_except_wr.h"
442#if defined(AO_GCC_ATOMIC_TEST_AND_SET) \
443 && !defined(AO_SKIPATOMIC_double_compare_and_swap_ANY)
445# if defined(__ILP32__) || !defined(__x86_64__) \
446 || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16)
447# include "../standard_ao_double_t.h"
450#elif !defined(__x86_64__) && (!defined(AO_USE_SYNC_CAS_BUILTIN) \
451 || defined(AO_GCC_ATOMIC_TEST_AND_SET))
452# include "../standard_ao_double_t.h"
457# ifndef AO_PREFER_GENERALIZED
458# define AO_ACCESS_double_CHECK_ALIGNED
459# include "../loadstore/double_atomic_load_store.h"
470# if defined(__PIC__) && !(AO_GNUC_PREREQ(5, 1) || AO_CLANG_PREREQ(4, 0))
485 __asm__ __volatile__(
"mov %%ebx, %2\n\t"
488 "lock; cmpxchg8b (%%edi)\n\t"
491 :
"+m" (*addr),
"=a" (
result),
492 "=m" (saved_ebx),
"=d" (
dummy)
493 :
"d" (old_val2),
"a" (old_val1),
494 "c" (new_val2),
"m" (new_val1)
501 __asm__ __volatile__(
"mov %%edi, %3\n\t"
505 "lock; cmpxchg8b (%%edi)\n\t"
509 :
"+m" (*addr),
"=a" (
result),
510 "=m" (saved_ebx),
"=m" (saved_edi),
"=d" (
dummy)
511 :
"d" (old_val2),
"a" (old_val1),
512 "c" (new_val2),
"m" (new_val1)
521# if defined(__GCC_ASM_FLAG_OUTPUTS__)
522 __asm__ __volatile__ (
"lock; cmpxchg8b %0"
523 :
"+m" (*addr),
"=@ccz" (
result),
524 "+d" (old_val2),
"+a" (old_val1)
525 :
"c" (new_val2),
"b" (new_val1)
530 __asm__ __volatile__ (
"lock; cmpxchg8b %0; setz %1"
532 :
"d" (old_val2),
"a" (old_val1),
533 "c" (new_val2),
"b" (new_val1)
539# define AO_HAVE_compare_double_and_swap_double_full
541#elif defined(__ILP32__) || !defined(__x86_64__)
542# include "../standard_ao_double_t.h"
546# ifndef AO_PREFER_GENERALIZED
547# define AO_ACCESS_double_CHECK_ALIGNED
548# include "../loadstore/double_atomic_load_store.h"
559 return __sync_bool_compare_and_swap(&addr->
AO_whole,
563# define AO_HAVE_double_compare_and_swap_full
565#elif defined(AO_CMPXCHG16B_AVAILABLE) \
566 || (defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16) \
567 && !defined(AO_THREAD_SANITIZER))
568# include "../standard_ao_double_t.h"
598# if defined(__GCC_ASM_FLAG_OUTPUTS__)
599 __asm__ __volatile__(
"lock; cmpxchg16b %0"
600 :
"+m" (*addr),
"=@ccz" (
result),
601 "+d" (old_val2),
"+a" (old_val1)
602 :
"c" (new_val2),
"b" (new_val1)
607 __asm__ __volatile__(
"lock; cmpxchg16b %0; setz %1"
609 :
"d" (old_val2),
"a" (old_val1),
610 "c" (new_val2),
"b" (new_val1)
615# define AO_HAVE_compare_double_and_swap_double_full
617#elif defined(AO_WEAK_DOUBLE_CAS_EMULATION)
618# include "../standard_ao_double_t.h"
643 old_val1, old_val2, new_val1, new_val2);
645# define AO_HAVE_compare_double_and_swap_double_full
648#ifdef AO_GCC_ATOMIC_TEST_AND_SET
652#undef AO_GCC_FORCE_HAVE_CAS
653#undef AO_SKIPATOMIC_double_compare_and_swap_ANY
654#undef AO_SKIPATOMIC_double_load
655#undef AO_SKIPATOMIC_double_load_acquire
656#undef AO_SKIPATOMIC_double_store
657#undef AO_SKIPATOMIC_double_store_release
AO_INLINE int AO_double_compare_and_swap_full(volatile AO_double_t *addr, AO_double_t old_val, AO_double_t new_val)
AO_INLINE void AO_nop_full(void)
#define AO_compare_double_and_swap_double_full(addr, old1, old2, newval1, newval2)
AO_API int AO_compare_double_and_swap_double_emulation(volatile AO_double_t *addr, AO_t old_val1, AO_t old_val2, AO_t new_val1, AO_t new_val2)
#define AO_fetch_compare_and_swap_full(addr, old, newval)
AO_INLINE unsigned char AO_char_fetch_and_add_full(volatile unsigned char *p, unsigned char incr)
AO_INLINE void AO_xor_full(volatile AO_t *p, AO_t value)
AO_INLINE void AO_short_and_full(volatile unsigned short *p, unsigned short value)
AO_INLINE unsigned short AO_short_fetch_compare_and_swap_full(volatile unsigned short *addr, unsigned short old_val, unsigned short new_val)
AO_INLINE void AO_or_full(volatile AO_t *p, AO_t value)
AO_INLINE void AO_char_and_full(volatile unsigned char *p, unsigned char value)
AO_INLINE int AO_compare_and_swap_full(volatile AO_t *addr, AO_t old, AO_t new_val)
AO_INLINE AO_t AO_fetch_and_add_full(volatile AO_t *p, AO_t incr)
AO_INLINE void AO_char_or_full(volatile unsigned char *p, unsigned char value)
AO_INLINE unsigned short AO_short_fetch_and_add_full(volatile unsigned short *p, unsigned short incr)
AO_INLINE unsigned char AO_char_fetch_compare_and_swap_full(volatile unsigned char *addr, unsigned char old_val, unsigned char new_val)
AO_INLINE AO_TS_VAL_t AO_test_and_set_full(volatile AO_TS_t *addr)
AO_INLINE void AO_char_xor_full(volatile unsigned char *p, unsigned char value)
AO_INLINE void AO_short_xor_full(volatile unsigned short *p, unsigned short value)
AO_INLINE void AO_short_or_full(volatile unsigned short *p, unsigned short value)
AO_INLINE void AO_and_full(volatile AO_t *p, AO_t value)
AO_INLINE unsigned AO_int_fetch_and_add_full(volatile unsigned *addr, unsigned incr)
AO_INLINE void AO_int_and_full(volatile unsigned *addr, unsigned value)
AO_INLINE void AO_int_xor_full(volatile unsigned *addr, unsigned value)
AO_INLINE void AO_int_or_full(volatile unsigned *addr, unsigned value)
AO_INLINE unsigned AO_int_fetch_compare_and_swap_full(volatile unsigned *addr, unsigned old_val, unsigned new_val)
double_ptr_storage AO_whole