summaryrefslogtreecommitdiff
path: root/src/atomic_ops
diff options
context:
space:
mode:
authorIvan Maidanski <ivmai@mail.ru>2017-01-24 01:42:06 +0300
committerIvan Maidanski <ivmai@mail.ru>2017-01-24 01:42:06 +0300
commit90281551455f043fc027ad98ac9e7063803b7b31 (patch)
treed4c71939199809f73e0c4b445cd579f0cc0061e6 /src/atomic_ops
parenta013152ae8fb09223b91f3183b40869960a7a79e (diff)
downloadlibatomic_ops-90281551455f043fc027ad98ac9e7063803b7b31.tar.gz
Implement char CAS and char/short add for msftc X86[_64] (VS 2013+)
* src/atomic_ops/sysdeps/msftc/common32_defs.h [_MSC_VER>=1800] (_InterlockedCompareExchange8): Declare intrinsic. * src/atomic_ops/sysdeps/msftc/common32_defs.h [_MSC_VER>=1800 && !AO_PREFER_GENERALIZED && !_M_ARM] (_InterlockedExchangeAdd16, _InterlockedExchangeAdd8): Likewise. * src/atomic_ops/sysdeps/msftc/x86_64.h [_MSC_VER>=1800] (_InterlockedCompareExchange8): Likewise. * src/atomic_ops/sysdeps/msftc/x86_64.h [_MSC_VER>=1800 && !AO_PREFER_GENERALIZED] (_InterlockedExchangeAdd16, _InterlockedExchangeAdd8): Likewise. * src/atomic_ops/sysdeps/msftc/common32_defs.h [_MSC_VER>=1800] (AO_char_fetch_compare_and_swap_full): Implement using intrinsic. * src/atomic_ops/sysdeps/msftc/common32_defs.h [_MSC_VER>=1800 && !AO_PREFER_GENERALIZED && !_M_ARM] (AO_char_fetch_and_add_full, AO_short_fetch_and_add_full): Likewise. * src/atomic_ops/sysdeps/msftc/x86_64.h [_MSC_VER>=1800] (AO_char_fetch_compare_and_swap_full): Likewise. * src/atomic_ops/sysdeps/msftc/x86_64.h [_MSC_VER>=1800 && !AO_PREFER_GENERALIZED] (AO_char_fetch_and_add_full, AO_short_fetch_and_add_full): Likewise. * src/atomic_ops/sysdeps/msftc/x86.h [!AO_NO_ASM_XADD] (AO_char_fetch_and_add_full, AO_short_fetch_and_add_full): Do not define if AO_HAVE_char_fetch_and_add_full. * src/atomic_ops/sysdeps/msftc/x86_64.h [AO_ASM_X64_AVAILABLE] (AO_char_fetch_and_add_full, AO_short_fetch_and_add_full): Do not use asm-based implementation if _MSC_VER>=1800.
Diffstat (limited to 'src/atomic_ops')
-rw-r--r--src/atomic_ops/sysdeps/msftc/common32_defs.h35
-rw-r--r--src/atomic_ops/sysdeps/msftc/x86.h2
-rw-r--r--src/atomic_ops/sysdeps/msftc/x86_64.h40
3 files changed, 75 insertions, 2 deletions
diff --git a/src/atomic_ops/sysdeps/msftc/common32_defs.h b/src/atomic_ops/sysdeps/msftc/common32_defs.h
index c3f5ee9..92f8092 100644
--- a/src/atomic_ops/sysdeps/msftc/common32_defs.h
+++ b/src/atomic_ops/sysdeps/msftc/common32_defs.h
@@ -174,3 +174,38 @@ AO_fetch_and_sub1_full(volatile AO_t *p)
# define AO_HAVE_short_fetch_and_sub1_full
# endif /* !AO_PREFER_GENERALIZED */
#endif /* _MSC_VER > 1400 */
+
+#if _MSC_VER >= 1800 /* Visual Studio 2013+ */
+
+# pragma intrinsic (_InterlockedCompareExchange8)
+
+ AO_INLINE unsigned char
+ AO_char_fetch_compare_and_swap_full(volatile unsigned char *addr,
+ unsigned char old_val,
+ unsigned char new_val)
+ {
+ return _InterlockedCompareExchange8((char volatile *)addr,
+ new_val, old_val);
+ }
+# define AO_HAVE_char_fetch_compare_and_swap_full
+
+# if !defined(AO_PREFER_GENERALIZED) && !defined(_M_ARM)
+# pragma intrinsic (_InterlockedExchangeAdd16)
+# pragma intrinsic (_InterlockedExchangeAdd8)
+
+ AO_INLINE unsigned char
+ AO_char_fetch_and_add_full(volatile unsigned char *p, unsigned char incr)
+ {
+ return _InterlockedExchangeAdd8((char volatile *)p, incr);
+ }
+# define AO_HAVE_char_fetch_and_add_full
+
+ AO_INLINE unsigned short
+ AO_short_fetch_and_add_full(volatile unsigned short *p,
+ unsigned short incr)
+ {
+ return _InterlockedExchangeAdd16((short volatile *)p, incr);
+ }
+# define AO_HAVE_short_fetch_and_add_full
+# endif /* !AO_PREFER_GENERALIZED && !_M_ARM */
+#endif /* _MSC_VER >= 1800 */
diff --git a/src/atomic_ops/sysdeps/msftc/x86.h b/src/atomic_ops/sysdeps/msftc/x86.h
index d9272f5..3de9616 100644
--- a/src/atomic_ops/sysdeps/msftc/x86.h
+++ b/src/atomic_ops/sysdeps/msftc/x86.h
@@ -63,7 +63,7 @@ AO_nop_full(void)
#endif
-#ifndef AO_NO_ASM_XADD
+#if !defined(AO_NO_ASM_XADD) && !defined(AO_HAVE_char_fetch_and_add_full)
AO_INLINE unsigned char
AO_char_fetch_and_add_full(volatile unsigned char *p, unsigned char incr)
{
diff --git a/src/atomic_ops/sysdeps/msftc/x86_64.h b/src/atomic_ops/sysdeps/msftc/x86_64.h
index b5eb298..fead273 100644
--- a/src/atomic_ops/sysdeps/msftc/x86_64.h
+++ b/src/atomic_ops/sysdeps/msftc/x86_64.h
@@ -171,7 +171,41 @@ AO_int_fetch_and_add_full(volatile unsigned int *p, unsigned int incr)
# endif /* !AO_PREFER_GENERALIZED */
#endif /* _MSC_VER > 1400 */
-#ifdef AO_ASM_X64_AVAILABLE
+#if _MSC_VER >= 1800 /* Visual Studio 2013+ */
+
+# pragma intrinsic (_InterlockedCompareExchange8)
+
+ AO_INLINE unsigned char
+ AO_char_fetch_compare_and_swap_full(volatile unsigned char *addr,
+ unsigned char old_val,
+ unsigned char new_val)
+ {
+ return _InterlockedCompareExchange8((char volatile *)addr,
+ new_val, old_val);
+ }
+# define AO_HAVE_char_fetch_compare_and_swap_full
+
+# ifndef AO_PREFER_GENERALIZED
+# pragma intrinsic (_InterlockedExchangeAdd16)
+# pragma intrinsic (_InterlockedExchangeAdd8)
+
+ AO_INLINE unsigned char
+ AO_char_fetch_and_add_full(volatile unsigned char *p, unsigned char incr)
+ {
+ return _InterlockedExchangeAdd8((char volatile *)p, incr);
+ }
+# define AO_HAVE_char_fetch_and_add_full
+
+ AO_INLINE unsigned short
+ AO_short_fetch_and_add_full(volatile unsigned short *p,
+ unsigned short incr)
+ {
+ return _InterlockedExchangeAdd16((short volatile *)p, incr);
+ }
+# define AO_HAVE_short_fetch_and_add_full
+# endif /* !AO_PREFER_GENERALIZED */
+
+#elif defined(AO_ASM_X64_AVAILABLE)
AO_INLINE unsigned char
AO_char_fetch_and_add_full(volatile unsigned char *p, unsigned char incr)
@@ -197,6 +231,10 @@ AO_int_fetch_and_add_full(volatile unsigned int *p, unsigned int incr)
}
# define AO_HAVE_short_fetch_and_add_full
+#endif /* _MSC_VER < 1800 && AO_ASM_X64_AVAILABLE */
+
+#ifdef AO_ASM_X64_AVAILABLE
+
/* As far as we can tell, the lfence and sfence instructions are not */
/* currently needed or useful for cached memory accesses. */