20
20
We don't implement anything specific for MY_ATOMIC_MODE_DUMMY, always use
22
8 and 16-bit atomics are not implemented, but it can be done if necessary.
26
x86 compilers (both VS2003 or VS2005) never use instrinsics, but generate
27
function calls to kernel32 instead, even in the optimized build.
28
We force intrinsics as described in MSDN documentation for
29
_InterlockedCompareExchange.
33
#if (_MSC_VER >= 1400)
37
/*Visual Studio 2003 and earlier do not have prototypes for atomic intrinsics*/
38
LONG _InterlockedExchange (LONG volatile *Target,LONG Value);
39
LONG _InterlockedCompareExchange (LONG volatile *Target, LONG Value, LONG Comp);
40
LONG _InterlockedExchangeAdd (LONG volatile *Addend, LONG Value);
43
#pragma intrinsic(_InterlockedExchangeAdd)
44
#pragma intrinsic(_InterlockedCompareExchange)
45
#pragma intrinsic(_InterlockedExchange)
48
#define InterlockedExchange _InterlockedExchange
49
#define InterlockedExchangeAdd _InterlockedExchangeAdd
50
#define InterlockedCompareExchange _InterlockedCompareExchange
52
No need to do something special for InterlockedCompareExchangePointer
53
as it is a #define to InterlockedCompareExchange. The same applies to
54
InterlockedExchangePointer.
23
58
#define MY_ATOMIC_MODE "msvc-intrinsics"
24
#define IL_EXCHG_ADD32 InterlockedExchangeAdd
25
#define IL_COMP_EXCHG32 InterlockedCompareExchange
26
#define IL_COMP_EXCHGptr InterlockedCompareExchangePointer
27
#define IL_EXCHG32 InterlockedExchange
28
#define IL_EXCHGptr InterlockedExchangePointer
59
#define IL_EXCHG_ADD32(A,B) InterlockedExchangeAdd((LONG volatile*)A,B)
60
#define IL_COMP_EXCHG32(A,B,C) InterlockedCompareExchange((LONG volatile*)A,B,C)
61
#define IL_COMP_EXCHGptr InterlockedCompareExchangePointer
62
#define IL_EXCHG32(A,B) InterlockedExchange((LONG volatile*)A,B)
63
#define IL_EXCHGptr InterlockedExchangePointer
29
64
#define make_atomic_add_body(S) \
30
65
v= IL_EXCHG_ADD ## S (a, v)
31
66
#define make_atomic_cas_body(S) \
38
73
ret= 0; /* avoid compiler warning */ \
39
74
ret= IL_COMP_EXCHG ## S (a, ret, ret);
77
my_yield_processor (equivalent of x86 PAUSE instruction) should be used
78
to improve performance on hyperthreaded CPUs. Intel recommends to use it in
79
spin loops also on non-HT machines to reduce power consumption (see e.g
80
http://softwarecommunity.intel.com/articles/eng/2004.htm)
82
Running benchmarks for spinlocks implemented with InterlockedCompareExchange
83
and YieldProcessor shows that much better performance is achieved by calling
84
YieldProcessor in a loop - that is, yielding longer. On Intel boxes setting
85
loop count in the range 200-300 brought best results.
88
#define YIELD_LOOPS 200
91
static __inline int my_yield_processor()
94
for(i=0; i<YIELD_LOOPS; i++)
96
#if (_MSC_VER <= 1310)
97
/* On older compilers YieldProcessor is not available, use inline assembly*/
106
#define LF_BACKOFF my_yield_processor()
41
107
#else /* cleanup */
43
109
#undef IL_EXCHG_ADD32