Commit 65083ba6 authored by Sergey Vojtovich's avatar Sergey Vojtovich

MDEV-17441 - InnoDB transition to C++11 atomics

Simplified mutex code. MutexDebug uses OSMutex instead of
atomic operations now.
parent e2b585c1
...@@ -35,7 +35,7 @@ Created 2013-03-26 Sunny Bains. ...@@ -35,7 +35,7 @@ Created 2013-03-26 Sunny Bains.
#include "sync0arr.h" #include "sync0arr.h"
/** OS mutex for tracking lock/unlock for debugging */ /** OS mutex for tracking lock/unlock for debugging */
template <template <typename> class Policy = NoPolicy> template <template <typename> class Policy>
struct OSTrackMutex { struct OSTrackMutex {
typedef Policy<OSTrackMutex> MutexPolicy; typedef Policy<OSTrackMutex> MutexPolicy;
...@@ -152,7 +152,7 @@ struct OSTrackMutex { ...@@ -152,7 +152,7 @@ struct OSTrackMutex {
#include <sys/syscall.h> #include <sys/syscall.h>
/** Mutex implementation that used the Linux futex. */ /** Mutex implementation that used the Linux futex. */
template <template <typename> class Policy = NoPolicy> template <template <typename> class Policy>
struct TTASFutexMutex { struct TTASFutexMutex {
typedef Policy<TTASFutexMutex> MutexPolicy; typedef Policy<TTASFutexMutex> MutexPolicy;
...@@ -264,7 +264,7 @@ struct TTASFutexMutex { ...@@ -264,7 +264,7 @@ struct TTASFutexMutex {
#endif /* HAVE_IB_LINUX_FUTEX */ #endif /* HAVE_IB_LINUX_FUTEX */
template <template <typename> class Policy = NoPolicy> template <template <typename> class Policy>
struct TTASMutex { struct TTASMutex {
typedef Policy<TTASMutex> MutexPolicy; typedef Policy<TTASMutex> MutexPolicy;
...@@ -364,7 +364,7 @@ struct TTASMutex { ...@@ -364,7 +364,7 @@ struct TTASMutex {
std::atomic<uint32_t> m_lock_word; std::atomic<uint32_t> m_lock_word;
}; };
template <template <typename> class Policy = NoPolicy> template <template <typename> class Policy>
struct TTASEventMutex { struct TTASEventMutex {
typedef Policy<TTASEventMutex> MutexPolicy; typedef Policy<TTASEventMutex> MutexPolicy;
...@@ -534,7 +534,6 @@ with the Performance Schema instrumentation. */ ...@@ -534,7 +534,6 @@ with the Performance Schema instrumentation. */
template <typename MutexImpl> template <typename MutexImpl>
struct PolicyMutex struct PolicyMutex
{ {
typedef MutexImpl MutexType;
typedef typename MutexImpl::MutexPolicy Policy; typedef typename MutexImpl::MutexPolicy Policy;
PolicyMutex() UNIV_NOTHROW : m_impl() PolicyMutex() UNIV_NOTHROW : m_impl()
...@@ -565,7 +564,7 @@ struct PolicyMutex ...@@ -565,7 +564,7 @@ struct PolicyMutex
pfs_exit(); pfs_exit();
#endif /* UNIV_PFS_MUTEX */ #endif /* UNIV_PFS_MUTEX */
policy().release(m_impl); ut_d(policy().context.release(m_impl));
m_impl.exit(); m_impl.exit();
} }
...@@ -591,11 +590,11 @@ struct PolicyMutex ...@@ -591,11 +590,11 @@ struct PolicyMutex
locker = pfs_begin_lock(&state, name, line); locker = pfs_begin_lock(&state, name, line);
#endif /* UNIV_PFS_MUTEX */ #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); 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 #ifdef UNIV_PFS_MUTEX
pfs_end(locker, 0); pfs_end(locker, 0);
#endif /* UNIV_PFS_MUTEX */ #endif /* UNIV_PFS_MUTEX */
...@@ -624,9 +623,9 @@ struct PolicyMutex ...@@ -624,9 +623,9 @@ struct PolicyMutex
if (ret == 0) { 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 #ifdef UNIV_PFS_MUTEX
...@@ -640,7 +639,7 @@ struct PolicyMutex ...@@ -640,7 +639,7 @@ struct PolicyMutex
/** @return true if the thread owns the mutex. */ /** @return true if the thread owns the mutex. */
bool is_owned() const UNIV_NOTHROW bool is_owned() const UNIV_NOTHROW
{ {
return(policy().is_owned()); return(policy().context.is_owned());
} }
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
...@@ -662,6 +661,7 @@ struct PolicyMutex ...@@ -662,6 +661,7 @@ struct PolicyMutex
m_impl.init(id, filename, line); m_impl.init(id, filename, line);
policy().init(m_impl, id, filename, line); policy().init(m_impl, id, filename, line);
ut_d(policy().context.init(id));
} }
/** Free resources (if any) */ /** Free resources (if any) */
...@@ -672,6 +672,7 @@ struct PolicyMutex ...@@ -672,6 +672,7 @@ struct PolicyMutex
#endif /* UNIV_PFS_MUTEX */ #endif /* UNIV_PFS_MUTEX */
m_impl.destroy(); m_impl.destroy();
policy().destroy(); policy().destroy();
ut_d(policy().context.destroy());
} }
/** Required for os_event_t */ /** Required for os_event_t */
......
This diff is collapsed.
/*****************************************************************************
Copyright (c) 2013, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
/******************************************************************//**
@file include/sync0policy.ic
Policy for mutexes.
Created 2012-08-21 Sunny Bains.
***********************************************************************/
#include "sync0debug.h"
template <typename Mutex>
std::string GenericPolicy<Mutex>::to_string() const
{
return(sync_mutex_to_string(get_id(), sync_file_created_get(this)));
}
template <typename Mutex>
std::string BlockMutexPolicy<Mutex>::to_string() const
{
/* I don't think it makes sense to keep track of the file name
and line number for each block mutex. Too much of overhead. Use the
latch id to figure out the location from the source. */
return(sync_mutex_to_string(get_id(), "buf0buf.cc:0"));
}
#ifdef UNIV_DEBUG
template <typename Mutex>
void MutexDebug<Mutex>::init(latch_id_t id)
UNIV_NOTHROW
{
m_context.m_id = id;
m_context.release();
m_magic_n = MUTEX_MAGIC_N;
}
template <typename Mutex>
void MutexDebug<Mutex>::enter(
const Mutex* mutex,
const char* name,
unsigned line)
UNIV_NOTHROW
{
ut_ad(!is_owned());
Context context(m_context.get_id());
context.locked(mutex, name, line);
/* Check for latch order violation. */
sync_check_lock_validate(&context);
}
template <typename Mutex>
void MutexDebug<Mutex>::locked(
const Mutex* mutex,
const char* name,
unsigned line)
UNIV_NOTHROW
{
ut_ad(!is_owned());
ut_ad(m_context.m_thread_id == ULINT_UNDEFINED);
m_context.locked(mutex, name, line);
sync_check_lock_granted(&m_context);
}
template <typename Mutex>
void MutexDebug<Mutex>::release(const Mutex*)
UNIV_NOTHROW
{
ut_ad(is_owned());
m_context.release();
sync_check_unlock(&m_context);
}
#endif /* UNIV_DEBUG */
...@@ -642,7 +642,6 @@ struct rw_lock_t ...@@ -642,7 +642,6 @@ struct rw_lock_t
} }
virtual std::string to_string() const; virtual std::string to_string() const;
virtual std::string locked_from() const;
/** For checking memory corruption. */ /** For checking memory corruption. */
ulint magic_n; ulint magic_n;
......
...@@ -999,9 +999,6 @@ struct latch_t { ...@@ -999,9 +999,6 @@ struct latch_t {
@return the string representation */ @return the string representation */
virtual std::string to_string() const = 0; virtual std::string to_string() const = 0;
/** @return "filename:line" from where the latch was last locked */
virtual std::string locked_from() const = 0;
/** @return the latch level */ /** @return the latch level */
latch_level_t get_level() const latch_level_t get_level() const
UNIV_NOTHROW UNIV_NOTHROW
...@@ -1117,33 +1114,6 @@ enum rw_lock_flag_t { ...@@ -1117,33 +1114,6 @@ enum rw_lock_flag_t {
#endif /* UNIV_INNOCHECKSUM */ #endif /* UNIV_INNOCHECKSUM */
static inline ulint my_atomic_loadlint(const ulint *A)
{
#ifdef _WIN64
return ulint(my_atomic_load64((volatile int64*)A));
#else
return ulint(my_atomic_loadlong(A));
#endif
}
static inline lint my_atomic_loadlint(const lint *A)
{
#ifdef _WIN64
return lint(my_atomic_load64((volatile int64*)A));
#else
return my_atomic_loadlong(A);
#endif
}
static inline void my_atomic_storelint(ulint *A, ulint B)
{
#ifdef _WIN64
my_atomic_store64((volatile int64*)A, B);
#else
my_atomic_storelong(A, B);
#endif
}
/** Simple non-atomic counter aligned to CACHE_LINE_SIZE /** Simple non-atomic counter aligned to CACHE_LINE_SIZE
@tparam Type the integer type of the counter */ @tparam Type the integer type of the counter */
template <typename Type> template <typename Type>
......
...@@ -38,8 +38,6 @@ Created 2012-03-24 Sunny Bains. ...@@ -38,8 +38,6 @@ Created 2012-03-24 Sunny Bains.
@param[in] T The resulting typedef alias */ @param[in] T The resulting typedef alias */
#define UT_MUTEX_TYPE(M, P, T) typedef PolicyMutex<M<P> > T; #define UT_MUTEX_TYPE(M, P, T) typedef PolicyMutex<M<P> > T;
typedef OSMutex EventMutex;
# ifdef HAVE_IB_LINUX_FUTEX # ifdef HAVE_IB_LINUX_FUTEX
UT_MUTEX_TYPE(TTASFutexMutex, GenericPolicy, FutexMutex); UT_MUTEX_TYPE(TTASFutexMutex, GenericPolicy, FutexMutex);
UT_MUTEX_TYPE(TTASFutexMutex, BlockMutexPolicy, BlockFutexMutex); UT_MUTEX_TYPE(TTASFutexMutex, BlockMutexPolicy, BlockFutexMutex);
......
...@@ -219,7 +219,7 @@ struct os_event { ...@@ -219,7 +219,7 @@ struct os_event {
int64_t signal_count; /*!< this is incremented int64_t signal_count; /*!< this is incremented
each time the event becomes each time the event becomes
signaled */ signaled */
mutable EventMutex mutex; /*!< this mutex protects mutable OSMutex mutex; /*!< this mutex protects
the next fields */ the next fields */
......
...@@ -497,10 +497,6 @@ UNIV_INTERN ulong srv_buf_dump_status_frequency; ...@@ -497,10 +497,6 @@ UNIV_INTERN ulong srv_buf_dump_status_frequency;
mutex_enter(&srv_sys.mutex); \ mutex_enter(&srv_sys.mutex); \
} while (0) } while (0)
/** Test if the system mutex is owned. */
#define srv_sys_mutex_own() (mutex_own(&srv_sys.mutex) \
&& !srv_read_only_mode)
/** Release the system mutex. */ /** Release the system mutex. */
#define srv_sys_mutex_exit() do { \ #define srv_sys_mutex_exit() do { \
mutex_exit(&srv_sys.mutex); \ mutex_exit(&srv_sys.mutex); \
...@@ -829,7 +825,7 @@ srv_suspend_thread_low( ...@@ -829,7 +825,7 @@ srv_suspend_thread_low(
srv_slot_t* slot) /*!< in/out: thread slot */ srv_slot_t* slot) /*!< in/out: thread slot */
{ {
ut_ad(!srv_read_only_mode); ut_ad(!srv_read_only_mode);
ut_ad(srv_sys_mutex_own()); ut_ad(mutex_own(&srv_sys.mutex));
ut_ad(slot->in_use); ut_ad(slot->in_use);
...@@ -1907,7 +1903,7 @@ void ...@@ -1907,7 +1903,7 @@ void
srv_active_wake_master_thread_low() srv_active_wake_master_thread_low()
{ {
ut_ad(!srv_read_only_mode); ut_ad(!srv_read_only_mode);
ut_ad(!srv_sys_mutex_own()); ut_ad(!mutex_own(&srv_sys.mutex));
srv_inc_activity_count(); srv_inc_activity_count();
...@@ -1933,7 +1929,8 @@ srv_active_wake_master_thread_low() ...@@ -1933,7 +1929,8 @@ srv_active_wake_master_thread_low()
void void
srv_wake_purge_thread_if_not_active() srv_wake_purge_thread_if_not_active()
{ {
ut_ad(!srv_sys_mutex_own()); ut_ad(!srv_read_only_mode);
ut_ad(!mutex_own(&srv_sys.mutex));
if (purge_sys.enabled() && !purge_sys.paused() if (purge_sys.enabled() && !purge_sys.paused()
&& !srv_sys.n_threads_active[SRV_PURGE] && !srv_sys.n_threads_active[SRV_PURGE]
......
...@@ -76,8 +76,8 @@ keep the global wait array for the sake of diagnostics and also to avoid ...@@ -76,8 +76,8 @@ keep the global wait array for the sake of diagnostics and also to avoid
infinite wait The error_monitor thread scans the global wait array to signal infinite wait The error_monitor thread scans the global wait array to signal
any waiting threads who have missed the signal. */ any waiting threads who have missed the signal. */
typedef SyncArrayMutex::MutexType WaitMutex; typedef TTASEventMutex<GenericPolicy> WaitMutex;
typedef BlockSyncArrayMutex::MutexType BlockWaitMutex; typedef TTASEventMutex<BlockMutexPolicy> BlockWaitMutex;
/** The latch types that use the sync array. */ /** The latch types that use the sync array. */
union sync_object_t { union sync_object_t {
...@@ -499,7 +499,7 @@ sync_array_cell_print( ...@@ -499,7 +499,7 @@ sync_array_cell_print(
WaitMutex* mutex = cell->latch.mutex; WaitMutex* mutex = cell->latch.mutex;
const WaitMutex::MutexPolicy& policy = mutex->policy(); const WaitMutex::MutexPolicy& policy = mutex->policy();
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
const char* name = policy.get_enter_filename(); const char* name = policy.context.get_enter_filename();
if (name == NULL) { if (name == NULL) {
/* The mutex might have been released. */ /* The mutex might have been released. */
name = "NULL"; name = "NULL";
...@@ -518,7 +518,7 @@ sync_array_cell_print( ...@@ -518,7 +518,7 @@ sync_array_cell_print(
mutex->state() mutex->state()
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
,name, ,name,
policy.get_enter_line() policy.context.get_enter_line()
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
); );
} }
...@@ -528,7 +528,7 @@ sync_array_cell_print( ...@@ -528,7 +528,7 @@ sync_array_cell_print(
const BlockWaitMutex::MutexPolicy& policy = const BlockWaitMutex::MutexPolicy& policy =
mutex->policy(); mutex->policy();
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
const char* name = policy.get_enter_filename(); const char* name = policy.context.get_enter_filename();
if (name == NULL) { if (name == NULL) {
/* The mutex might have been released. */ /* The mutex might have been released. */
name = "NULL"; name = "NULL";
...@@ -546,7 +546,7 @@ sync_array_cell_print( ...@@ -546,7 +546,7 @@ sync_array_cell_print(
(ulong) mutex->state() (ulong) mutex->state()
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
,name, ,name,
(ulong) policy.get_enter_line() (ulong) policy.context.get_enter_line()
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
); );
} else if (type == RW_LOCK_X } else if (type == RW_LOCK_X
...@@ -738,7 +738,7 @@ sync_array_detect_deadlock( ...@@ -738,7 +738,7 @@ sync_array_detect_deadlock(
const WaitMutex::MutexPolicy& policy = mutex->policy(); const WaitMutex::MutexPolicy& policy = mutex->policy();
if (mutex->state() != MUTEX_STATE_UNLOCKED) { if (mutex->state() != MUTEX_STATE_UNLOCKED) {
thread = policy.get_thread_id(); thread = policy.context.get_thread_id();
/* Note that mutex->thread_id above may be /* Note that mutex->thread_id above may be
also OS_THREAD_ID_UNDEFINED, because the also OS_THREAD_ID_UNDEFINED, because the
...@@ -753,7 +753,7 @@ sync_array_detect_deadlock( ...@@ -753,7 +753,7 @@ sync_array_detect_deadlock(
if (ret) { if (ret) {
const char* name; const char* name;
name = policy.get_enter_filename(); name = policy.context.get_enter_filename();
if (name == NULL) { if (name == NULL) {
/* The mutex might have been /* The mutex might have been
...@@ -765,7 +765,7 @@ sync_array_detect_deadlock( ...@@ -765,7 +765,7 @@ sync_array_detect_deadlock(
<< "Mutex " << mutex << " owned by" << "Mutex " << mutex << " owned by"
" thread " << os_thread_pf(thread) " thread " << os_thread_pf(thread)
<< " file " << name << " line " << " file " << name << " line "
<< policy.get_enter_line(); << policy.context.get_enter_line();
sync_array_cell_print(stderr, cell); sync_array_cell_print(stderr, cell);
...@@ -785,7 +785,7 @@ sync_array_detect_deadlock( ...@@ -785,7 +785,7 @@ sync_array_detect_deadlock(
mutex->policy(); mutex->policy();
if (mutex->state() != MUTEX_STATE_UNLOCKED) { if (mutex->state() != MUTEX_STATE_UNLOCKED) {
thread = policy.get_thread_id(); thread = policy.context.get_thread_id();
/* Note that mutex->thread_id above may be /* Note that mutex->thread_id above may be
also OS_THREAD_ID_UNDEFINED, because the also OS_THREAD_ID_UNDEFINED, because the
...@@ -800,7 +800,7 @@ sync_array_detect_deadlock( ...@@ -800,7 +800,7 @@ sync_array_detect_deadlock(
if (ret) { if (ret) {
const char* name; const char* name;
name = policy.get_enter_filename(); name = policy.context.get_enter_filename();
if (name == NULL) { if (name == NULL) {
/* The mutex might have been /* The mutex might have been
...@@ -812,7 +812,7 @@ sync_array_detect_deadlock( ...@@ -812,7 +812,7 @@ sync_array_detect_deadlock(
<< "Mutex " << mutex << " owned by" << "Mutex " << mutex << " owned by"
" thread " << os_thread_pf(thread) " thread " << os_thread_pf(thread)
<< " file " << name << " line " << " file " << name << " line "
<< policy.get_enter_line(); << policy.context.get_enter_line();
return(true); return(true);
......
...@@ -1156,10 +1156,10 @@ rw_lock_debug_print( ...@@ -1156,10 +1156,10 @@ rw_lock_debug_print(
fprintf(f, "\n"); fprintf(f, "\n");
} }
/** Print where it was locked from /** Print the rw-lock information.
@return the string representation */ @return the string representation */
std::string std::string
rw_lock_t::locked_from() const rw_lock_t::to_string() const
{ {
/* Note: For X locks it can be locked form multiple places because /* Note: For X locks it can be locked form multiple places because
the same thread can call X lock recursively. */ the same thread can call X lock recursively. */
...@@ -1169,6 +1169,11 @@ rw_lock_t::locked_from() const ...@@ -1169,6 +1169,11 @@ rw_lock_t::locked_from() const
ut_ad(rw_lock_validate(this)); ut_ad(rw_lock_validate(this));
msg << "RW-LATCH: "
<< "thread id " << os_thread_pf(os_thread_get_curr_id())
<< " addr: " << this
<< " Locked from: ";
rw_lock_debug_mutex_enter(); rw_lock_debug_mutex_enter();
for (rw_lock_debug_t* info = UT_LIST_GET_FIRST(debug_list); for (rw_lock_debug_t* info = UT_LIST_GET_FIRST(debug_list);
...@@ -1191,19 +1196,4 @@ rw_lock_t::locked_from() const ...@@ -1191,19 +1196,4 @@ rw_lock_t::locked_from() const
return(msg.str()); return(msg.str());
} }
/** Print the rw-lock information.
@return the string representation */
std::string
rw_lock_t::to_string() const
{
std::ostringstream msg;
msg << "RW-LATCH: "
<< "thread id " << os_thread_pf(os_thread_get_curr_id())
<< " addr: " << this
<< " Locked from: " << locked_from().c_str();
return(msg.str());
}
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
...@@ -1458,7 +1458,9 @@ trx_commit_in_memory( ...@@ -1458,7 +1458,9 @@ trx_commit_in_memory(
trx_mutex_exit(trx); trx_mutex_exit(trx);
ut_a(trx->error_state == DB_SUCCESS); ut_a(trx->error_state == DB_SUCCESS);
srv_wake_purge_thread_if_not_active(); if (!srv_read_only_mode) {
srv_wake_purge_thread_if_not_active();
}
} }
/** Commit a transaction and a mini-transaction. /** Commit a transaction and a mini-transaction.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment