summaryrefslogtreecommitdiff
path: root/include/atomic/generic-msvc.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/atomic/generic-msvc.h')
-rw-r--r--include/atomic/generic-msvc.h44
1 files changed, 31 insertions, 13 deletions
diff --git a/include/atomic/generic-msvc.h b/include/atomic/generic-msvc.h
index f1e1b0e88c9..a84cde6b2c3 100644
--- a/include/atomic/generic-msvc.h
+++ b/include/atomic/generic-msvc.h
@@ -23,6 +23,7 @@
*/
#undef MY_ATOMIC_HAS_8_16
+#include <windows.h>
/*
x86 compilers (both VS2003 or VS2005) never use instrinsics, but generate
function calls to kernel32 instead, even in the optimized build.
@@ -36,19 +37,17 @@
#else
C_MODE_START
/*Visual Studio 2003 and earlier do not have prototypes for atomic intrinsics*/
-LONG _InterlockedExchange (LONG volatile *Target,LONG Value);
LONG _InterlockedCompareExchange (LONG volatile *Target, LONG Value, LONG Comp);
-LONG _InterlockedExchangeAdd (LONG volatile *Addend, LONG Value);
+LONGLONG _InterlockedCompareExchange64 (LONGLONG volatile *Target,
+ LONGLONG Value, LONGLONG Comp);
C_MODE_END
-#pragma intrinsic(_InterlockedExchangeAdd)
#pragma intrinsic(_InterlockedCompareExchange)
-#pragma intrinsic(_InterlockedExchange)
+#pragma intrinsic(_InterlockedCompareExchange64)
#endif
-#define InterlockedExchange _InterlockedExchange
-#define InterlockedExchangeAdd _InterlockedExchangeAdd
#define InterlockedCompareExchange _InterlockedCompareExchange
+#define InterlockedCompareExchange64 _InterlockedCompareExchange64
/*
No need to do something special for InterlockedCompareExchangePointer
as it is a #define to InterlockedCompareExchange. The same applies to
@@ -57,23 +56,39 @@ C_MODE_END
#endif /*_M_IX86*/
#define MY_ATOMIC_MODE "msvc-intrinsics"
-#define IL_EXCHG_ADD32(X,Y) InterlockedExchangeAdd((volatile LONG *)(X),(Y))
-#define IL_COMP_EXCHG32(X,Y,Z) InterlockedCompareExchange((volatile LONG *)(X),(Y),(Z))
+/* Implement using CAS on WIN32 */
+#define IL_COMP_EXCHG32(X,Y,Z) \
+ InterlockedCompareExchange((volatile LONG *)(X),(Y),(Z))
+#define IL_COMP_EXCHG64(X,Y,Z) \
+ InterlockedCompareExchange64((volatile LONGLONG *)(X), \
+ (LONGLONG)(Y),(LONGLONG)(Z))
#define IL_COMP_EXCHGptr InterlockedCompareExchangePointer
-#define IL_EXCHG32(X,Y) InterlockedExchange((volatile LONG *)(X),(Y))
-#define IL_EXCHGptr InterlockedExchangePointer
-#define make_atomic_add_body(S) \
- v= IL_EXCHG_ADD ## S (a, v)
+
#define make_atomic_cas_body(S) \
int ## S initial_cmp= *cmp; \
int ## S initial_a= IL_COMP_EXCHG ## S (a, set, initial_cmp); \
if (!(ret= (initial_a == initial_cmp))) *cmp= initial_a;
+
+#ifndef _M_IX86
+/* Use full set of optimised functions on WIN64 */
+#define IL_EXCHG_ADD32(X,Y) \
+ InterlockedExchangeAdd((volatile LONG *)(X),(Y))
+#define IL_EXCHG_ADD64(X,Y) \
+ InterlockedExchangeAdd64((volatile LONGLONG *)(X),(LONGLONG)(Y))
+#define IL_EXCHG32(X,Y) \
+ InterlockedExchange((volatile LONG *)(X),(Y))
+#define IL_EXCHG64(X,Y) \
+ InterlockedExchange64((volatile LONGLONG *)(X),(LONGLONG)(Y))
+#define IL_EXCHGptr InterlockedExchangePointer
+
+#define make_atomic_add_body(S) \
+ v= IL_EXCHG_ADD ## S (a, v)
#define make_atomic_swap_body(S) \
v= IL_EXCHG ## S (a, v)
#define make_atomic_load_body(S) \
ret= 0; /* avoid compiler warning */ \
ret= IL_COMP_EXCHG ## S (a, ret, ret);
-
+#endif
/*
my_yield_processor (equivalent of x86 PAUSE instruction) should be used
to improve performance on hyperthreaded CPUs. Intel recommends to use it in
@@ -108,9 +123,12 @@ static __inline int my_yield_processor()
#else /* cleanup */
#undef IL_EXCHG_ADD32
+#undef IL_EXCHG_ADD64
#undef IL_COMP_EXCHG32
+#undef IL_COMP_EXCHG64
#undef IL_COMP_EXCHGptr
#undef IL_EXCHG32
+#undef IL_EXCHG64
#undef IL_EXCHGptr
#endif