From 61cc839253bdc403a4da1ad638c20334d94fc9c0 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Mon, 17 Nov 2008 23:04:36 +0100 Subject: [PATCH] Fix for Percona reported bug with manual merge and fix of bug in patch (changed to use of UNIV_SYNC_ATOMIC from faulty HAVE_ATOMIC_BUILTINS). --- storage/innobase/include/sync0rw.ic | 29 ++++++++++++++++++++++------- storage/innobase/sync/sync0arr.c | 7 ++++++- storage/innobase/sync/sync0rw.c | 6 +++--- 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/storage/innobase/include/sync0rw.ic b/storage/innobase/include/sync0rw.ic index d5d3ee954be..ce25ae0e6a8 100644 --- a/storage/innobase/include/sync0rw.ic +++ b/storage/innobase/include/sync0rw.ic @@ -57,10 +57,25 @@ UNIV_INLINE void rw_lock_set_waiters( /*================*/ - rw_lock_t* lock, - ulint flag) + rw_lock_t* lock) { - lock->waiters = flag; +#ifdef UNIV_SYNC_ATOMIC + os_compare_and_swap(&(lock->waiters), 0, 1); +#else /* UNIV_SYNC_ATOMIC */ + lock->waiters = 1; +#endif /* UNIV_SYNC_ATOMIC */ +} +UNIV_INLINE +void +rw_lock_reset_waiters( +/*================*/ + rw_lock_t* lock) +{ +#ifdef UNIV_SYNC_ATOMIC + os_compare_and_swap(&(lock->waiters), 1, 0); +#else /* UNIV_SYNC_ATOMIC */ + lock->waiters = 0; +#endif /* UNIV_SYNC_ATOMIC */ } /********************************************************************** @@ -454,7 +469,7 @@ rw_lock_s_unlock_direct( /* Decrease reader count by incrementing lock_word */ lock->lock_word++; - ut_ad(!lock->waiters); + ut_ad(!rw_lock_get_waiters(lock)); ut_ad(rw_lock_validate(lock)); #ifdef UNIV_SYNC_PERF_STAT rw_s_exit_count++; @@ -494,8 +509,8 @@ rw_lock_x_unlock_func( /* Lock is now free. May have to signal read/write waiters. We do not need to signal wait_ex waiters, since they cannot exist when there is a writer. */ - if(lock->waiters) { - rw_lock_set_waiters(lock, 0); + if(rw_lock_get_waiters(lock)) { + rw_lock_reset_waiters(lock); os_event_set(lock->event); sync_array_object_signalled(sync_primary_wait_array); } @@ -532,7 +547,7 @@ rw_lock_x_unlock_direct( lock->lock_word += X_LOCK_DECR; - ut_ad(!lock->waiters); + ut_ad(!rw_lock_get_waiters(lock)); ut_ad(rw_lock_validate(lock)); #ifdef UNIV_SYNC_PERF_STAT diff --git a/storage/innobase/sync/sync0arr.c b/storage/innobase/sync/sync0arr.c index a03d6d13502..bb64ac07342 100644 --- a/storage/innobase/sync/sync0arr.c +++ b/storage/innobase/sync/sync0arr.c @@ -549,7 +549,8 @@ sync_array_find_thread( cell = sync_array_get_nth_cell(arr, i); if (cell->wait_object != NULL - && os_thread_eq(cell->thread, thread)) { + && os_thread_eq(cell->thread, thread) + && cell->waiting)) { return(cell); /* Found */ } @@ -887,6 +888,10 @@ sync_arr_wake_threads_if_sema_free(void) } count++; + if (!cell->waiting) { + continue; + } + if (sync_arr_cell_can_wake_up(cell)) { event = sync_cell_get_event(cell); diff --git a/storage/innobase/sync/sync0rw.c b/storage/innobase/sync/sync0rw.c index ced2f72187a..e178606cef5 100644 --- a/storage/innobase/sync/sync0rw.c +++ b/storage/innobase/sync/sync0rw.c @@ -209,7 +209,7 @@ rw_lock_create_func( #endif /* UNIV_SYNC_ATOMIC */ lock->lock_word = X_LOCK_DECR; - rw_lock_set_waiters(lock, 0); + lock->waiters = 0; lock->writer_thread = -1; lock->pass = 0; @@ -369,7 +369,7 @@ lock_loop: /* Set waiters before checking lock_word to ensure wake-up signal is sent. This may lead to some unnecessary signals. */ - rw_lock_set_waiters(lock, 1); + rw_lock_set_waiters(lock); if (TRUE == rw_lock_s_lock_low(lock, pass, file_name, line)) { sync_array_free_cell(sync_primary_wait_array, index); @@ -634,7 +634,7 @@ lock_loop: /* Waiters must be set before checking lock_word, to ensure signal is sent. This could lead to a few unnecessary wake-up signals. */ - rw_lock_set_waiters(lock, 1); + rw_lock_set_waiters(lock); if (rw_lock_x_lock_low(lock, pass, file_name, line)) { sync_array_free_cell(sync_primary_wait_array, index);