MySQL 8.4.2
Source Code Documentation
sync0sharded_rw.h
Go to the documentation of this file.
1/*****************************************************************************
2
3Copyright (c) 2017, 2024, Oracle and/or its affiliates.
4
5This program is free software; you can redistribute it and/or modify
6it under the terms of the GNU General Public License, version 2.0,
7as published by the Free Software Foundation.
8
9This program is designed to work with certain software (including
10but not limited to OpenSSL) that is licensed under separate terms,
11as designated in a particular file or component or in included license
12documentation. The authors of MySQL hereby grant you an additional
13permission to link the program and your derivative works with the
14separately licensed software that they have either included with
15the program or referenced in the documentation.
16
17This program is distributed in the hope that it will be useful,
18but WITHOUT ANY WARRANTY; without even the implied warranty of
19MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20GNU General Public License, version 2.0, for more details.
21
22You should have received a copy of the GNU General Public License
23along with this program; if not, write to the Free Software
24Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25
26Portions of this file contain modifications contributed and copyrighted by
27Google, Inc. Those modifications are gratefully acknowledged and are described
28briefly in the InnoDB documentation. The contributions by Google are
29incorporated with their permission, and subject to the conditions contained in
30the file COPYING.Google.
31
32*****************************************************************************/
33
34/**************************************************/ /**
35 @file include/sync0sharded_rw.h
36
37 The sharded read-write lock (for threads).
38
39 The s-lock scales better than in single rw-lock,
40 but the x-lock is much slower.
41
42 *******************************************************/
43
44#ifndef sync0sharded_rw_h
45#define sync0sharded_rw_h
46
47#include "sync0rw.h"
48#include "ut0cpu_cache.h"
49#include "ut0rnd.h"
50#include "ut0ut.h"
51
52#ifndef UNIV_HOTBACKUP
53#ifndef UNIV_LIBRARY
54
55/** Rw-lock with very fast, highly concurrent s-lock but slower x-lock.
56It's basically array of rw-locks. When s-lock is being acquired, single
57rw-lock from array is selected randomly and s-locked. Therefore, all
58rw-locks from array has to be x-locked when x-lock is being acquired.
59
60Purpose of this data structure is to reduce contention on single atomic
61in single rw-lock when a lot of threads need to acquire s-lock very often,
62but x-lock is very rare. */
64 public:
65 void create(
66#ifdef UNIV_PFS_RWLOCK
67 mysql_pfs_key_t pfs_key,
68#endif
69 latch_id_t latch_id, size_t n_shards) {
70 ut_ad(ut_is_2pow(n_shards));
71 m_n_shards = n_shards;
72
73 m_shards = static_cast<Shard *>(
75
76 for_each([
77#ifdef UNIV_PFS_RWLOCK
78 pfs_key,
79#endif
80 latch_id](rw_lock_t &lock) {
81 static_cast<void>(latch_id); // clang -Wunused-lambda-capture
82 rw_lock_create(pfs_key, &lock, latch_id);
83 });
84 }
85
86 void free() {
87 ut_a(m_shards != nullptr);
88
90
92 m_shards = nullptr;
93 m_n_shards = 0;
94 }
95
96 size_t s_lock(ut::Location location) {
97 const size_t shard_no =
98 default_indexer_t<>::get_rnd_index() & (m_n_shards - 1);
99 rw_lock_s_lock_gen(&m_shards[shard_no], 0, location);
100 return shard_no;
101 }
102
103 void s_unlock(size_t shard_no) {
104 ut_a(shard_no < m_n_shards);
105 rw_lock_s_unlock(&m_shards[shard_no]);
106 }
107 /** Checks if there is a thread requesting an x-latch waiting for threads to
108 release their s-latches on given shard.
109 @param[in] shard_no The shard to check.
110 @return true iff there is an x-latcher blocked by s-latchers on shard_no. */
111 bool is_x_blocked_by_s(size_t shard_no) {
112 ut_a(shard_no < m_n_shards);
113 return m_shards[shard_no].is_x_blocked_by_s();
114 }
115 /**
116 Tries to obtain exclusive latch - similar to x_lock(), but non-blocking, and
117 thus can fail.
118 @return true iff succeeded to acquire the exclusive latch
119 */
120 bool try_x_lock(ut::Location location) {
121 for (size_t shard_no = 0; shard_no < m_n_shards; ++shard_no) {
122 if (!rw_lock_x_lock_nowait(&m_shards[shard_no], location)) {
123 while (0 < shard_no--) {
124 rw_lock_x_unlock(&m_shards[shard_no]);
125 }
126 return (false);
127 }
128 }
129 return (true);
130 }
131
132 void x_lock(ut::Location location) {
133 for_each([location](rw_lock_t &lock) {
134 rw_lock_x_lock_gen(&lock, 0, location);
135 });
136 }
137
138 void x_unlock() {
140 }
141
142#ifdef UNIV_DEBUG
143 bool s_own(size_t shard_no) const {
144 return rw_lock_own(&m_shards[shard_no], RW_LOCK_S);
145 }
146
147 bool x_own() const { return rw_lock_own(&m_shards[0], RW_LOCK_X); }
148#endif /* !UNIV_DEBUG */
149
150 private:
152
153 template <typename F>
154 void for_each(F f) {
156 }
157
158 Shard *m_shards = nullptr;
159
160 size_t m_n_shards = 0;
161};
162
163#else /* !UNIV_LIBRARY */
164
165/* For UNIV_LIBRARY, rw_lock is no-op, so sharded rw-lock is also no-op. */
166
167class Sharded_rw_lock {
168 public:
169 void create(
170#ifdef UNIV_PFS_RWLOCK
171 mysql_pfs_key_t pfs_key,
172#endif
173 latch_id_t latch_id, size_t n_shards) {
174 }
175
176 void free() {}
177
178 size_t s_lock() { return 0; }
179
180 void s_unlock(size_t shard_no) { ut_a(shard_no == 0); }
181
182 void x_lock() {}
183
184 void x_unlock() {}
185};
186
187#endif /* UNIV_LIBRARY */
188#endif /* UNIV_HOTBACKUP */
189
190#endif /* sync0sharded_rw.h */
Rw-lock with very fast, highly concurrent s-lock but slower x-lock.
Definition: sync0sharded_rw.h:63
bool s_own(size_t shard_no) const
Definition: sync0sharded_rw.h:143
void x_unlock()
Definition: sync0sharded_rw.h:138
size_t s_lock(ut::Location location)
Definition: sync0sharded_rw.h:96
void s_unlock(size_t shard_no)
Definition: sync0sharded_rw.h:103
bool x_own() const
Definition: sync0sharded_rw.h:147
bool try_x_lock(ut::Location location)
Tries to obtain exclusive latch - similar to x_lock(), but non-blocking, and thus can fail.
Definition: sync0sharded_rw.h:120
bool is_x_blocked_by_s(size_t shard_no)
Checks if there is a thread requesting an x-latch waiting for threads to release their s-latches on g...
Definition: sync0sharded_rw.h:111
void for_each(F f)
Definition: sync0sharded_rw.h:154
void free()
Definition: sync0sharded_rw.h:86
void create(mysql_pfs_key_t pfs_key, latch_id_t latch_id, size_t n_shards)
Definition: sync0sharded_rw.h:65
Shard * m_shards
Definition: sync0sharded_rw.h:158
size_t m_n_shards
Definition: sync0sharded_rw.h:160
void x_lock(ut::Location location)
Definition: sync0sharded_rw.h:132
void for_each(const Shards< COUNT > &shards, Function &&f) noexcept
Iterate over the shards.
Definition: ut0counter.h:323
Provides atomic access in shared-exclusive modes.
Definition: shared_spin_lock.h:79
void * zalloc_withkey(PSI_memory_key_t key, std::size_t size) noexcept
Dynamically allocates zero-initialized storage of given size.
Definition: ut0new.h:632
void free(void *ptr) noexcept
Releases storage which has been dynamically allocated through any of the ut::malloc*(),...
Definition: ut0new.h:717
Define for performance schema registration key.
Definition: sync0sync.h:51
The structure used in the spin lock implementation of a read-write lock.
Definition: sync0rw.h:363
A utility wrapper class, which adds padding at the end of the wrapped structure, so that the next obj...
Definition: ut0cpu_cache.h:55
Definition: ut0core.h:36
The read-write lock (for threads, not for database transactions)
bool rw_lock_own(const rw_lock_t *lock, ulint lock_type)
Checks if the thread has locked the rw-lock in the specified mode, with the pass value == 0.
Definition: sync0rw.cc:858
static void rw_lock_s_unlock(rw_lock_t *L)
Definition: sync0rw.h:808
static void rw_lock_x_lock_gen(rw_lock_t *M, ulint P, ut::Location L)
Definition: sync0rw.h:786
static bool rw_lock_x_lock_nowait(rw_lock_t *M, ut::Location L)
Definition: sync0rw.h:790
#define rw_lock_create(K, L, ID)
Definition: sync0rw.h:720
static void rw_lock_x_unlock(rw_lock_t *L)
Definition: sync0rw.h:811
static void rw_lock_s_lock_gen(rw_lock_t *M, ulint P, ut::Location L)
Definition: sync0rw.h:735
static void rw_lock_free(rw_lock_t *M)
Definition: sync0rw.h:804
latch_id_t
Each latch has an ID.
Definition: sync0types.h:343
@ RW_LOCK_S
Definition: sync0types.h:208
@ RW_LOCK_X
Definition: sync0types.h:209
#define UNIV_PFS_RWLOCK
Definition: univ.i:137
Utilities related to CPU cache.
#define ut_ad(EXPR)
Debug assertion.
Definition: ut0dbg.h:105
#define ut_a(EXPR)
Abort execution if EXPR does not evaluate to nonzero.
Definition: ut0dbg.h:93
#define UT_NEW_THIS_FILE_PSI_KEY
Definition: ut0new.h:564
Random numbers and hashing.
Various utilities.
#define ut_is_2pow(n)
Determines if a number is zero or a power of two.
Definition: ut0ut.h:203