Skip to content

Commit e13459a

Browse files
committed
MDEV-7148 - Recurring: InnoDB: Failing assertion: !lock->recursive
Re-applied lost in the merge revision: commit ed313e8 Author: Sergey Vojtovich <svoj@mariadb.org> Date: Mon Dec 1 14:58:29 2014 +0400 MDEV-7148 - Recurring: InnoDB: Failing assertion: !lock->recursive On PPC64 high-loaded server may crash due to assertion failure in InnoDB rwlocks code. This happened because load order between "recursive" and "writer_thread" wasn't properly enforced.
1 parent 7dee7a0 commit e13459a

File tree

4 files changed

+28
-14
lines changed

4 files changed

+28
-14
lines changed

storage/innobase/include/sync0rw.ic

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,7 @@ rw_lock_x_lock_func_nowait(
386386
ulint line) /*!< in: line where requested */
387387
{
388388
ibool success;
389+
ibool local_recursive= lock->recursive;
389390

390391
#ifdef INNODB_RW_LOCKS_USE_ATOMICS
391392
success = os_compare_and_swap_lint(&lock->lock_word, X_LOCK_DECR, 0);
@@ -400,10 +401,14 @@ rw_lock_x_lock_func_nowait(
400401
mutex_exit(&(lock->mutex));
401402

402403
#endif
404+
/* Note: recursive must be loaded before writer_thread see
405+
comment for rw_lock_set_writer_id_and_recursion_flag().
406+
To achieve this we load it before os_compare_and_swap_lint(),
407+
which implies full memory barrier in current implementation. */
403408
if (success) {
404409
rw_lock_set_writer_id_and_recursion_flag(lock, TRUE);
405410

406-
} else if (lock->recursive
411+
} else if (local_recursive
407412
&& os_thread_eq(lock->writer_thread,
408413
os_thread_get_curr_id())) {
409414
/* Relock: this lock_word modification is safe since no other

storage/innobase/sync/sync0rw.cc

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,8 @@ rw_lock_x_lock_low(
545545
const char* file_name,/*!< in: file name where lock requested */
546546
ulint line) /*!< in: line where requested */
547547
{
548+
ibool local_recursive= lock->recursive;
549+
548550
if (rw_lock_lock_word_decr(lock, X_LOCK_DECR)) {
549551

550552
/* lock->recursive also tells us if the writer_thread
@@ -566,12 +568,12 @@ rw_lock_x_lock_low(
566568
} else {
567569
os_thread_id_t thread_id = os_thread_get_curr_id();
568570

569-
if (!pass) {
570-
os_rmb;
571-
}
572-
573-
/* Decrement failed: relock or failed lock */
574-
if (!pass && lock->recursive
571+
/* Decrement failed: relock or failed lock
572+
Note: recursive must be loaded before writer_thread see
573+
comment for rw_lock_set_writer_id_and_recursion_flag().
574+
To achieve this we load it before rw_lock_lock_word_decr(),
575+
which implies full memory barrier in current implementation. */
576+
if (!pass && local_recursive
575577
&& os_thread_eq(lock->writer_thread, thread_id)) {
576578
/* Relock */
577579
if (lock->lock_word == 0) {

storage/xtradb/include/sync0rw.ic

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,7 @@ rw_lock_x_lock_func_nowait(
511511
ulint line) /*!< in: line where requested */
512512
{
513513
ibool success;
514+
ibool local_recursive= lock->recursive;
514515

515516
#ifdef INNODB_RW_LOCKS_USE_ATOMICS
516517
success = os_compare_and_swap_lint(&lock->lock_word, X_LOCK_DECR, 0);
@@ -525,10 +526,14 @@ rw_lock_x_lock_func_nowait(
525526
mutex_exit(&(lock->mutex));
526527

527528
#endif
529+
/* Note: recursive must be loaded before writer_thread see
530+
comment for rw_lock_set_writer_id_and_recursion_flag().
531+
To achieve this we load it before os_compare_and_swap_lint(),
532+
which implies full memory barrier in current implementation. */
528533
if (success) {
529534
rw_lock_set_writer_id_and_recursion_flag(lock, TRUE);
530535

531-
} else if (lock->recursive
536+
} else if (local_recursive
532537
&& os_thread_eq(lock->writer_thread,
533538
os_thread_get_curr_id())) {
534539
/* Relock: this lock_word modification is safe since no other

storage/xtradb/sync/sync0rw.cc

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,8 @@ rw_lock_x_lock_low(
694694
const char* file_name,/*!< in: file name where lock requested */
695695
ulint line) /*!< in: line where requested */
696696
{
697+
ibool local_recursive= lock->recursive;
698+
697699
if (rw_lock_lock_word_decr(lock, X_LOCK_DECR)) {
698700

699701
/* lock->recursive also tells us if the writer_thread
@@ -715,12 +717,12 @@ rw_lock_x_lock_low(
715717
} else {
716718
os_thread_id_t thread_id = os_thread_get_curr_id();
717719

718-
if (!pass) {
719-
os_rmb;
720-
}
721-
722-
/* Decrement failed: relock or failed lock */
723-
if (!pass && lock->recursive
720+
/* Decrement failed: relock or failed lock
721+
Note: recursive must be loaded before writer_thread see
722+
comment for rw_lock_set_writer_id_and_recursion_flag().
723+
To achieve this we load it before rw_lock_lock_word_decr(),
724+
which implies full memory barrier in current implementation. */
725+
if (!pass && local_recursive
724726
&& os_thread_eq(lock->writer_thread, thread_id)) {
725727
/* Relock */
726728
if (lock->lock_word == 0) {

0 commit comments

Comments
 (0)