From 76c17992ca1dca259518ee1fd49527e7622e8877 Mon Sep 17 00:00:00 2001 From: Krunal Bauskar Date: Tue, 7 Jul 2020 12:16:50 +0800 Subject: [PATCH] Using optimal memory-barrier (in form of acquire/release) for event-mutex MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - EventMutex is home-grown spin-lock implementation that provide lock/unlock functionality. To facilitate this it uses a couple of atomic variables like m_lock_word and waiters with lock-word meant to track mutex lock/unlock operation and waiters to flag presence of waiter in turn need for a signal. - Currently, EventMutex uses the default memory barrier offered by C++ atomic that defaults to sequential consistency. This order is too strict and it can be switched to use acquire/release order without affecting the core flow/correctness. - In addition to the use of acquire/release barrier patch also identifies a redundant memory-fence that could be safely removed with the new proposed order. --- storage/innobase/include/ib0mutex.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/storage/innobase/include/ib0mutex.h b/storage/innobase/include/ib0mutex.h index 2e77e191dab..eb4047a31ce 100644 --- a/storage/innobase/include/ib0mutex.h +++ b/storage/innobase/include/ib0mutex.h @@ -532,13 +532,13 @@ struct TTASEventMutex { @return true on success */ bool try_lock() UNIV_NOTHROW { bool expected = false; - return (m_lock_word.compare_exchange_strong(expected, true)); + return (m_lock_word.compare_exchange_strong( + expected, true, std::memory_order_acquire, std::memory_order_acquire)); } /** Release the mutex. */ void exit() UNIV_NOTHROW { - m_lock_word.store(false); - std::atomic_thread_fence(std::memory_order_acquire); + m_lock_word.store(false, std::memory_order_release); if (m_waiters.load(std::memory_order_acquire)) { signal(); @@ -684,7 +684,7 @@ struct TTASEventMutex { /** Note that there are no threads waiting on the mutex */ void clear_waiters() UNIV_NOTHROW { - m_waiters.store(false, std::memory_order_release); + m_waiters.store(false, std::memory_order_acquire); } /** Wakeup any waiting thread(s). */