Commit 0cd2e6c6 authored by Marko Mäkelä's avatar Marko Mäkelä

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.
parent f7f0bc74
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. 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 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 the terms of the GNU General Public License as published by the Free Software
......
...@@ -389,7 +389,7 @@ struct trx_lock_t ...@@ -389,7 +389,7 @@ struct trx_lock_t
/** Pre-allocated record locks */ /** Pre-allocated record locks */
struct { struct {
ib_lock_t lock; byte pad[256]; alignas(CPU_LEVEL1_DCACHE_LINESIZE) ib_lock_t lock;
} rec_pool[8]; } rec_pool[8];
/** Pre-allocated table locks */ /** Pre-allocated table locks */
...@@ -583,6 +583,7 @@ struct trx_t : ilist_node<> ...@@ -583,6 +583,7 @@ struct trx_t : ilist_node<>
that it is no longer "active". that it is no longer "active".
*/ */
alignas(CPU_LEVEL1_DCACHE_LINESIZE)
Atomic_counter<int32_t> n_ref; Atomic_counter<int32_t> n_ref;
...@@ -698,7 +699,7 @@ struct trx_t : ilist_node<> ...@@ -698,7 +699,7 @@ struct trx_t : ilist_node<>
/** The locks of the transaction. Protected by lock_sys.latch /** The locks of the transaction. Protected by lock_sys.latch
(insertions also by trx_t::mutex). */ (insertions also by trx_t::mutex). */
trx_lock_t lock; alignas(CPU_LEVEL1_DCACHE_LINESIZE) trx_lock_t lock;
#ifdef WITH_WSREP #ifdef WITH_WSREP
/** whether wsrep_on(mysql_thd) held at the start of transaction */ /** whether wsrep_on(mysql_thd) held at the start of transaction */
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 2013, 2014, Oracle and/or its affiliates. All Rights Reserved. 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 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 the terms of the GNU General Public License as published by the Free Software
...@@ -31,7 +31,7 @@ Created 2012-Feb-26 Sunny Bains ...@@ -31,7 +31,7 @@ Created 2012-Feb-26 Sunny Bains
#include <queue> #include <queue>
#include <functional> #include <functional>
#include "ut0new.h" #include <my_global.h>
/** Allocate the memory for the object in blocks. We keep the objects sorted /** 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 on pointer so that they are closer together in case they have to be iterated
...@@ -41,8 +41,6 @@ struct Pool { ...@@ -41,8 +41,6 @@ struct Pool {
typedef Type value_type; 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 { struct Element {
Pool* m_pool; Pool* m_pool;
value_type m_type; value_type m_type;
...@@ -57,17 +55,30 @@ struct Pool { ...@@ -57,17 +55,30 @@ struct Pool {
m_size(size), m_size(size),
m_last() m_last()
{ {
ut_ad(ut_is_2pow(size));
ut_a(size >= sizeof(Element)); ut_a(size >= sizeof(Element));
static_assert(!(sizeof(Element) % CPU_LEVEL1_DCACHE_LINESIZE),
"alignment");
m_lock_strategy.create(); m_lock_strategy.create();
ut_a(m_start == 0); 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_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 /* Note: Initialise only a small subset, even though we have
allocated all the memory. This is required only because PFS allocated all the memory. This is required only because PFS
...@@ -90,7 +101,7 @@ struct Pool { ...@@ -90,7 +101,7 @@ struct Pool {
Factory::destroy(&elem->m_type); Factory::destroy(&elem->m_type);
} }
ut_free(m_start); IF_WIN(_aligned_free,free)(m_start);
m_end = m_last = m_start = 0; m_end = m_last = m_start = 0;
m_size = 0; m_size = 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment