From 691080d4ab50bb9400267b62cf1cf37ecf959cc5 Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Tue, 15 Dec 2015 22:18:29 +0300 Subject: [PATCH] Few improvements related to CPU cache line size and padding: Bug #79636: CACHE_LINE_SIZE should be 128 on AArch64 Bug #79637: Hard-coded cache line size Bug #79638: Reconcile CACHE_LINE_SIZE with CPU_LEVEL1_DCACHE_LINESIZE - changed CPU_LEVEL1_DCACHE_LINESIZE to default to 128 bytes on POWER and AArch64 architectures in cases when no value could be detected by CMake using getconf - changed pfs_global.h to assume CPU_LEVEL1_DCACHE_LINESIZE is always defined (and throw a compile-time error if it's not) - changed CACHE_LINE_SIZE definition in ut0counter.h to be an alias of CPU_LEVEL1_DCACHE_LINESIZE - changed a number of hard-coded 64-byte cache line size values in the InnoDB code - fixed insufficient padding for srv_conc members in srv0conc.cc --- cmake/cpu_info.cmake | 4 ---- include/my_global.h | 13 +++++++++++++ storage/innobase/btr/btr0sea.cc | 4 ++-- storage/innobase/include/read0types.h | 2 +- storage/innobase/include/trx0sys.h | 9 ++++++--- storage/innobase/include/ut0counter.h | 12 ++++++++---- storage/innobase/srv/srv0conc.cc | 4 +++- storage/perfschema/pfs_global.h | 2 +- 8 files changed, 34 insertions(+), 16 deletions(-) diff --git a/cmake/cpu_info.cmake b/cmake/cpu_info.cmake index 9d5f321..96eeb77 100644 --- a/cmake/cpu_info.cmake +++ b/cmake/cpu_info.cmake @@ -24,7 +24,3 @@ IF(GETCONF) OUTPUT_VARIABLE CPU_LEVEL1_DCACHE_LINESIZE ) ENDIF() -IF(CPU_LEVEL1_DCACHE_LINESIZE AND CPU_LEVEL1_DCACHE_LINESIZE GREATER 0) -ELSE() - SET(CPU_LEVEL1_DCACHE_LINESIZE 64) -ENDIF() diff --git a/include/my_global.h b/include/my_global.h index 2d50b36..1c0e69e 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -778,4 +778,17 @@ typedef mode_t MY_MODE; #if defined(_WIN32) || defined(_WIN64) #define strcasecmp _stricmp #endif + +/* + Provide defaults for the CPU cache line size, if it has not been detected by + CMake using getconf +*/ +#if !defined(CPU_LEVEL1_DCACHE_LINESIZE) || CPU_LEVEL1_DCACHE_LINESIZE == 0 + #if defined(__powerpc__) || defined(__aarch64__) + #define CPU_LEVEL1_DCACHE_LINESIZE 128 + #else + #define CPU_LEVEL1_DCACHE_LINESIZE 64 + #endif +#endif + #endif // MY_GLOBAL_INCLUDED diff --git a/storage/innobase/btr/btr0sea.cc b/storage/innobase/btr/btr0sea.cc index ce8cef6..81c27a7 100644 --- a/storage/innobase/btr/btr0sea.cc +++ b/storage/innobase/btr/btr0sea.cc @@ -62,7 +62,7 @@ ulint btr_search_n_hash_fail = 0; /** padding to prevent other memory update hotspots from residing on the same memory cache line as btr_search_latches */ -byte btr_sea_pad1[64]; +byte btr_sea_pad1[CACHE_LINE_SIZE]; /** The latches protecting the adaptive search system: this latches protects the (1) positions of records on those pages where a hash index has been built. @@ -74,7 +74,7 @@ rw_lock_t** btr_search_latches; /** padding to prevent other memory update hotspots from residing on the same memory cache line */ -byte btr_sea_pad2[64]; +byte btr_sea_pad2[CACHE_LINE_SIZE]; /** The adaptive hash index */ btr_search_sys_t* btr_search_sys; diff --git a/storage/innobase/include/read0types.h b/storage/innobase/include/read0types.h index 230aac4..5802d24 100644 --- a/storage/innobase/include/read0types.h +++ b/storage/innobase/include/read0types.h @@ -324,7 +324,7 @@ class ReadView { typedef UT_LIST_NODE_T(ReadView) node_t; /** List of read views in trx_sys */ - byte pad1[64 - sizeof(node_t)]; + byte pad1[CACHE_LINE_SIZE - sizeof(node_t)]; node_t m_view_list; }; diff --git a/storage/innobase/include/trx0sys.h b/storage/innobase/include/trx0sys.h index f1d81e1..b65bf7d 100644 --- a/storage/innobase/include/trx0sys.h +++ b/storage/innobase/include/trx0sys.h @@ -579,13 +579,15 @@ struct trx_sys_t { transactions which exist or existed */ #endif /* UNIV_DEBUG */ - char pad1[64]; /*!< To avoid false sharing */ + char pad1[CACHE_LINE_SIZE]; + /*!< To avoid false sharing */ trx_ut_list_t rw_trx_list; /*!< List of active and committed in memory read-write transactions, sorted on trx id, biggest first. Recovered transactions are always on this list. */ - char pad2[64]; /*!< To avoid false sharing */ + char pad2[CACHE_LINE_SIZE]; + /*!< To avoid false sharing */ trx_ut_list_t mysql_trx_list; /*!< List of transactions created for MySQL. All user transactions are on mysql_trx_list. The rw_trx_list @@ -605,7 +607,8 @@ struct trx_sys_t { to ensure right order of removal and consistent snapshot. */ - char pad3[64]; /*!< To avoid false sharing */ + char pad3[CACHE_LINE_SIZE]; + /*!< To avoid false sharing */ trx_rseg_t* rseg_array[TRX_SYS_N_RSEGS]; /*!< Pointer array to rollback segments; NULL if slot not in use; diff --git a/storage/innobase/include/ut0counter.h b/storage/innobase/include/ut0counter.h index 6b187ec..87acca6 100644 --- a/storage/innobase/include/ut0counter.h +++ b/storage/innobase/include/ut0counter.h @@ -32,11 +32,15 @@ Created 2012/04/12 by Sunny Bains #include "os0thread.h" /** CPU cache line size */ -#ifdef __powerpc__ -#define CACHE_LINE_SIZE 128 +#ifndef UNIV_HOTBACKUP +# ifdef CPU_LEVEL1_DCACHE_LINESIZE +# define CACHE_LINE_SIZE CPU_LEVEL1_DCACHE_LINESIZE +# else +# error CPU_LEVEL1_DCACHE_LINESIZE is undefined +# endif /* CPU_LEVEL1_DCACHE_LINESIZE */ #else -#define CACHE_LINE_SIZE 64 -#endif /* __powerpc__ */ +# define CACHE_LINE_SIZE 64 +#endif /* UNIV_HOTBACKUP */ /** Default number of slots to use in ib_counter_t */ #define IB_N_SLOTS 64 diff --git a/storage/innobase/srv/srv0conc.cc b/storage/innobase/srv/srv0conc.cc index ae06869..a6523be 100644 --- a/storage/innobase/srv/srv0conc.cc +++ b/storage/innobase/srv/srv0conc.cc @@ -69,7 +69,7 @@ ulong srv_thread_concurrency = 0; /** Variables tracking the active and waiting threads. */ struct srv_conc_t { - char pad[64 - (sizeof(ulint) + sizeof(lint))]; + char pad1[CACHE_LINE_SIZE - sizeof(ulint)]; /** Number of transactions that have declared_to_be_inside_innodb set. It used to be a non-error for this value to drop below zero temporarily. @@ -78,6 +78,8 @@ struct srv_conc_t { volatile lint n_active; + char pad2[CACHE_LINE_SIZE - sizeof(lint)]; + /** Number of OS threads waiting in the FIFO for permission to enter InnoDB */ volatile lint n_waiting; diff --git a/storage/perfschema/pfs_global.h b/storage/perfschema/pfs_global.h index 31a385c..6339922 100644 --- a/storage/perfschema/pfs_global.h +++ b/storage/perfschema/pfs_global.h @@ -42,7 +42,7 @@ extern bool pfs_initialized; #ifdef CPU_LEVEL1_DCACHE_LINESIZE #define PFS_CACHE_LINE_SIZE CPU_LEVEL1_DCACHE_LINESIZE #else -#define PFS_CACHE_LINE_SIZE 128 +#error CPU_LEVEL1_DCACHE_LINESIZE is undefined #endif /**