Skip to content

Commit f17ba2c

Browse files
committed
Bug #79487: Provide non-Windows implementations for LF_BACKOFF
Add LF_BACKOFF implementations for GCC and Sun Studio + some minor code unification with InnoDB.
1 parent d04d7a8 commit f17ba2c

File tree

5 files changed

+65
-53
lines changed

5 files changed

+65
-53
lines changed

include/atomic/generic-msvc.h

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -106,30 +106,4 @@ static inline void my_atomic_storeptr(void * volatile *a, void *v)
106106
(void)InterlockedExchangePointer(a, v);
107107
}
108108

109-
110-
/*
111-
my_yield_processor (equivalent of x86 PAUSE instruction) should be used
112-
to improve performance on hyperthreaded CPUs. Intel recommends to use it in
113-
spin loops also on non-HT machines to reduce power consumption (see e.g
114-
http://softwarecommunity.intel.com/articles/eng/2004.htm)
115-
116-
Running benchmarks for spinlocks implemented with InterlockedCompareExchange
117-
and YieldProcessor shows that much better performance is achieved by calling
118-
YieldProcessor in a loop - that is, yielding longer. On Intel boxes setting
119-
loop count in the range 200-300 brought best results.
120-
*/
121-
#define YIELD_LOOPS 200
122-
123-
static inline int my_yield_processor()
124-
{
125-
int i;
126-
for (i=0; i<YIELD_LOOPS; i++)
127-
{
128-
YieldProcessor();
129-
}
130-
return 1;
131-
}
132-
133-
#define LF_BACKOFF my_yield_processor()
134-
135109
#endif /* ATOMIC_MSC_INCLUDED */

include/lf.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323

2424
C_MODE_START
2525

26+
#define LF_BACKOFF my_yield_processor()
27+
2628
/*
2729
wait-free dynamic array, see lf_dynarray.c
2830

include/my_atomic.h

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,52 @@
6363
#endif
6464

6565
/*
66-
the macro below defines (as an expression) the code that
67-
will be run in spin-loops. Intel manuals recummend to have PAUSE there.
68-
It is expected to be defined in include/atomic/ *.h files
66+
the macro below defines (as an expression) the code that will be run in
67+
spin-loops. Intel manuals recommend to have PAUSE there.
6968
*/
70-
#ifndef LF_BACKOFF
71-
#define LF_BACKOFF (1)
69+
#ifdef HAVE_PAUSE_INSTRUCTION
70+
/* According to the gcc info page, asm volatile means that the instruction
71+
has important side-effects and must not be removed. Also asm volatile may
72+
trigger a memory barrier (spilling all registers to memory). */
73+
# ifdef __SUNPRO_CC
74+
# define MY_PAUSE() asm ("pause" )
75+
# else
76+
# define MY_PAUSE() __asm__ __volatile__ ("pause")
77+
# endif /* __SUNPRO_CC */
78+
79+
# elif defined(HAVE_FAKE_PAUSE_INSTRUCTION)
80+
# define UT_PAUSE() __asm__ __volatile__ ("rep; nop")
81+
# elif defined(_MSC_VER)
82+
/* In the Win32 API, the x86 PAUSE instruction is executed by calling the
83+
YieldProcessor macro defined in WinNT.h. It is a CPU architecture-
84+
independent way by using YieldProcessor. */
85+
# define MY_PAUSE() YieldProcessor()
86+
# else
87+
# define MY_PAUSE() ((void) 0)
7288
#endif
7389

90+
/*
91+
my_yield_processor (equivalent of x86 PAUSE instruction) should be used to
92+
improve performance on hyperthreaded CPUs. Intel recommends to use it in spin
93+
loops also on non-HT machines to reduce power consumption (see e.g
94+
http://softwarecommunity.intel.com/articles/eng/2004.htm)
95+
96+
Running benchmarks for spinlocks implemented with InterlockedCompareExchange
97+
and YieldProcessor shows that much better performance is achieved by calling
98+
YieldProcessor in a loop - that is, yielding longer. On Intel boxes setting
99+
loop count in the range 200-300 brought best results.
100+
*/
101+
#define MY_YIELD_LOOPS 200
102+
103+
static inline int my_yield_processor()
104+
{
105+
int i;
106+
for (i= 0; i < MY_YIELD_LOOPS; i++)
107+
{
108+
MY_COMPILER_BARRIER();
109+
MY_PAUSE();
110+
}
111+
return 1;
112+
}
113+
74114
#endif /* MY_ATOMIC_INCLUDED */

include/my_compiler.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,18 @@ inline bool unlikely(bool expr)
104104
# define MY_ALIGNED(size)
105105
#endif
106106

107+
/*
108+
the macro below defines a compiler barrier, i.e. compiler-specific code to
109+
prevent instructions reordering during compile time.
110+
*/
111+
#if defined __GNUC__ || defined __SUNPRO_C || defined __SUNPRO_CC
112+
# define MY_COMPILER_BARRIER() asm volatile ("" ::: "memory")
113+
#elif defined _MSC_VER
114+
# define MY_COMPILER_BARRIER() _ReadWriteBarrier()
115+
#else
116+
# error No MY_COMPILER_BARRIER() implementation for this compiler!
117+
#endif
118+
107119
/* Visual Studio requires '__inline' for C code */
108120
#if !defined(__cplusplus) && defined(_MSC_VER)
109121
# define inline __inline

storage/innobase/include/ut0ut.h

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -54,29 +54,13 @@ Created 1/20/1994 Heikki Tuuri
5454
typedef time_t ib_time_t;
5555

5656
#ifndef UNIV_HOTBACKUP
57-
# if defined(HAVE_PAUSE_INSTRUCTION)
58-
/* According to the gcc info page, asm volatile means that the
59-
instruction has important side-effects and must not be removed.
60-
Also asm volatile may trigger a memory barrier (spilling all registers
61-
to memory). */
62-
# ifdef __SUNPRO_CC
63-
# define UT_RELAX_CPU() asm ("pause" )
64-
# else
65-
# define UT_RELAX_CPU() __asm__ __volatile__ ("pause")
66-
# endif /* __SUNPRO_CC */
67-
68-
# elif defined(HAVE_FAKE_PAUSE_INSTRUCTION)
69-
# define UT_RELAX_CPU() __asm__ __volatile__ ("rep; nop")
70-
# elif defined _WIN32
71-
/* In the Win32 API, the x86 PAUSE instruction is executed by calling
72-
the YieldProcessor macro defined in WinNT.h. It is a CPU architecture-
73-
independent way by using YieldProcessor. */
74-
# define UT_RELAX_CPU() YieldProcessor()
57+
58+
#include <my_atomic.h>
59+
60+
# ifdef MY_PAUSE
61+
# define UT_RELAX_CPU() MY_PAUSE()
7562
# else
76-
# define UT_RELAX_CPU() do { \
77-
volatile lint volatile_var; \
78-
os_compare_and_swap_lint(&volatile_var, 0, 1); \
79-
} while (0)
63+
# error MY_PAUSE() is undefined
8064
# endif
8165

8266
# if defined(HAVE_HMT_PRIORITY_INSTRUCTION)

0 commit comments

Comments
 (0)