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