diff options
Diffstat (limited to 'storage/innobase/include/ib0mutex.h')
-rw-r--r-- | storage/innobase/include/ib0mutex.h | 127 |
1 files changed, 66 insertions, 61 deletions
diff --git a/storage/innobase/include/ib0mutex.h b/storage/innobase/include/ib0mutex.h index eaf391be09b..f4ba8a81275 100644 --- a/storage/innobase/include/ib0mutex.h +++ b/storage/innobase/include/ib0mutex.h @@ -35,7 +35,7 @@ Created 2013-03-26 Sunny Bains. #include "sync0arr.h" /** OS mutex for tracking lock/unlock for debugging */ -template <template <typename> class Policy = NoPolicy> +template <template <typename> class Policy> struct OSTrackMutex { typedef Policy<OSTrackMutex> MutexPolicy; @@ -152,7 +152,7 @@ private: #include <sys/syscall.h> /** Mutex implementation that used the Linux futex. */ -template <template <typename> class Policy = NoPolicy> +template <template <typename> class Policy> struct TTASFutexMutex { typedef Policy<TTASFutexMutex> MutexPolicy; @@ -167,21 +167,24 @@ struct TTASFutexMutex { ~TTASFutexMutex() { - ut_a(m_lock_word == MUTEX_STATE_UNLOCKED); + ut_ad(m_lock_word.load(std::memory_order_relaxed) + == MUTEX_STATE_UNLOCKED); } /** Called when the mutex is "created". Note: Not from the constructor but when the mutex is initialised. */ void init(latch_id_t, const char*, uint32_t) UNIV_NOTHROW { - ut_a(m_lock_word == MUTEX_STATE_UNLOCKED); + ut_ad(m_lock_word.load(std::memory_order_relaxed) + == MUTEX_STATE_UNLOCKED); } /** Destroy the mutex. */ void destroy() UNIV_NOTHROW { /* The destructor can be called at shutdown. */ - ut_a(m_lock_word == MUTEX_STATE_UNLOCKED); + ut_ad(m_lock_word.load(std::memory_order_relaxed) + == MUTEX_STATE_UNLOCKED); } /** Acquire the mutex. @@ -202,9 +205,8 @@ struct TTASFutexMutex { } for (n_waits= 0;; n_waits++) { - if (my_atomic_fas32_explicit(&m_lock_word, - MUTEX_STATE_WAITERS, - MY_MEMORY_ORDER_ACQUIRE) + if (m_lock_word.exchange(MUTEX_STATE_WAITERS, + std::memory_order_acquire) == MUTEX_STATE_UNLOCKED) { break; } @@ -220,9 +222,8 @@ struct TTASFutexMutex { /** Release the mutex. */ void exit() UNIV_NOTHROW { - if (my_atomic_fas32_explicit(&m_lock_word, - MUTEX_STATE_UNLOCKED, - MY_MEMORY_ORDER_RELEASE) + if (m_lock_word.exchange(MUTEX_STATE_UNLOCKED, + std::memory_order_release) == MUTEX_STATE_WAITERS) { syscall(SYS_futex, &m_lock_word, FUTEX_WAKE_PRIVATE, 1, 0, 0, 0); @@ -234,10 +235,11 @@ struct TTASFutexMutex { bool try_lock() UNIV_NOTHROW { int32 oldval = MUTEX_STATE_UNLOCKED; - return(my_atomic_cas32_strong_explicit(&m_lock_word, &oldval, - MUTEX_STATE_LOCKED, - MY_MEMORY_ORDER_ACQUIRE, - MY_MEMORY_ORDER_RELAXED)); + return m_lock_word.compare_exchange_strong( + oldval, + MUTEX_STATE_LOCKED, + std::memory_order_acquire, + std::memory_order_relaxed); } /** @return non-const version of the policy */ @@ -257,12 +259,12 @@ private: /** lock_word is the target of the atomic test-and-set instruction when atomic operations are enabled. */ - int32 m_lock_word; + std::atomic<int32> m_lock_word; }; #endif /* HAVE_IB_LINUX_FUTEX */ -template <template <typename> class Policy = NoPolicy> +template <template <typename> class Policy> struct TTASMutex { typedef Policy<TTASMutex> MutexPolicy; @@ -277,40 +279,45 @@ struct TTASMutex { ~TTASMutex() { - ut_ad(m_lock_word == MUTEX_STATE_UNLOCKED); + ut_ad(m_lock_word.load(std::memory_order_relaxed) + == MUTEX_STATE_UNLOCKED); } /** Called when the mutex is "created". Note: Not from the constructor but when the mutex is initialised. */ void init(latch_id_t) UNIV_NOTHROW { - ut_ad(m_lock_word == MUTEX_STATE_UNLOCKED); + ut_ad(m_lock_word.load(std::memory_order_relaxed) + == MUTEX_STATE_UNLOCKED); } /** Destroy the mutex. */ void destroy() UNIV_NOTHROW { /* The destructor can be called at shutdown. */ - ut_ad(m_lock_word == MUTEX_STATE_UNLOCKED); + ut_ad(m_lock_word.load(std::memory_order_relaxed) + == MUTEX_STATE_UNLOCKED); } /** Try and lock the mutex. @return true on success */ bool try_lock() UNIV_NOTHROW { - int32 oldval = MUTEX_STATE_UNLOCKED; - return(my_atomic_cas32_strong_explicit(&m_lock_word, &oldval, - MUTEX_STATE_LOCKED, - MY_MEMORY_ORDER_ACQUIRE, - MY_MEMORY_ORDER_RELAXED)); + uint32_t oldval = MUTEX_STATE_UNLOCKED; + return m_lock_word.compare_exchange_strong( + oldval, + MUTEX_STATE_LOCKED, + std::memory_order_acquire, + std::memory_order_relaxed); } /** Release the mutex. */ void exit() UNIV_NOTHROW { - ut_ad(m_lock_word == MUTEX_STATE_LOCKED); - my_atomic_store32_explicit(&m_lock_word, MUTEX_STATE_UNLOCKED, - MY_MEMORY_ORDER_RELEASE); + ut_ad(m_lock_word.load(std::memory_order_relaxed) + == MUTEX_STATE_LOCKED); + m_lock_word.store(MUTEX_STATE_UNLOCKED, + std::memory_order_release); } /** Acquire the mutex. @@ -353,12 +360,11 @@ private: /** Policy data */ MutexPolicy m_policy; - /** lock_word is the target of the atomic test-and-set instruction - when atomic operations are enabled. */ - int32 m_lock_word; + /** mutex state */ + std::atomic<uint32_t> m_lock_word; }; -template <template <typename> class Policy = NoPolicy> +template <template <typename> class Policy> struct TTASEventMutex { typedef Policy<TTASEventMutex> MutexPolicy; @@ -376,7 +382,7 @@ struct TTASEventMutex { ~TTASEventMutex() UNIV_NOTHROW { - ut_ad(m_lock_word == MUTEX_STATE_UNLOCKED); + ut_ad(state() == MUTEX_STATE_UNLOCKED); } /** Called when the mutex is "created". Note: Not from the constructor @@ -385,7 +391,7 @@ struct TTASEventMutex { void init(latch_id_t id, const char*, uint32_t) UNIV_NOTHROW { ut_a(m_event == 0); - ut_a(m_lock_word == MUTEX_STATE_UNLOCKED); + ut_ad(state() == MUTEX_STATE_UNLOCKED); m_event = os_event_create(sync_latch_get_name(id)); } @@ -396,7 +402,7 @@ struct TTASEventMutex { void destroy() UNIV_NOTHROW { - ut_ad(m_lock_word == MUTEX_STATE_UNLOCKED); + ut_ad(state() == MUTEX_STATE_UNLOCKED); /* We have to free the event before InnoDB shuts down. */ os_event_destroy(m_event); @@ -408,20 +414,20 @@ struct TTASEventMutex { bool try_lock() UNIV_NOTHROW { - int32 oldval = MUTEX_STATE_UNLOCKED; - return(my_atomic_cas32_strong_explicit(&m_lock_word, &oldval, - MUTEX_STATE_LOCKED, - MY_MEMORY_ORDER_ACQUIRE, - MY_MEMORY_ORDER_RELAXED)); + uint32_t oldval = MUTEX_STATE_UNLOCKED; + return m_lock_word.compare_exchange_strong( + oldval, + MUTEX_STATE_LOCKED, + std::memory_order_acquire, + std::memory_order_relaxed); } /** Release the mutex. */ void exit() UNIV_NOTHROW { - if (my_atomic_fas32_explicit(&m_lock_word, - MUTEX_STATE_UNLOCKED, - MY_MEMORY_ORDER_RELEASE) + if (m_lock_word.exchange(MUTEX_STATE_UNLOCKED, + std::memory_order_release) == MUTEX_STATE_WAITERS) { os_event_set(m_event); sync_array_object_signalled(); @@ -459,11 +465,12 @@ struct TTASEventMutex { : SYNC_MUTEX, filename, line, &cell); - int32 oldval = MUTEX_STATE_LOCKED; - my_atomic_cas32_strong_explicit(&m_lock_word, &oldval, - MUTEX_STATE_WAITERS, - MY_MEMORY_ORDER_RELAXED, - MY_MEMORY_ORDER_RELAXED); + uint32_t oldval = MUTEX_STATE_LOCKED; + m_lock_word.compare_exchange_strong( + oldval, + MUTEX_STATE_WAITERS, + std::memory_order_relaxed, + std::memory_order_relaxed); if (oldval == MUTEX_STATE_UNLOCKED) { sync_array_free_cell(sync_arr, cell); @@ -482,9 +489,7 @@ struct TTASEventMutex { int32 state() const UNIV_NOTHROW { - return(my_atomic_load32_explicit(const_cast<int32*> - (&m_lock_word), - MY_MEMORY_ORDER_RELAXED)); + return m_lock_word.load(std::memory_order_relaxed); } /** The event that the mutex will wait in sync0arr.cc @@ -514,9 +519,8 @@ private: TTASEventMutex(const TTASEventMutex&); TTASEventMutex& operator=(const TTASEventMutex&); - /** lock_word is the target of the atomic test-and-set instruction - when atomic operations are enabled. */ - int32 m_lock_word; + /** mutex state */ + std::atomic<uint32_t> m_lock_word; /** Used by sync0arr.cc for the wait queue */ os_event_t m_event; @@ -530,7 +534,6 @@ with the Performance Schema instrumentation. */ template <typename MutexImpl> struct PolicyMutex { - typedef MutexImpl MutexType; typedef typename MutexImpl::MutexPolicy Policy; PolicyMutex() UNIV_NOTHROW : m_impl() @@ -561,7 +564,7 @@ struct PolicyMutex pfs_exit(); #endif /* UNIV_PFS_MUTEX */ - policy().release(m_impl); + ut_d(policy().context.release(m_impl)); m_impl.exit(); } @@ -587,11 +590,11 @@ struct PolicyMutex locker = pfs_begin_lock(&state, name, line); #endif /* UNIV_PFS_MUTEX */ - policy().enter(m_impl, name, line); + ut_d(policy().context.enter(m_impl, name, line)); m_impl.enter(n_spins, n_delay, name, line); - policy().locked(m_impl, name, line); + ut_d(policy().context.locked(m_impl, name, line)); #ifdef UNIV_PFS_MUTEX pfs_end(locker, 0); #endif /* UNIV_PFS_MUTEX */ @@ -620,9 +623,9 @@ struct PolicyMutex if (ret == 0) { - policy().enter(m_impl, name, line); + ut_d(policy().context.enter(m_impl, name, line)); - policy().locked(m_impl, name, line); + ut_d(policy().context.locked(m_impl, name, line)); } #ifdef UNIV_PFS_MUTEX @@ -636,7 +639,7 @@ struct PolicyMutex /** @return true if the thread owns the mutex. */ bool is_owned() const UNIV_NOTHROW { - return(policy().is_owned()); + return(policy().context.is_owned()); } #endif /* UNIV_DEBUG */ @@ -658,6 +661,7 @@ struct PolicyMutex m_impl.init(id, filename, line); policy().init(m_impl, id, filename, line); + ut_d(policy().context.init(id)); } /** Free resources (if any) */ @@ -668,6 +672,7 @@ struct PolicyMutex #endif /* UNIV_PFS_MUTEX */ m_impl.destroy(); policy().destroy(); + ut_d(policy().context.destroy()); } /** Required for os_event_t */ |