From: Ivan Maidanski Date: Mon, 8 Oct 2012 10:51:30 +0000 (+0400) Subject: Properly fix compare_double_and_swap_double for gcc/x32 (use built-in CAS) X-Git-Tag: libatomic_ops-7_4_0~72^2~3 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=cbe517e6d41ab721a14151c0db40dd56cb98cc86;p=platform%2Fupstream%2Flibatomic_ops.git Properly fix compare_double_and_swap_double for gcc/x32 (use built-in CAS) * src/atomic_ops/sysdeps/gcc/x86.h (AO_double_compare_and_swap_full): New function (only if __x86_64__) implemented using GCC built-in __sync CAS primitive available for x32. * src/atomic_ops/sysdeps/gcc/x86.h (AO_HAVE_double_compare_and_swap_full): New macro (for x32 only). * src/atomic_ops/sysdeps/gcc/x86.h (AO_compare_double_and_swap_double_full): Implement using double_compare_and_swap_full instead of cmpxchg8b for x32 (since x86_64 has available cmpxchg and cmpxchg16b but not cmpxchg8b). --- diff --git a/src/atomic_ops/sysdeps/gcc/x86.h b/src/atomic_ops/sysdeps/gcc/x86.h index 6cdacd1..c8d8ade 100644 --- a/src/atomic_ops/sysdeps/gcc/x86.h +++ b/src/atomic_ops/sysdeps/gcc/x86.h @@ -176,6 +176,8 @@ AO_fetch_compare_and_swap_full(volatile AO_t *addr, AO_t old_val, } #define AO_HAVE_fetch_compare_and_swap_full +#if !defined(__x86_64__) + /* Returns nonzero if the comparison succeeded. */ /* Really requires at least a Pentium. */ AO_INLINE int @@ -238,4 +240,38 @@ AO_compare_double_and_swap_double_full(volatile AO_double_t *addr, } #define AO_HAVE_compare_double_and_swap_double_full +#else /* x86_64 && ILP32 */ + + /* X32 has native support for 64-bit integer operations (AO_double_t */ + /* is a 64-bit integer and we could use 64-bit cmpxchg). */ + /* This primitive is used by compare_double_and_swap_double_full. */ + AO_INLINE int + AO_double_compare_and_swap_full(volatile AO_double_t *addr, + AO_double_t old_val, AO_double_t new_val) + { + /* It is safe to use __sync CAS built-in here. */ + return __sync_bool_compare_and_swap(&addr->AO_whole, + old_val.AO_whole, new_val.AO_whole + /* empty protection list */); + } +# define AO_HAVE_double_compare_and_swap_full + + /* TODO: Remove if generalized. */ + AO_INLINE int + AO_compare_double_and_swap_double_full(volatile AO_double_t *addr, + AO_t old_val1, AO_t old_val2, + AO_t new_val1, AO_t new_val2) + { + AO_double_t old_w; + AO_double_t new_w; + old_w.AO_val1 = old_val1; + old_w.AO_val2 = old_val2; + new_w.AO_val1 = new_val1; + new_w.AO_val2 = new_val2; + return AO_double_compare_and_swap_full(addr, old_w, new_w); + } +# define AO_HAVE_compare_double_and_swap_double_full + +#endif /* x86_64 && ILP32 */ + #define AO_T_IS_INT