summaryrefslogtreecommitdiff
path: root/storage/innobase/include/ib0mutex.h
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/include/ib0mutex.h')
-rw-r--r--storage/innobase/include/ib0mutex.h127
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 */