From a6d9efc45938225665f7708f98a81fb6a7724f0f Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Thu, 8 Dec 2011 16:39:56 +0400 Subject: [PATCH] Add new macro (AO_PREFER_GENERALIZED) to favor generalized primitives over direct assembly-based ones * configure.ac (AO_PREFER_GENERALIZED): New AC template. * src/atomic_ops/sysdeps/armcc/arm_v6.h (AO_test_and_set, AO_HAVE_test_and_set, AO_fetch_and_add, AO_HAVE_fetch_and_add, AO_fetch_and_add1, AO_HAVE_fetch_and_add1, AO_fetch_and_sub1, AO_HAVE_fetch_and_sub1): Do not define if AO_PREFER_GENERALIZED. * src/atomic_ops/sysdeps/gcc/arm.h (AO_test_and_set, AO_HAVE_test_and_set, AO_fetch_and_add, AO_HAVE_fetch_and_add, AO_fetch_and_add1, AO_HAVE_fetch_and_add1, AO_fetch_and_sub1, AO_HAVE_fetch_and_sub1): Likewise. * src/atomic_ops/sysdeps/gcc/avr32.h (AO_test_and_set_full, AO_HAVE_test_and_set_full): Likewise. * src/atomic_ops/sysdeps/gcc/hexagon.h (AO_fetch_and_add, AO_HAVE_fetch_and_add, AO_test_and_set, AO_HAVE_test_and_set): Likewise. * src/atomic_ops/sysdeps/gcc/ia64.h (AO_fetch_and_add1_acquire, AO_HAVE_fetch_and_add1_acquire, AO_fetch_and_add1_release, AO_HAVE_fetch_and_add1_release, AO_fetch_and_sub1_acquire, AO_HAVE_fetch_and_sub1_acquire, AO_fetch_and_sub1_release, AO_HAVE_fetch_and_sub1_release, AO_int_fetch_and_add1_acquire, AO_HAVE_int_fetch_and_add1_acquire, AO_int_fetch_and_add1_release, AO_HAVE_int_fetch_and_add1_release, AO_int_fetch_and_sub1_acquire, AO_HAVE_int_fetch_and_sub1_acquire, AO_int_fetch_and_sub1_release, AO_HAVE_int_fetch_and_sub1_release): Likewise. * src/atomic_ops/sysdeps/gcc/powerpc.h (AO_test_and_set, AO_HAVE_test_and_set, AO_test_and_set_acquire, AO_HAVE_test_and_set_acquire, AO_test_and_set_release, AO_HAVE_test_and_set_release, AO_test_and_set_full, AO_HAVE_test_and_set_full): Likewise. * src/atomic_ops/sysdeps/gcc/x86.h (AO_fetch_and_add_full, AO_HAVE_fetch_and_add_full, AO_and_full, AO_HAVE_and_full, AO_or_full, AO_HAVE_or_full, AO_xor_full, AO_HAVE_xor_full): Likewise. * src/atomic_ops/sysdeps/gcc/x86_64.h (AO_fetch_and_add_full, AO_HAVE_fetch_and_add_full, AO_and_full, AO_HAVE_and_full, AO_or_full, AO_HAVE_or_full, AO_xor_full, AO_HAVE_xor_full): Likewise. * src/atomic_ops/sysdeps/hpc/ia64.h (AO_fetch_and_add1_acquire, AO_HAVE_fetch_and_add1_acquire, AO_fetch_and_add1_release, AO_HAVE_fetch_and_add1_release, AO_fetch_and_sub1_acquire, AO_HAVE_fetch_and_sub1_acquire, AO_fetch_and_sub1_release, AO_HAVE_fetch_and_sub1_release): Likewise. * src/atomic_ops/sysdeps/ibmc/powerpc.h (AO_test_and_set_acquire, AO_HAVE_test_and_set_acquire, AO_test_and_set_release, AO_HAVE_test_and_set_release, AO_test_and_set_full, AO_HAVE_test_and_set_full): Likewise. * src/atomic_ops/sysdeps/icc/ia64.h (AO_fetch_and_add1_acquire, AO_HAVE_fetch_and_add1_acquire, AO_fetch_and_add1_release, AO_HAVE_fetch_and_add1_release, AO_fetch_and_sub1_acquire, AO_HAVE_fetch_and_sub1_acquire, AO_fetch_and_sub1_release, AO_HAVE_fetch_and_sub1_release): Likewise. * src/atomic_ops/sysdeps/msftc/x86_64.h (AO_fetch_and_add_full, AO_HAVE_fetch_and_add_full, AO_fetch_and_add1_full, AO_HAVE_fetch_and_add1_full, AO_fetch_and_sub1_full, AO_HAVE_fetch_and_sub1_full): Likewise. * src/atomic_ops/sysdeps/sunc/x86.h (AO_fetch_and_add_full, AO_HAVE_fetch_and_add_full, AO_and_full, AO_HAVE_and_full, AO_or_full, AO_HAVE_or_full, AO_xor_full, AO_HAVE_xor_full): Likewise. * src/atomic_ops/sysdeps/sunc/x86_64.h (AO_fetch_and_add_full, AO_HAVE_fetch_and_add_full, AO_and_full, AO_HAVE_and_full, AO_or_full, AO_HAVE_or_full, AO_xor_full, AO_HAVE_xor_full): Likewise. * src/atomic_ops/sysdeps/gcc/arm.h (AO_test_and_set_full, AO_HAVE_test_and_set_full): Do not define if AO_PREFER_GENERALIZED (but only in case of ARMv6+). * src/atomic_ops/sysdeps/msftc/common32_defs.h (_InterlockedIncrement, _InterlockedDecrement, _InterlockedExchangeAdd): Do not declare intrinsic if both AO_PREFER_GENERALIZED and AO_ASSUME_WINDOWS98. * src/atomic_ops/sysdeps/msftc/common32_defs.h (AO_fetch_and_add_full, AO_HAVE_fetch_and_add_full, AO_fetch_and_add1_full, AO_HAVE_fetch_and_add1_full, AO_fetch_and_sub1_full, AO_HAVE_fetch_and_sub1_full): Do not define if both AO_PREFER_GENERALIZED and AO_ASSUME_WINDOWS98. * src/atomic_ops/sysdeps/msftc/x86_64.h (_InterlockedIncrement64, _InterlockedDecrement64, _InterlockedExchangeAdd64): Do not declare intrinsic if AO_PREFER_GENERALIZED. --- configure.ac | 2 ++ src/atomic_ops/sysdeps/armcc/arm_v6.h | 2 ++ src/atomic_ops/sysdeps/gcc/arm.h | 4 ++++ src/atomic_ops/sysdeps/gcc/avr32.h | 12 +++++++----- src/atomic_ops/sysdeps/gcc/hexagon.h | 2 ++ src/atomic_ops/sysdeps/gcc/ia64.h | 4 ++++ src/atomic_ops/sysdeps/gcc/powerpc.h | 4 ++++ src/atomic_ops/sysdeps/gcc/x86.h | 4 ++++ src/atomic_ops/sysdeps/gcc/x86_64.h | 4 ++++ src/atomic_ops/sysdeps/hpc/ia64.h | 2 ++ src/atomic_ops/sysdeps/ibmc/powerpc.h | 2 ++ src/atomic_ops/sysdeps/icc/ia64.h | 2 ++ src/atomic_ops/sysdeps/msftc/common32_defs.h | 10 +++++++--- src/atomic_ops/sysdeps/msftc/x86_64.h | 10 +++++++--- src/atomic_ops/sysdeps/sunc/x86.h | 4 ++++ src/atomic_ops/sysdeps/sunc/x86_64.h | 4 ++++ 16 files changed, 61 insertions(+), 11 deletions(-) diff --git a/configure.ac b/configure.ac index 4427849..763ec56 100644 --- a/configure.ac +++ b/configure.ac @@ -83,6 +83,8 @@ AH_TEMPLATE([AO_TRACE_MALLOC], [Trace AO_malloc/free calls (for debug only)]) # These macros are tested in public headers AH_TEMPLATE([AO_GENERALIZE_ASM_BOOL_CAS], [Force compare_and_swap definition via fetch_compare_and_swap]) +AH_TEMPLATE([AO_PREFER_GENERALIZED], + [Prefer generalized definitions to direct assembly-based ones]) AH_TEMPLATE([AO_USE_PTHREAD_DEFS], [Emulate atomic operations via slow and async-signal-unsafe \ pthread locking]) diff --git a/src/atomic_ops/sysdeps/armcc/arm_v6.h b/src/atomic_ops/sysdeps/armcc/arm_v6.h index 0ef50c3..57b8476 100644 --- a/src/atomic_ops/sysdeps/armcc/arm_v6.h +++ b/src/atomic_ops/sysdeps/armcc/arm_v6.h @@ -96,6 +96,7 @@ __asm { more flexible, other instructions can be done between the LDREX and STREX accesses. " */ +#ifndef AO_PREFER_GENERALIZED AO_INLINE AO_TS_VAL_t AO_test_and_set(volatile AO_TS_t *addr) { @@ -173,6 +174,7 @@ __asm { return result; } #define AO_HAVE_fetch_and_sub1 +#endif /* !AO_PREFER_GENERALIZED */ /* NEC LE-IT: compare and swap */ #ifndef AO_GENERALIZE_ASM_BOOL_CAS diff --git a/src/atomic_ops/sysdeps/gcc/arm.h b/src/atomic_ops/sysdeps/gcc/arm.h index 4f14271..4496d9a 100644 --- a/src/atomic_ops/sysdeps/gcc/arm.h +++ b/src/atomic_ops/sysdeps/gcc/arm.h @@ -145,6 +145,7 @@ AO_INLINE void AO_store(volatile AO_t *addr, AO_t value) interrupt latencies. LDREX, STREX are more flexible, other instructions can be done between the LDREX and STREX accesses." */ +#ifndef AO_PREFER_GENERALIZED #if !defined(AO_FORCE_USE_SWP) || defined(__thumb2__) /* But, on the other hand, there could be a considerable performance */ /* degradation in case of a race. Eg., test_atomic.c executing */ @@ -238,6 +239,7 @@ AO_fetch_and_sub1(volatile AO_t *p) return result; } #define AO_HAVE_fetch_and_sub1 +#endif /* !AO_PREFER_GENERALIZED */ /* NEC LE-IT: compare and swap */ #ifndef AO_GENERALIZE_ASM_BOOL_CAS @@ -351,6 +353,8 @@ AO_fetch_compare_and_swap(volatile AO_t *addr, AO_t old_val, AO_t new_val) #endif /* __ARM_ARCH_x */ #if !defined(AO_HAVE_test_and_set_full) && !defined(AO_HAVE_test_and_set) \ + && (!defined(AO_PREFER_GENERALIZED) \ + || !defined(AO_HAVE_fetch_compare_and_swap)) \ && !defined(__ARM_ARCH_2__) && !defined(__ARM_ARCH_6M__) AO_INLINE AO_TS_VAL_t AO_test_and_set_full(volatile AO_TS_t *addr) diff --git a/src/atomic_ops/sysdeps/gcc/avr32.h b/src/atomic_ops/sysdeps/gcc/avr32.h index c1bf56c..c5a12a3 100644 --- a/src/atomic_ops/sysdeps/gcc/avr32.h +++ b/src/atomic_ops/sysdeps/gcc/avr32.h @@ -28,9 +28,10 @@ #include "../test_and_set_t_is_ao_t.h" -AO_INLINE AO_TS_VAL_t -AO_test_and_set_full(volatile AO_TS_t *addr) -{ +#ifndef AO_PREFER_GENERALIZED + AO_INLINE AO_TS_VAL_t + AO_test_and_set_full(volatile AO_TS_t *addr) + { register long ret; __asm__ __volatile__( @@ -40,8 +41,9 @@ AO_test_and_set_full(volatile AO_TS_t *addr) : "memory"); return (AO_TS_VAL_t)ret; -} -#define AO_HAVE_test_and_set_full + } +# define AO_HAVE_test_and_set_full +#endif /* !AO_PREFER_GENERALIZED */ AO_INLINE int AO_compare_and_swap_full(volatile AO_t *addr, AO_t old, AO_t new_val) diff --git a/src/atomic_ops/sysdeps/gcc/hexagon.h b/src/atomic_ops/sysdeps/gcc/hexagon.h index 38d73f9..da7eb4e 100644 --- a/src/atomic_ops/sysdeps/gcc/hexagon.h +++ b/src/atomic_ops/sysdeps/gcc/hexagon.h @@ -27,6 +27,7 @@ AO_nop_full(void) /* The Hexagon has load-locked, store-conditional primitives, and so */ /* resulting code is very nearly identical to that of PowerPC. */ +#ifndef AO_PREFER_GENERALIZED AO_INLINE AO_t AO_fetch_and_add(volatile AO_t *addr, AO_t incr) { @@ -67,6 +68,7 @@ AO_test_and_set(volatile AO_TS_t *addr) return (AO_TS_VAL_t)oldval; } #define AO_HAVE_test_and_set +#endif /* !AO_PREFER_GENERALIZED */ #ifndef AO_GENERALIZE_ASM_BOOL_CAS AO_INLINE int diff --git a/src/atomic_ops/sysdeps/gcc/ia64.h b/src/atomic_ops/sysdeps/gcc/ia64.h index 97e325e..88f4c90 100644 --- a/src/atomic_ops/sysdeps/gcc/ia64.h +++ b/src/atomic_ops/sysdeps/gcc/ia64.h @@ -61,6 +61,7 @@ AO_nop_full(void) } #define AO_HAVE_nop_full +#ifndef AO_PREFER_GENERALIZED AO_INLINE AO_t AO_fetch_and_add1_acquire (volatile AO_t *addr) { @@ -108,6 +109,7 @@ AO_fetch_and_sub1_release (volatile AO_t *addr) return result; } #define AO_HAVE_fetch_and_sub1_release +#endif /* !AO_PREFER_GENERALIZED */ AO_INLINE AO_t AO_fetch_compare_and_swap_acquire(volatile AO_t *addr, AO_t old, AO_t new_val) @@ -202,6 +204,7 @@ AO_short_fetch_compare_and_swap_release(volatile unsigned short *addr, /* FIXME: Add compare_double_and_swap_double for the _ILP32 case. */ #else +# ifndef AO_PREFER_GENERALIZED AO_INLINE unsigned int AO_int_fetch_and_add1_acquire(volatile unsigned int *addr) { @@ -245,6 +248,7 @@ AO_short_fetch_compare_and_swap_release(volatile unsigned short *addr, return result; } # define AO_HAVE_int_fetch_and_sub1_release +# endif /* !AO_PREFER_GENERALIZED */ AO_INLINE unsigned int AO_int_fetch_compare_and_swap_acquire(volatile unsigned int *addr, diff --git a/src/atomic_ops/sysdeps/gcc/powerpc.h b/src/atomic_ops/sysdeps/gcc/powerpc.h index e508724..275a277 100644 --- a/src/atomic_ops/sysdeps/gcc/powerpc.h +++ b/src/atomic_ops/sysdeps/gcc/powerpc.h @@ -102,6 +102,7 @@ AO_store_release(volatile AO_t *addr, AO_t value) } #define AO_HAVE_store_release +#ifndef AO_PREFER_GENERALIZED /* This is similar to the code in the garbage collector. Deleting */ /* this and having it synthesized from compare_and_swap would probably */ /* only cost us a load immediate instruction. */ @@ -165,6 +166,7 @@ AO_test_and_set_full(volatile AO_TS_t *addr) { return result; } #define AO_HAVE_test_and_set_full +#endif /* !AO_PREFER_GENERALIZED */ #ifndef AO_GENERALIZE_ASM_BOOL_CAS @@ -294,6 +296,7 @@ AO_fetch_compare_and_swap_full(volatile AO_t *addr, AO_t old_val, } #define AO_HAVE_fetch_compare_and_swap_full +#ifndef AO_PREFER_GENERALIZED AO_INLINE AO_t AO_fetch_and_add(volatile AO_t *addr, AO_t incr) { AO_t oldval; @@ -345,6 +348,7 @@ AO_fetch_and_add_full(volatile AO_t *addr, AO_t incr) { return result; } #define AO_HAVE_fetch_and_add_full +#endif /* !AO_PREFER_GENERALIZED */ #if defined(__powerpc64__) || defined(__ppc64__) || defined(__64BIT__) /* Empty */ diff --git a/src/atomic_ops/sysdeps/gcc/x86.h b/src/atomic_ops/sysdeps/gcc/x86.h index 11ac54b..0c7d703 100644 --- a/src/atomic_ops/sysdeps/gcc/x86.h +++ b/src/atomic_ops/sysdeps/gcc/x86.h @@ -56,6 +56,7 @@ AO_nop_full(void) /* currently needed or useful for cached memory accesses. */ /* Really only works for 486 and later */ +#ifndef AO_PREFER_GENERALIZED AO_INLINE AO_t AO_fetch_and_add_full (volatile AO_t *p, AO_t incr) { @@ -67,6 +68,7 @@ AO_fetch_and_add_full (volatile AO_t *p, AO_t incr) return result; } #define AO_HAVE_fetch_and_add_full +#endif /* !AO_PREFER_GENERALIZED */ AO_INLINE unsigned char AO_char_fetch_and_add_full (volatile unsigned char *p, unsigned char incr) @@ -92,6 +94,7 @@ AO_short_fetch_and_add_full (volatile unsigned short *p, unsigned short incr) } #define AO_HAVE_short_fetch_and_add_full +#ifndef AO_PREFER_GENERALIZED /* Really only works for 486 and later */ AO_INLINE void AO_and_full (volatile AO_t *p, AO_t value) @@ -116,6 +119,7 @@ AO_xor_full (volatile AO_t *p, AO_t value) "=m" (*p) : "r" (value), "m" (*p) : "memory"); } #define AO_HAVE_xor_full +#endif /* !AO_PREFER_GENERALIZED */ AO_INLINE AO_TS_VAL_t AO_test_and_set_full(volatile AO_TS_t *addr) diff --git a/src/atomic_ops/sysdeps/gcc/x86_64.h b/src/atomic_ops/sysdeps/gcc/x86_64.h index 062eeb5..cf46d1e 100644 --- a/src/atomic_ops/sysdeps/gcc/x86_64.h +++ b/src/atomic_ops/sysdeps/gcc/x86_64.h @@ -42,6 +42,7 @@ AO_nop_full(void) /* As far as we can tell, the lfence and sfence instructions are not */ /* currently needed or useful for cached memory accesses. */ +#ifndef AO_PREFER_GENERALIZED AO_INLINE AO_t AO_fetch_and_add_full (volatile AO_t *p, AO_t incr) { @@ -53,6 +54,7 @@ AO_fetch_and_add_full (volatile AO_t *p, AO_t incr) return result; } #define AO_HAVE_fetch_and_add_full +#endif /* !AO_PREFER_GENERALIZED */ AO_INLINE unsigned char AO_char_fetch_and_add_full (volatile unsigned char *p, unsigned char incr) @@ -90,6 +92,7 @@ AO_int_fetch_and_add_full (volatile unsigned int *p, unsigned int incr) } #define AO_HAVE_int_fetch_and_add_full +#ifndef AO_PREFER_GENERALIZED AO_INLINE void AO_and_full (volatile AO_t *p, AO_t value) { @@ -113,6 +116,7 @@ AO_xor_full (volatile AO_t *p, AO_t value) "=m" (*p) : "r" (value), "m" (*p) : "memory"); } #define AO_HAVE_xor_full +#endif /* !AO_PREFER_GENERALIZED */ AO_INLINE AO_TS_VAL_t AO_test_and_set_full(volatile AO_TS_t *addr) diff --git a/src/atomic_ops/sysdeps/hpc/ia64.h b/src/atomic_ops/sysdeps/hpc/ia64.h index ab0e0e9..6391eda 100644 --- a/src/atomic_ops/sysdeps/hpc/ia64.h +++ b/src/atomic_ops/sysdeps/hpc/ia64.h @@ -49,6 +49,7 @@ AO_nop_full(void) } #define AO_HAVE_nop_full +#ifndef AO_PREFER_GENERALIZED AO_INLINE AO_t AO_fetch_and_add1_acquire (volatile AO_t *p) { @@ -80,6 +81,7 @@ AO_fetch_and_sub1_release (volatile AO_t *p) _LDHINT_NONE, _UP_MEM_FENCE); } #define AO_HAVE_fetch_and_sub1_release +#endif /* !AO_PREFER_GENERALIZED */ AO_INLINE AO_t AO_fetch_compare_and_swap_acquire(volatile AO_t *addr, AO_t old_val, diff --git a/src/atomic_ops/sysdeps/ibmc/powerpc.h b/src/atomic_ops/sysdeps/ibmc/powerpc.h index 2c39ec1..2438c8c 100644 --- a/src/atomic_ops/sysdeps/ibmc/powerpc.h +++ b/src/atomic_ops/sysdeps/ibmc/powerpc.h @@ -51,6 +51,7 @@ AO_store_release(volatile AO_t *addr, AO_t value) } #define AO_HAVE_store_release +#ifndef AO_PREFER_GENERALIZED /* This is similar to the code in the garbage collector. Deleting */ /* this and having it synthesized from compare_and_swap would probably */ /* only cost us a load immediate instruction. */ @@ -84,6 +85,7 @@ AO_test_and_set_full(volatile AO_TS_t *addr) { return result; } #define AO_HAVE_test_and_set_full +#endif /* !AO_PREFER_GENERALIZED */ /*AO_INLINE AO_t AO_fetch_compare_and_swap(volatile AO_t *addr, AO_t old_val, AO_t new_val) diff --git a/src/atomic_ops/sysdeps/icc/ia64.h b/src/atomic_ops/sysdeps/icc/ia64.h index f7b8b58..b43a501 100644 --- a/src/atomic_ops/sysdeps/icc/ia64.h +++ b/src/atomic_ops/sysdeps/icc/ia64.h @@ -104,6 +104,7 @@ AO_nop_full(void) } #define AO_HAVE_nop_full +#ifndef AO_PREFER_GENERALIZED AO_INLINE AO_t AO_fetch_and_add1_acquire(volatile AO_t *p) { @@ -131,6 +132,7 @@ AO_fetch_and_sub1_release(volatile AO_t *p) return __fetchadd8_rel((unsigned __int64 *)p, -1); } #define AO_HAVE_fetch_and_sub1_release +#endif /* !AO_PREFER_GENERALIZED */ AO_INLINE AO_t AO_fetch_compare_and_swap_acquire(volatile AO_t *addr, AO_t old_val, diff --git a/src/atomic_ops/sysdeps/msftc/common32_defs.h b/src/atomic_ops/sysdeps/msftc/common32_defs.h index 4acff0a..989974e 100644 --- a/src/atomic_ops/sysdeps/msftc/common32_defs.h +++ b/src/atomic_ops/sysdeps/msftc/common32_defs.h @@ -63,15 +63,18 @@ # endif # endif /* _MSC_VER < 1400 */ -# pragma intrinsic (_InterlockedIncrement) -# pragma intrinsic (_InterlockedDecrement) -# pragma intrinsic (_InterlockedExchangeAdd) +# if !defined(AO_PREFER_GENERALIZED) || !defined(AO_ASSUME_WINDOWS98) +# pragma intrinsic (_InterlockedIncrement) +# pragma intrinsic (_InterlockedDecrement) +# pragma intrinsic (_InterlockedExchangeAdd) +# endif /* !AO_PREFER_GENERALIZED */ # pragma intrinsic (_InterlockedCompareExchange) # define AO_INTERLOCKED_VOLATILE volatile #endif /* _MSC_VER >= 1310 */ +#if !defined(AO_PREFER_GENERALIZED) || !defined(AO_ASSUME_WINDOWS98) AO_INLINE AO_t AO_fetch_and_add_full(volatile AO_t *p, AO_t incr) { @@ -93,6 +96,7 @@ AO_fetch_and_sub1_full(volatile AO_t *p) return _InterlockedDecrement((LONG AO_INTERLOCKED_VOLATILE *)p) + 1; } #define AO_HAVE_fetch_and_sub1_full +#endif /* !AO_PREFER_GENERALIZED */ #ifdef AO_ASSUME_WINDOWS98 AO_INLINE AO_t diff --git a/src/atomic_ops/sysdeps/msftc/x86_64.h b/src/atomic_ops/sysdeps/msftc/x86_64.h index e237b6a..254eec4 100644 --- a/src/atomic_ops/sysdeps/msftc/x86_64.h +++ b/src/atomic_ops/sysdeps/msftc/x86_64.h @@ -46,11 +46,14 @@ /* Assume _MSC_VER >= 1400 */ #include -#pragma intrinsic (_InterlockedIncrement64) -#pragma intrinsic (_InterlockedDecrement64) -#pragma intrinsic (_InterlockedExchangeAdd64) #pragma intrinsic (_InterlockedCompareExchange64) +#ifndef AO_PREFER_GENERALIZED + +# pragma intrinsic (_InterlockedIncrement64) +# pragma intrinsic (_InterlockedDecrement64) +# pragma intrinsic (_InterlockedExchangeAdd64) + AO_INLINE AO_t AO_fetch_and_add_full (volatile AO_t *p, AO_t incr) { @@ -71,6 +74,7 @@ AO_fetch_and_sub1_full (volatile AO_t *p) return _InterlockedDecrement64((LONGLONG volatile *)p) + 1; } #define AO_HAVE_fetch_and_sub1_full +#endif /* !AO_PREFER_GENERALIZED */ AO_INLINE AO_t AO_fetch_compare_and_swap_full(volatile AO_t *addr, AO_t old_val, diff --git a/src/atomic_ops/sysdeps/sunc/x86.h b/src/atomic_ops/sysdeps/sunc/x86.h index 6b55d0a..7cad139 100644 --- a/src/atomic_ops/sysdeps/sunc/x86.h +++ b/src/atomic_ops/sysdeps/sunc/x86.h @@ -53,6 +53,7 @@ AO_nop_full(void) /* currently needed or useful for cached memory accesses. */ /* Really only works for 486 and later */ +#ifndef AO_PREFER_GENERALIZED AO_INLINE AO_t AO_fetch_and_add_full (volatile AO_t *p, AO_t incr) { @@ -64,6 +65,7 @@ AO_fetch_and_add_full (volatile AO_t *p, AO_t incr) return result; } #define AO_HAVE_fetch_and_add_full +#endif /* !AO_PREFER_GENERALIZED */ AO_INLINE unsigned char AO_char_fetch_and_add_full (volatile unsigned char *p, unsigned char incr) @@ -89,6 +91,7 @@ AO_short_fetch_and_add_full (volatile unsigned short *p, unsigned short incr) } #define AO_HAVE_short_fetch_and_add_full +#ifndef AO_PREFER_GENERALIZED /* Really only works for 486 and later */ AO_INLINE void AO_and_full (volatile AO_t *p, AO_t value) @@ -116,6 +119,7 @@ AO_xor_full (volatile AO_t *p, AO_t value) : "memory"); } #define AO_HAVE_xor_full +#endif /* !AO_PREFER_GENERALIZED */ AO_INLINE AO_TS_VAL_t AO_test_and_set_full (volatile AO_TS_t *addr) diff --git a/src/atomic_ops/sysdeps/sunc/x86_64.h b/src/atomic_ops/sysdeps/sunc/x86_64.h index 8162345..a5fe2d4 100644 --- a/src/atomic_ops/sysdeps/sunc/x86_64.h +++ b/src/atomic_ops/sysdeps/sunc/x86_64.h @@ -42,6 +42,7 @@ AO_nop_full(void) /* As far as we can tell, the lfence and sfence instructions are not */ /* currently needed or useful for cached memory accesses. */ +#ifndef AO_PREFER_GENERALIZED AO_INLINE AO_t AO_fetch_and_add_full (volatile AO_t *p, AO_t incr) { @@ -53,6 +54,7 @@ AO_fetch_and_add_full (volatile AO_t *p, AO_t incr) return result; } #define AO_HAVE_fetch_and_add_full +#endif /* !AO_PREFER_GENERALIZED */ AO_INLINE unsigned char AO_char_fetch_and_add_full (volatile unsigned char *p, unsigned char incr) @@ -90,6 +92,7 @@ AO_int_fetch_and_add_full (volatile unsigned int *p, unsigned int incr) } #define AO_HAVE_int_fetch_and_add_full +#ifndef AO_PREFER_GENERALIZED AO_INLINE void AO_and_full (volatile AO_t *p, AO_t value) { @@ -116,6 +119,7 @@ AO_xor_full (volatile AO_t *p, AO_t value) : "memory"); } #define AO_HAVE_xor_full +#endif /* !AO_PREFER_GENERALIZED */ AO_INLINE AO_TS_VAL_t AO_test_and_set_full (volatile AO_TS_t *addr) -- 2.7.4