From d4ba50477e6f0092a3b83528c02c0f30a2b708a3 Mon Sep 17 00:00:00 2001 From: Yasufumi Kinoshita Date: Wed, 30 Mar 2016 14:32:20 +1100 Subject: [PATCH] Some POWER specific optimizations Bug#18842925 : SET THREAD PRIORITY IN INNODB MUTEX SPINLOOP Like "pause" instruction for hyper-threading at Intel CPUs, POWER has special instructions only for hinting priority of hardware-threads. Approved by Sunny in rb#6256 Backport of the 5.7 fix - https://github.com/mysql/mysql-server/commit/c92102a6ef0f280bfb56e5585fca0d0cdcc34890 (excluded cache line size patch) Suggestion by Stewart Smith --- config.h.cmake | 1 + configure.cmake | 10 ++++++++++ storage/innobase/include/ut0ut.h | 8 ++++++++ storage/innobase/ut/ut0ut.cc | 4 ++++ storage/xtradb/include/ut0ut.h | 8 ++++++++ storage/xtradb/ut/ut0ut.cc | 4 ++++ 6 files changed, 35 insertions(+) diff --git a/config.h.cmake b/config.h.cmake index ce6f14723b887..493f90edc8cff 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -225,6 +225,7 @@ #cmakedefine HAVE_PREAD 1 #cmakedefine HAVE_PAUSE_INSTRUCTION 1 #cmakedefine HAVE_FAKE_PAUSE_INSTRUCTION 1 +#cmakedefine HAVE_HMT_PRIORITY_INSTRUCTION 1 #cmakedefine HAVE_RDTSCLL 1 #cmakedefine HAVE_READ_REAL_TIME 1 #cmakedefine HAVE_PTHREAD_ATTR_CREATE 1 diff --git a/configure.cmake b/configure.cmake index a1fdb98389d67..acb80965a6425 100644 --- a/configure.cmake +++ b/configure.cmake @@ -855,6 +855,16 @@ IF(NOT CMAKE_CROSSCOMPILING AND NOT MSVC) } " HAVE_FAKE_PAUSE_INSTRUCTION) ENDIF() + IF (NOT HAVE_PAUSE_INSTRUCTION) + CHECK_C_SOURCE_COMPILES(" + int main() + { + __asm__ __volatile__ (\"or 1,1,1\"); + __asm__ __volatile__ (\"or 2,2,2\"); + return 0; + } + " HAVE_HMT_PRIORITY_INSTRUCTION) + ENDIF() ENDIF() CHECK_SYMBOL_EXISTS(tcgetattr "termios.h" HAVE_TCGETATTR 1) diff --git a/storage/innobase/include/ut0ut.h b/storage/innobase/include/ut0ut.h index 338cdf115d75a..03e4b5df8337f 100644 --- a/storage/innobase/include/ut0ut.h +++ b/storage/innobase/include/ut0ut.h @@ -92,6 +92,14 @@ struct ut_when_dtor { # define UT_RELAX_CPU() __asm__ __volatile__ ("":::"memory") # endif +# if defined(HAVE_HMT_PRIORITY_INSTRUCTION) +# define UT_LOW_PRIORITY_CPU() __asm__ __volatile__ ("or 1,1,1") +# define UT_RESUME_PRIORITY_CPU() __asm__ __volatile__ ("or 2,2,2") +# else +# define UT_LOW_PRIORITY_CPU() ((void)0) +# define UT_RESUME_PRIORITY_CPU() ((void)0) +# endif + /*********************************************************************//** Delays execution for at most max_wait_us microseconds or returns earlier if cond becomes true. diff --git a/storage/innobase/ut/ut0ut.cc b/storage/innobase/ut/ut0ut.cc index a0fc154ce6b94..85e77b6cced6b 100644 --- a/storage/innobase/ut/ut0ut.cc +++ b/storage/innobase/ut/ut0ut.cc @@ -401,6 +401,8 @@ ut_delay( { ulint i, j; + UT_LOW_PRIORITY_CPU(); + j = 0; for (i = 0; i < delay * 50; i++) { @@ -408,6 +410,8 @@ ut_delay( UT_RELAX_CPU(); } + UT_RESUME_PRIORITY_CPU(); + return(j); } #endif /* !UNIV_HOTBACKUP */ diff --git a/storage/xtradb/include/ut0ut.h b/storage/xtradb/include/ut0ut.h index fbebbc68628f4..6ea23514994cd 100644 --- a/storage/xtradb/include/ut0ut.h +++ b/storage/xtradb/include/ut0ut.h @@ -89,6 +89,14 @@ struct ut_when_dtor { # define UT_RELAX_CPU() __asm__ __volatile__ ("":::"memory") # endif +# if defined(HAVE_HMT_PRIORITY_INSTRUCTION) +# define UT_LOW_PRIORITY_CPU() __asm__ __volatile__ ("or 1,1,1") +# define UT_RESUME_PRIORITY_CPU() __asm__ __volatile__ ("or 2,2,2") +# else +# define UT_LOW_PRIORITY_CPU() ((void)0) +# define UT_RESUME_PRIORITY_CPU() ((void)0) +# endif + /*********************************************************************//** Delays execution for at most max_wait_us microseconds or returns earlier if cond becomes true. diff --git a/storage/xtradb/ut/ut0ut.cc b/storage/xtradb/ut/ut0ut.cc index 5e85594ef440a..42fc04e5f8169 100644 --- a/storage/xtradb/ut/ut0ut.cc +++ b/storage/xtradb/ut/ut0ut.cc @@ -402,6 +402,8 @@ ut_delay( { ulint i, j; + UT_LOW_PRIORITY_CPU(); + j = 0; for (i = 0; i < delay * 50; i++) { @@ -409,6 +411,8 @@ ut_delay( UT_RELAX_CPU(); } + UT_RESUME_PRIORITY_CPU(); + return(j); } #endif /* !UNIV_HOTBACKUP */