summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2022-04-14 10:06:34 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2022-04-14 10:06:34 +0300
commit0cd2e6c61478baf91235a66f0357974a26f02ece (patch)
tree63ded4347125b95e9478f4e90c01d976777e95ea
parentf7f0bc748e88f911b957d3dbf3bc0828a33675fb (diff)
downloadmariadb-git-0cd2e6c61478baf91235a66f0357974a26f02ece.tar.gz
MDEV-28313: InnoDB transactions are not aligned at cache lines
trx_lock_t: Remove byte pad[256] and use alignas(CPU_LEVEL1_DCACHE_LINESIZE) instead. trx_t: Declare n_ref (the first member) aligned at cache line. Pool: Assert that the sizes are multiples of CPU_LEVEL1_DCACHE_LINESIZE, and invoke an aligned allocator.
-rw-r--r--storage/innobase/include/trx0sys.h2
-rw-r--r--storage/innobase/include/trx0trx.h15
-rw-r--r--storage/innobase/include/ut0pool.h25
3 files changed, 27 insertions, 15 deletions
diff --git a/storage/innobase/include/trx0sys.h b/storage/innobase/include/trx0sys.h
index cbac3fd3a94..aa3cdd6a24b 100644
--- a/storage/innobase/include/trx0sys.h
+++ b/storage/innobase/include/trx0sys.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, 2021, MariaDB Corporation.
+Copyright (c) 2017, 2022, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h
index 6b9ffdc6374..2fd04353a2b 100644
--- a/storage/innobase/include/trx0trx.h
+++ b/storage/innobase/include/trx0trx.h
@@ -387,13 +387,13 @@ struct trx_lock_t
only be modified by the thread that is
serving the running transaction. */
- /** Pre-allocated record locks */
- struct {
- ib_lock_t lock; byte pad[256];
- } rec_pool[8];
+ /** Pre-allocated record locks */
+ struct {
+ alignas(CPU_LEVEL1_DCACHE_LINESIZE) ib_lock_t lock;
+ } rec_pool[8];
- /** Pre-allocated table locks */
- ib_lock_t table_pool[8];
+ /** Pre-allocated table locks */
+ ib_lock_t table_pool[8];
/** Memory heap for trx_locks. Protected by lock_sys.assert_locked()
and lock_sys.is_writer() || trx->mutex_is_owner(). */
@@ -583,6 +583,7 @@ private:
that it is no longer "active".
*/
+ alignas(CPU_LEVEL1_DCACHE_LINESIZE)
Atomic_counter<int32_t> n_ref;
@@ -698,7 +699,7 @@ public:
/** The locks of the transaction. Protected by lock_sys.latch
(insertions also by trx_t::mutex). */
- trx_lock_t lock;
+ alignas(CPU_LEVEL1_DCACHE_LINESIZE) trx_lock_t lock;
#ifdef WITH_WSREP
/** whether wsrep_on(mysql_thd) held at the start of transaction */
diff --git a/storage/innobase/include/ut0pool.h b/storage/innobase/include/ut0pool.h
index 41b02e0a985..ccea69fe549 100644
--- a/storage/innobase/include/ut0pool.h
+++ b/storage/innobase/include/ut0pool.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2013, 2014, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2018, 2020, MariaDB Corporation.
+Copyright (c) 2018, 2022, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -31,7 +31,7 @@ Created 2012-Feb-26 Sunny Bains
#include <queue>
#include <functional>
-#include "ut0new.h"
+#include <my_global.h>
/** Allocate the memory for the object in blocks. We keep the objects sorted
on pointer so that they are closer together in case they have to be iterated
@@ -41,8 +41,6 @@ struct Pool {
typedef Type value_type;
- // FIXME: Add an assertion to check alignment and offset is
- // as we expect it. Also, sizeof(void*) can be 8, can we impove on this.
struct Element {
Pool* m_pool;
value_type m_type;
@@ -57,17 +55,30 @@ struct Pool {
m_size(size),
m_last()
{
+ ut_ad(ut_is_2pow(size));
ut_a(size >= sizeof(Element));
+ static_assert(!(sizeof(Element) % CPU_LEVEL1_DCACHE_LINESIZE),
+ "alignment");
m_lock_strategy.create();
ut_a(m_start == 0);
- m_start = reinterpret_cast<Element*>(ut_zalloc_nokey(m_size));
+#ifdef _MSC_VER
+ m_start = static_cast<Element*>(
+ _aligned_malloc(m_size, CPU_LEVEL1_DCACHE_LINESIZE));
+#else
+ void* start;
+ ut_a(!posix_memalign(&start, CPU_LEVEL1_DCACHE_LINESIZE,
+ m_size));
+ m_start = static_cast<Element*>(start);
+#endif
+ memset_aligned<CPU_LEVEL1_DCACHE_LINESIZE>(
+ m_start, 0, m_size);
m_last = m_start;
- m_end = &m_start[m_size / sizeof(*m_start)];
+ m_end = &m_start[m_size / sizeof *m_start];
/* Note: Initialise only a small subset, even though we have
allocated all the memory. This is required only because PFS
@@ -90,7 +101,7 @@ struct Pool {
Factory::destroy(&elem->m_type);
}
- ut_free(m_start);
+ IF_WIN(_aligned_free,free)(m_start);
m_end = m_last = m_start = 0;
m_size = 0;
}