summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Maidanski <ivmai@mail.ru>2017-01-17 01:48:48 +0300
committerIvan Maidanski <ivmai@mail.ru>2017-01-17 01:48:48 +0300
commit7708b76c70c61c0c4aca40f75439ca98537972b2 (patch)
treeb7b70620e6ea96d9c5339cbe44ec1f6ecfde94d1
parent8262e52fb577c634d8d93d76ec2ddecbdba1f995 (diff)
downloadlibatomic_ops-7708b76c70c61c0c4aca40f75439ca98537972b2.tar.gz
Add asm-based char/short/int CAS implementation for gcc/x86[_64]
* src/atomic_ops/sysdeps/gcc/x86.h [!AO_GCC_ATOMIC_TEST_AND_SET] (AO_char_and_full, AO_char_or_full, AO_char_xor_full, AO_short_and_full, AO_short_or_full, AO_short_xor_full): Do not define if AO_PREFER_GENERALIZED. * src/atomic_ops/sysdeps/gcc/x86.h [!AO_GCC_ATOMIC_TEST_AND_SET] (AO_char_fetch_compare_and_swap_full, AO_short_fetch_compare_and_swap_full): Implement. * src/atomic_ops/sysdeps/gcc/x86.h [!AO_GCC_ATOMIC_TEST_AND_SET && __x86_64__ && !__ILP32__] (AO_int_fetch_compare_and_swap_full): Likewise. * src/atomic_ops/sysdeps/gcc/x86.h [!AO_GCC_ATOMIC_TEST_AND_SET && __x86_64__ && !__ILP32__] (AO_int_fetch_and_add_full, AO_int_and_full, AO_int_or_full, AO_int_xor_full): Do not define if AO_PREFER_GENERALIZED.
-rw-r--r--src/atomic_ops/sysdeps/gcc/x86.h64
1 files changed, 63 insertions, 1 deletions
diff --git a/src/atomic_ops/sysdeps/gcc/x86.h b/src/atomic_ops/sysdeps/gcc/x86.h
index 90b64bc..e38f5ca 100644
--- a/src/atomic_ops/sysdeps/gcc/x86.h
+++ b/src/atomic_ops/sysdeps/gcc/x86.h
@@ -169,7 +169,6 @@ AO_short_fetch_and_add_full (volatile unsigned short *p, unsigned short incr)
/* AO_store_full could be implemented directly using "xchg" but it */
/* could be generalized efficiently as an ordinary store accomplished */
/* with AO_nop_full ("mfence" instruction). */
-#endif /* !AO_PREFER_GENERALIZED */
AO_INLINE void
AO_char_and_full (volatile unsigned char *p, unsigned char value)
@@ -224,6 +223,7 @@ AO_short_xor_full (volatile unsigned short *p, unsigned short value)
: "memory");
}
#define AO_HAVE_short_xor_full
+#endif /* !AO_PREFER_GENERALIZED */
AO_INLINE AO_TS_VAL_t
AO_test_and_set_full(volatile AO_TS_t *addr)
@@ -279,8 +279,69 @@ AO_fetch_compare_and_swap_full(volatile AO_t *addr, AO_t old_val,
}
#define AO_HAVE_fetch_compare_and_swap_full
+ AO_INLINE unsigned char
+ AO_char_fetch_compare_and_swap_full(volatile unsigned char *addr,
+ unsigned char old_val,
+ unsigned char new_val)
+ {
+# ifdef AO_USE_SYNC_CAS_BUILTIN
+ return __sync_val_compare_and_swap(addr, old_val, new_val
+ /* empty protection list */);
+# else
+ unsigned char fetched_val;
+
+ __asm__ __volatile__ ("lock; cmpxchgb %3, %4"
+ : "=a" (fetched_val), "=m" (*addr)
+ : "a" (old_val), "r" (new_val), "m" (*addr)
+ : "memory");
+ return fetched_val;
+# endif
+ }
+# define AO_HAVE_char_fetch_compare_and_swap_full
+
+ AO_INLINE unsigned short
+ AO_short_fetch_compare_and_swap_full(volatile unsigned short *addr,
+ unsigned short old_val,
+ unsigned short new_val)
+ {
+# ifdef AO_USE_SYNC_CAS_BUILTIN
+ return __sync_val_compare_and_swap(addr, old_val, new_val
+ /* empty protection list */);
+# else
+ unsigned short fetched_val;
+
+ __asm__ __volatile__ ("lock; cmpxchgw %3, %4"
+ : "=a" (fetched_val), "=m" (*addr)
+ : "a" (old_val), "r" (new_val), "m" (*addr)
+ : "memory");
+ return fetched_val;
+# endif
+ }
+# define AO_HAVE_short_fetch_compare_and_swap_full
+
# if defined(__x86_64__) && !defined(__ILP32__)
AO_INLINE unsigned int
+ AO_int_fetch_compare_and_swap_full(volatile unsigned int *addr,
+ unsigned int old_val,
+ unsigned int new_val)
+ {
+# ifdef AO_USE_SYNC_CAS_BUILTIN
+ return __sync_val_compare_and_swap(addr, old_val, new_val
+ /* empty protection list */);
+# else
+ unsigned int fetched_val;
+
+ __asm__ __volatile__ ("lock; cmpxchgl %3, %4"
+ : "=a" (fetched_val), "=m" (*addr)
+ : "a" (old_val), "r" (new_val), "m" (*addr)
+ : "memory");
+ return fetched_val;
+# endif
+ }
+# define AO_HAVE_int_fetch_compare_and_swap_full
+
+# ifndef AO_PREFER_GENERALIZED
+ AO_INLINE unsigned int
AO_int_fetch_and_add_full (volatile unsigned int *p, unsigned int incr)
{
unsigned int result;
@@ -319,6 +380,7 @@ AO_fetch_compare_and_swap_full(volatile AO_t *addr, AO_t old_val,
: "memory");
}
# define AO_HAVE_int_xor_full
+# endif /* !AO_PREFER_GENERALIZED */
# else
# define AO_T_IS_INT