From 3cc6202a7b583fedfd82b405b840d426e21d0cba Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Fri, 25 May 2018 14:44:04 +0300 Subject: [PATCH] Bug #79487: Provide non-Windows implementations for LF_BACKOFF Add LF_BACKOFF implementations for GCC and Sun Studio. --- include/lf.h | 2 ++ include/my_atomic.h | 69 ++++++++++++++++++++++++++++++++++++++++----------- include/my_compiler.h | 12 +++++++++ 3 files changed, 68 insertions(+), 15 deletions(-) diff --git a/include/lf.h b/include/lf.h index 96368ef83b8..1f214f8a6c4 100644 --- a/include/lf.h +++ b/include/lf.h @@ -40,6 +40,8 @@ #include "mysql/service_mysql_alloc.h" #include "sql_string.h" +#define LF_BACKOFF my_yield_processor() + /* wait-free dynamic array, see lf_dynarray.c diff --git a/include/my_atomic.h b/include/my_atomic.h index ce8927816f6..e0a41b59977 100644 --- a/include/my_atomic.h +++ b/include/my_atomic.h @@ -28,13 +28,51 @@ */ #if defined(_MSC_VER) - #include +#endif + +#include "my_compiler.h" + +/* + the macro below defines (as an expression) the code that + will be run in spin-loops. Intel manuals recummend to have PAUSE there. +*/ +#ifdef HAVE_PAUSE_INSTRUCTION + /* + According to the gcc info page, asm volatile means that the instruction + has important side-effects and must not be removed. Also asm volatile may + trigger a memory barrier (spilling all registers to memory). + */ +# define MY_PAUSE() __asm__ __volatile__ ("pause") +# elif defined(HAVE_FAKE_PAUSE_INSTRUCTION) +# define MY_PAUSE() __asm__ __volatile__ ("rep; nop") +# elif defined(_MSC_VER) + /* + In the Win32 API, the x86 PAUSE instruction is executed by calling the + YieldProcessor macro defined in WinNT.h. It is a CPU architecture- + independent way by using YieldProcessor. + */ +# define MY_PAUSE() YieldProcessor() +# else +# define MY_PAUSE() ((void) 0) +#endif + +/* + POWER-specific macros to relax CPU threads to give more core resources to + other threads executing in the core. +*/ +#if defined(HAVE_HMT_PRIORITY_INSTRUCTION) +# define MY_LOW_PRIORITY_CPU() __asm__ __volatile__ ("or 1,1,1") +# define MY_RESUME_PRIORITY_CPU() __asm__ __volatile__ ("or 2,2,2") +#else +# define MY_LOW_PRIORITY_CPU() ((void)0) +# define MY_RESUME_PRIORITY_CPU() ((void)0) +#endif /* - my_yield_processor (equivalent of x86 PAUSE instruction) should be used - to improve performance on hyperthreaded CPUs. Intel recommends to use it in - spin loops also on non-HT machines to reduce power consumption (see e.g + my_yield_processor (equivalent of x86 PAUSE instruction) should be used to + improve performance on hyperthreaded CPUs. Intel recommends to use it in spin + loops also on non-HT machines to reduce power consumption (see e.g http://softwarecommunity.intel.com/articles/eng/2004.htm) Running benchmarks for spinlocks implemented with InterlockedCompareExchange @@ -42,22 +80,23 @@ YieldProcessor in a loop - that is, yielding longer. On Intel boxes setting loop count in the range 200-300 brought best results. */ -#define YIELD_LOOPS 200 +#define MY_YIELD_LOOPS 200 -static inline int my_yield_processor() { +static inline int my_yield_processor() +{ int i; - for (i = 0; i < YIELD_LOOPS; i++) { - YieldProcessor(); - } - return 1; -} -#define LF_BACKOFF my_yield_processor() + MY_LOW_PRIORITY_CPU(); -#else // !defined(_MSC_VER) + for (i= 0; i < MY_YIELD_LOOPS; i++) + { + MY_COMPILER_BARRIER(); + MY_PAUSE(); + } -#define LF_BACKOFF (1) + MY_RESUME_PRIORITY_CPU(); -#endif + return 1; +} #endif /* MY_ATOMIC_INCLUDED */ diff --git a/include/my_compiler.h b/include/my_compiler.h index 8527e0c6733..fc38652674c 100644 --- a/include/my_compiler.h +++ b/include/my_compiler.h @@ -94,6 +94,18 @@ inline bool unlikely(bool expr) { return expr; } #define MY_ALIGNED(size) #endif +/* + the macro below defines a compiler barrier, i.e. compiler-specific code to + prevent instructions reordering during compile time. +*/ +#if defined __GNUC__ || defined __SUNPRO_C || defined __SUNPRO_CC +# define MY_COMPILER_BARRIER() __asm__ __volatile__ ("" ::: "memory") +#elif defined _MSC_VER +# define MY_COMPILER_BARRIER() _ReadWriteBarrier() +#else +# error No MY_COMPILER_BARRIER() implementation for this compiler! +#endif + /* Visual Studio requires '__inline' for C code */ #if !defined(__cplusplus) && defined(_MSC_VER) #define inline __inline