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.
#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 @@ struct OSTrackMutex {
#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;
......@@ -264,7 +264,7 @@ struct TTASFutexMutex {
#endif /* HAVE_IB_LINUX_FUTEX */
template <template <typename> class Policy = NoPolicy>
template <template <typename> class Policy>
struct TTASMutex {
typedef Policy<TTASMutex> MutexPolicy;
......@@ -364,7 +364,7 @@ struct TTASMutex {
std::atomic<uint32_t> m_lock_word;
};
template <template <typename> class Policy = NoPolicy>
template <template <typename> class Policy>
struct TTASEventMutex {
typedef Policy<TTASEventMutex> MutexPolicy;
......@@ -534,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()
......@@ -565,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();
}
......@@ -591,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 */
......@@ -624,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
......@@ -640,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 */
......@@ -662,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) */
......@@ -672,6 +672,7 @@ struct PolicyMutex
#endif /* UNIV_PFS_MUTEX */
m_impl.destroy();
policy().destroy();
ut_d(policy().context.destroy());
}
/** 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
}
virtual std::string to_string() const;
virtual std::string locked_from() const;
/** For checking memory corruption. */
ulint magic_n;
......
......@@ -999,9 +999,6 @@ struct latch_t {
@return the string representation */
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 */
latch_level_t get_level() const
UNIV_NOTHROW
......@@ -1117,33 +1114,6 @@ enum rw_lock_flag_t {
#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
@tparam Type the integer type of the counter */
template <typename Type>
......
......@@ -38,8 +38,6 @@ Created 2012-03-24 Sunny Bains.
@param[in] T The resulting typedef alias */
#define UT_MUTEX_TYPE(M, P, T) typedef PolicyMutex<M<P> > T;
typedef OSMutex EventMutex;
# ifdef HAVE_IB_LINUX_FUTEX
UT_MUTEX_TYPE(TTASFutexMutex, GenericPolicy, FutexMutex);
UT_MUTEX_TYPE(TTASFutexMutex, BlockMutexPolicy, BlockFutexMutex);
......
......@@ -219,7 +219,7 @@ struct os_event {
int64_t signal_count; /*!< this is incremented
each time the event becomes
signaled */
mutable EventMutex mutex; /*!< this mutex protects
mutable OSMutex mutex; /*!< this mutex protects
the next fields */
......
......@@ -497,10 +497,6 @@ UNIV_INTERN ulong srv_buf_dump_status_frequency;
mutex_enter(&srv_sys.mutex); \
} 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. */
#define srv_sys_mutex_exit() do { \
mutex_exit(&srv_sys.mutex); \
......@@ -829,7 +825,7 @@ srv_suspend_thread_low(
srv_slot_t* slot) /*!< in/out: thread slot */
{
ut_ad(!srv_read_only_mode);
ut_ad(srv_sys_mutex_own());
ut_ad(mutex_own(&srv_sys.mutex));
ut_ad(slot->in_use);
......@@ -1907,7 +1903,7 @@ void
srv_active_wake_master_thread_low()
{
ut_ad(!srv_read_only_mode);
ut_ad(!srv_sys_mutex_own());
ut_ad(!mutex_own(&srv_sys.mutex));
srv_inc_activity_count();
......@@ -1933,7 +1929,8 @@ srv_active_wake_master_thread_low()
void
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()
&& !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
infinite wait The error_monitor thread scans the global wait array to signal
any waiting threads who have missed the signal. */
typedef SyncArrayMutex::MutexType WaitMutex;
typedef BlockSyncArrayMutex::MutexType BlockWaitMutex;
typedef TTASEventMutex<GenericPolicy> WaitMutex;
typedef TTASEventMutex<BlockMutexPolicy> BlockWaitMutex;
/** The latch types that use the sync array. */
union sync_object_t {
......@@ -499,7 +499,7 @@ sync_array_cell_print(
WaitMutex* mutex = cell->latch.mutex;
const WaitMutex::MutexPolicy& policy = mutex->policy();
#ifdef UNIV_DEBUG
const char* name = policy.get_enter_filename();
const char* name = policy.context.get_enter_filename();
if (name == NULL) {
/* The mutex might have been released. */
name = "NULL";
......@@ -518,7 +518,7 @@ sync_array_cell_print(
mutex->state()
#ifdef UNIV_DEBUG
,name,
policy.get_enter_line()
policy.context.get_enter_line()
#endif /* UNIV_DEBUG */
);
}
......@@ -528,7 +528,7 @@ sync_array_cell_print(
const BlockWaitMutex::MutexPolicy& policy =
mutex->policy();
#ifdef UNIV_DEBUG
const char* name = policy.get_enter_filename();
const char* name = policy.context.get_enter_filename();
if (name == NULL) {
/* The mutex might have been released. */
name = "NULL";
......@@ -546,7 +546,7 @@ sync_array_cell_print(
(ulong) mutex->state()
#ifdef UNIV_DEBUG
,name,
(ulong) policy.get_enter_line()
(ulong) policy.context.get_enter_line()
#endif /* UNIV_DEBUG */
);
} else if (type == RW_LOCK_X
......@@ -738,7 +738,7 @@ sync_array_detect_deadlock(
const WaitMutex::MutexPolicy& policy = mutex->policy();
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
also OS_THREAD_ID_UNDEFINED, because the
......@@ -753,7 +753,7 @@ sync_array_detect_deadlock(
if (ret) {
const char* name;
name = policy.get_enter_filename();
name = policy.context.get_enter_filename();
if (name == NULL) {
/* The mutex might have been
......@@ -765,7 +765,7 @@ sync_array_detect_deadlock(
<< "Mutex " << mutex << " owned by"
" thread " << os_thread_pf(thread)
<< " file " << name << " line "
<< policy.get_enter_line();
<< policy.context.get_enter_line();
sync_array_cell_print(stderr, cell);
......@@ -785,7 +785,7 @@ sync_array_detect_deadlock(
mutex->policy();
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
also OS_THREAD_ID_UNDEFINED, because the
......@@ -800,7 +800,7 @@ sync_array_detect_deadlock(
if (ret) {
const char* name;
name = policy.get_enter_filename();
name = policy.context.get_enter_filename();
if (name == NULL) {
/* The mutex might have been
......@@ -812,7 +812,7 @@ sync_array_detect_deadlock(
<< "Mutex " << mutex << " owned by"
" thread " << os_thread_pf(thread)
<< " file " << name << " line "
<< policy.get_enter_line();
<< policy.context.get_enter_line();
return(true);
......
......@@ -1156,10 +1156,10 @@ rw_lock_debug_print(
fprintf(f, "\n");
}
/** Print where it was locked from
/** Print the rw-lock information.
@return the string representation */
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
the same thread can call X lock recursively. */
......@@ -1169,6 +1169,11 @@ rw_lock_t::locked_from() const
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();
for (rw_lock_debug_t* info = UT_LIST_GET_FIRST(debug_list);
......@@ -1191,19 +1196,4 @@ rw_lock_t::locked_from() const
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 */
......@@ -1458,7 +1458,9 @@ trx_commit_in_memory(
trx_mutex_exit(trx);
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.
......
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