Skip to content

Commit d937049

Browse files
committed
[RP012] Small reordering around atomic operations and memory orderings
The atomic operations and memory orderings (builtin functions) are not reordered during optimization due to concerns about triggering critical cases. Therefore, manual optimization is required for these non-critical cases.
1 parent d6dbde6 commit d937049

File tree

5 files changed

+40
-34
lines changed

5 files changed

+40
-34
lines changed

MYSQL_VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ MYSQL_VERSION_MINOR=0
33
MYSQL_VERSION_PATCH=42
44
MYSQL_VERSION_EXTRA=
55
MYSQL_VERSION_STABILITY="LTS"
6-
MYSQL_RP_REVISION="-RP011"
6+
MYSQL_RP_REVISION="-RP012"

storage/innobase/include/sync0rw.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
Copyright (c) 1995, 2025, Oracle and/or its affiliates.
44
Copyright (c) 2008, Google Inc.
5+
Copyright (c) 2025, buildup-db.
56
67
Portions of this file contain modifications contributed and copyrighted by
78
Google, Inc. Those modifications are gratefully acknowledged and are described
@@ -265,14 +266,14 @@ This is used by both s_lock and x_lock operations.
265266
@param[in] amount amount to decrement
266267
@param[in] threshold threshold of judgement
267268
@return true if decr occurs */
268-
static inline bool rw_lock_lock_word_decr(rw_lock_t *lock, ulint amount,
269-
lint threshold);
269+
static inline bool rw_lock_lock_word_decr(rw_lock_t *lock, int32_t amount,
270+
int32_t threshold);
270271

271272
/** Increments lock_word the specified amount and returns new value.
272273
@param[in,out] lock rw-lock
273274
@param[in] amount amount to decrement
274275
@return lock->lock_word after increment */
275-
static inline lint rw_lock_lock_word_incr(rw_lock_t *lock, ulint amount);
276+
static inline int32_t rw_lock_lock_word_incr(rw_lock_t *lock, int32_t amount);
276277

277278
/** This function sets the lock->writer_thread and lock->recursive fields. Sets
278279
lock->recursive field using atomic release after setting lock->writer thread to

storage/innobase/include/sync0rw.ic

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
Copyright (c) 1995, 2025, Oracle and/or its affiliates.
44
Copyright (c) 2008, Google Inc.
5+
Copyright (c) 2025, buildup-db.
56

67
Portions of this file contain modifications contributed and copyrighted by
78
Google, Inc. Those modifications are gratefully acknowledged and are described
@@ -95,7 +96,7 @@ static inline void rw_lock_reset_waiter_flag(
9596
static inline ulint rw_lock_get_writer(
9697
const rw_lock_t *lock) /*!< in: rw-lock */
9798
{
98-
lint lock_word = lock->lock_word;
99+
int32_t lock_word = lock->lock_word;
99100

100101
ut_ad(lock_word <= X_LOCK_DECR);
101102
if (lock_word > X_LOCK_HALF_DECR) {
@@ -122,7 +123,7 @@ static inline ulint rw_lock_get_writer(
122123
static inline ulint rw_lock_get_reader_count(
123124
const rw_lock_t *lock) /*!< in: rw-lock */
124125
{
125-
lint lock_word = lock->lock_word;
126+
int32_t lock_word = lock->lock_word;
126127
ut_ad(lock_word <= X_LOCK_DECR);
127128

128129
if (lock_word > X_LOCK_HALF_DECR) {
@@ -154,7 +155,7 @@ static inline ulint rw_lock_get_reader_count(
154155
static inline ulint rw_lock_get_x_lock_count(
155156
const rw_lock_t *lock) /*!< in: rw-lock */
156157
{
157-
lint lock_copy = lock->lock_word;
158+
int32_t lock_copy = lock->lock_word;
158159
ut_ad(lock_copy <= X_LOCK_DECR);
159160

160161
if (lock_copy == 0 || lock_copy == -X_LOCK_HALF_DECR) {
@@ -183,7 +184,7 @@ static inline ulint rw_lock_get_sx_lock_count(
183184
const rw_lock_t *lock) /*!< in: rw-lock */
184185
{
185186
#ifdef UNIV_DEBUG
186-
lint lock_copy = lock->lock_word;
187+
int32_t lock_copy = lock->lock_word;
187188

188189
ut_ad(lock_copy <= X_LOCK_DECR);
189190

@@ -209,13 +210,12 @@ static inline ulint rw_lock_get_sx_lock_count(
209210
@return true if decr occurs */
210211
ALWAYS_INLINE
211212
bool rw_lock_lock_word_decr(rw_lock_t *lock, /*!< in/out: rw-lock */
212-
ulint amount, /*!< in: amount to decrement */
213-
lint threshold) /*!< in: threshold of judgement */
213+
int32_t amount, /*!< in: amount to decrement */
214+
int32_t threshold) /*!< in: threshold of judgement */
214215
{
215216
int32_t local_lock_word;
216217

217-
os_rmb;
218-
local_lock_word = lock->lock_word;
218+
local_lock_word = lock->lock_word.load(std::memory_order_acquire);
219219
while (local_lock_word > threshold) {
220220
if (lock->lock_word.compare_exchange_strong(local_lock_word,
221221
local_lock_word - amount)) {
@@ -227,9 +227,9 @@ bool rw_lock_lock_word_decr(rw_lock_t *lock, /*!< in/out: rw-lock */
227227

228228
/** Increments lock_word the specified amount and returns new value.
229229
@return lock->lock_word after increment */
230-
static inline lint rw_lock_lock_word_incr(
230+
static inline int32_t rw_lock_lock_word_incr(
231231
rw_lock_t *lock, /*!< in/out: rw-lock */
232-
ulint amount) /*!< in: amount of increment */
232+
int32_t amount) /*!< in: amount of increment */
233233
{
234234
return (lock->lock_word.fetch_add(amount) + amount);
235235
}
@@ -315,10 +315,11 @@ static inline bool rw_lock_x_lock_func_nowait(rw_lock_t *lock,
315315
/* Relock: this lock_word modification is safe since no other
316316
threads can modify (lock, unlock, or reserve) lock_word while
317317
there is an exclusive writer and this is the writer thread. */
318-
if (lock->lock_word == 0 || lock->lock_word == -X_LOCK_HALF_DECR) {
318+
const int32_t lock_word = lock->lock_word;
319+
if (lock_word == 0 || lock_word == -X_LOCK_HALF_DECR) {
319320
/* There are 1 x-locks */
320321
lock->lock_word -= X_LOCK_DECR;
321-
} else if (lock->lock_word <= -X_LOCK_DECR) {
322+
} else if (lock_word <= -X_LOCK_DECR) {
322323
/* There are 2 or more x-locks */
323324
lock->lock_word--;
324325
} else {
@@ -362,7 +363,7 @@ static inline void rw_lock_s_unlock_func(IF_DEBUG(ulint pass, )
362363
ut_d(rw_lock_remove_debug_info(lock, pass, RW_LOCK_S));
363364

364365
/* Increment lock_word to indicate 1 less reader */
365-
lint lock_word = rw_lock_lock_word_incr(lock, 1);
366+
int32_t lock_word = rw_lock_lock_word_incr(lock, 1);
366367
if (lock_word == 0 || lock_word == -X_LOCK_HALF_DECR) {
367368
/* wait_ex waiter exists. It may not be asleep, but we signal
368369
anyway. We do not wake other waiters, because they can't
@@ -396,7 +397,8 @@ static inline void rw_lock_x_unlock_func(IF_DEBUG(ulint pass, )
396397

397398
ut_d(rw_lock_remove_debug_info(lock, pass, RW_LOCK_X));
398399

399-
if (lock->lock_word == 0 || lock->lock_word == -X_LOCK_HALF_DECR) {
400+
const int32_t lock_word = lock->lock_word;
401+
if (lock_word == 0 || lock_word == -X_LOCK_HALF_DECR) {
400402
/* There is 1 x-lock */
401403
/* atomic increment is needed, because it is last */
402404
if (rw_lock_lock_word_incr(lock, X_LOCK_DECR) <= 0) {
@@ -413,13 +415,13 @@ static inline void rw_lock_x_unlock_func(IF_DEBUG(ulint pass, )
413415
os_event_set(lock->event);
414416
sync_array_object_signalled();
415417
}
416-
} else if (lock->lock_word == -X_LOCK_DECR ||
417-
lock->lock_word == -(X_LOCK_DECR + X_LOCK_HALF_DECR)) {
418+
} else if (lock_word == -X_LOCK_DECR ||
419+
lock_word == -(X_LOCK_DECR + X_LOCK_HALF_DECR)) {
418420
/* There are 2 x-locks */
419421
lock->lock_word += X_LOCK_DECR;
420422
} else {
421423
/* There are more than 2 x-locks. */
422-
ut_ad(lock->lock_word < -X_LOCK_DECR);
424+
ut_ad(lock_word < -X_LOCK_DECR);
423425
lock->lock_word += 1;
424426
}
425427

storage/innobase/include/ut0lst.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/*****************************************************************************
22
33
Copyright (c) 1995, 2025, Oracle and/or its affiliates.
4+
Copyright (c) 2025, buildup-db.
45
56
This program is free software; you can redistribute it and/or modify it under
67
the terms of the GNU General Public License, version 2.0, as published by the
@@ -117,7 +118,7 @@ struct ut_list_base {
117118
@param diff the value by which to increase the length. Can be negative. */
118119
void update_length(int diff) {
119120
ut_ad(diff > 0 || static_cast<size_t>(-diff) <= get_length());
120-
count.store(get_length() + diff, std::memory_order_release);
121+
count.fetch_add(diff, std::memory_order_acq_rel);
121122
}
122123

123124
void clear() {

storage/innobase/sync/sync0rw.cc

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
Copyright (c) 1995, 2025, Oracle and/or its affiliates.
44
Copyright (c) 2008, Google Inc.
5+
Copyright (c) 2025, buildup-db.
56
67
Portions of this file contain modifications contributed and copyrighted by
78
Google, Inc. Those modifications are gratefully acknowledged and are described
@@ -282,8 +283,8 @@ void rw_lock_s_lock_spin(rw_lock_t *lock, ulint pass, ut::Location location) {
282283
lock_loop:
283284

284285
/* Spin waiting for the writer field to become free */
285-
os_rmb;
286-
while (i < srv_n_spin_wait_rounds && lock->lock_word <= 0) {
286+
while (i < srv_n_spin_wait_rounds &&
287+
lock->lock_word.load(std::memory_order_acquire) <= 0) {
287288
if (srv_spin_wait_delay) {
288289
ut_delay(ut::random_from_interval_fast(0, srv_spin_wait_delay));
289290
}
@@ -376,17 +377,15 @@ static inline void rw_lock_x_lock_wait_func(rw_lock_t *lock,
376377
sync_array_t *sync_arr;
377378
uint64_t count_os_wait = 0;
378379

379-
os_rmb;
380-
ut_ad(lock->lock_word <= threshold);
380+
ut_ad(lock->lock_word.load(std::memory_order_acquire) <= threshold);
381381

382-
while (lock->lock_word < threshold) {
382+
while (lock->lock_word.load(std::memory_order_acquire) < threshold) {
383383
if (srv_spin_wait_delay) {
384384
ut_delay(ut::random_from_interval_fast(0, srv_spin_wait_delay));
385385
}
386386

387387
if (i < srv_n_spin_wait_rounds) {
388388
i++;
389-
os_rmb;
390389
continue;
391390
}
392391

@@ -399,7 +398,7 @@ static inline void rw_lock_x_lock_wait_func(rw_lock_t *lock,
399398
i = 0;
400399

401400
/* Check lock_word to ensure wake-up isn't missed.*/
402-
if (lock->lock_word < threshold) {
401+
if (lock->lock_word.load(std::memory_order_acquire) < threshold) {
403402
++count_os_wait;
404403

405404
/* Add debug info as it is needed to detect possible
@@ -484,7 +483,8 @@ static inline bool rw_lock_x_lock_low(
484483
} else {
485484
/* At least one X lock by this thread already
486485
exists. Add another. */
487-
if (lock->lock_word == 0 || lock->lock_word == -X_LOCK_HALF_DECR) {
486+
const int32_t lock_word = lock->lock_word;
487+
if (lock_word == 0 || lock_word == -X_LOCK_HALF_DECR) {
488488
lock->lock_word -= X_LOCK_DECR;
489489
} else {
490490
ut_ad(lock->lock_word <= -X_LOCK_DECR);
@@ -594,8 +594,9 @@ void rw_lock_x_lock_func(rw_lock_t *lock, ulint pass, ut::Location location) {
594594
}
595595

596596
/* Spin waiting for the lock_word to become free */
597-
os_rmb;
598-
while (i < srv_n_spin_wait_rounds && lock->lock_word <= X_LOCK_HALF_DECR) {
597+
while (i < srv_n_spin_wait_rounds &&
598+
lock->lock_word.load(std::memory_order_acquire) <=
599+
X_LOCK_HALF_DECR) {
599600
if (srv_spin_wait_delay) {
600601
ut_delay(ut::random_from_interval_fast(0, srv_spin_wait_delay));
601602
}
@@ -659,8 +660,9 @@ void rw_lock_sx_lock_func(rw_lock_t *lock, ulint pass, ut::Location location) {
659660

660661
} else {
661662
/* Spin waiting for the lock_word to become free */
662-
os_rmb;
663-
while (i < srv_n_spin_wait_rounds && lock->lock_word <= X_LOCK_HALF_DECR) {
663+
while (i < srv_n_spin_wait_rounds &&
664+
lock->lock_word.load(std::memory_order_acquire) <=
665+
X_LOCK_HALF_DECR) {
664666
if (srv_spin_wait_delay) {
665667
ut_delay(ut::random_from_interval_fast(0, srv_spin_wait_delay));
666668
}

0 commit comments

Comments
 (0)