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 */
......
...@@ -30,247 +30,176 @@ Created 2012-08-21 Sunny Bains. ...@@ -30,247 +30,176 @@ Created 2012-08-21 Sunny Bains.
#include "ut0rnd.h" #include "ut0rnd.h"
#include "os0thread.h" #include "os0thread.h"
#include "srv0mon.h" #include "srv0mon.h"
#include "sync0debug.h"
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
# define MUTEX_MAGIC_N 979585UL template <typename Mutex> class MutexDebug: public latch_t
{
template <typename Mutex> /** Mutex to check for lock order violation */
class MutexDebug { const Mutex *m_mutex;
public: /** Filename from where enter was called */
const char *m_filename;
/** Line mumber in filename */
unsigned m_line;
/** Thread ID of the thread that owns the mutex */
os_thread_id_t m_thread_id;
/** Mutex protecting the above members */
mutable OSMutex m_debug_mutex;
/** For passing context to SyncDebug */
struct Context : public latch_t {
/** Constructor */ void set(const Mutex *mutex, const char *filename, unsigned line,
Context() os_thread_id_t thread_id)
:
m_mutex(),
m_filename(),
m_line(),
m_thread_id(ULINT_UNDEFINED)
{ {
/* No op */ m_debug_mutex.enter();
m_mutex= mutex;
m_filename= filename;
m_line= line;
m_thread_id= thread_id;
m_debug_mutex.exit();
} }
/** Create the context for SyncDebug
@param[in] id ID of the latch to track */
Context(latch_id_t id)
:
latch_t(id)
{
ut_ad(id != LATCH_ID_NONE);
}
/** Set to locked state const MutexDebug get() const
@param[in] mutex The mutex to acquire
@param[in] filename File name from where to acquire
@param[in] line Line number in filename */
void locked(
const Mutex* mutex,
const char* filename,
unsigned line)
UNIV_NOTHROW
{ {
m_mutex = mutex; MutexDebug ret;
m_debug_mutex.enter();
my_atomic_storelint(&m_thread_id, ret.m_mutex= m_mutex;
ulint(os_thread_get_curr_id())); ret.m_filename= m_filename;
ret.m_line= m_line;
m_filename = filename; ret.m_thread_id= m_thread_id;
m_debug_mutex.exit();
m_line = line; return ret;
} }
/** Reset to unlock state */
void release()
UNIV_NOTHROW
{
m_mutex = NULL;
my_atomic_storelint(&m_thread_id, ULINT_UNDEFINED);
m_filename = NULL; /**
Called either when mutex is locked or destroyed. Thus members are protected
m_line = 0; from concurrent modification.
} */
void assert_clean_context()
/** Print information about the latch
@return the string representation */
virtual std::string to_string() const
UNIV_NOTHROW
{ {
std::ostringstream msg; ut_ad(!m_mutex);
ut_ad(!m_filename);
msg << m_mutex->policy().to_string(); ut_ad(!m_line);
ut_ad(m_thread_id == os_thread_id_t(ULINT_UNDEFINED));
if (m_thread_id != ULINT_UNDEFINED) {
msg << " addr: " << m_mutex
<< " acquired: " << locked_from().c_str();
} else {
msg << "Not locked";
} }
return(msg.str());
}
/** @return the name of the file and line number in the file
from where the mutex was acquired "filename:line" */
virtual std::string locked_from() const
{
std::ostringstream msg;
msg << sync_basename(m_filename) << ":" << m_line;
return(std::string(msg.str())); public:
} /**
Called when the mutex is "created". Note: Not from the constructor
/** Mutex to check for lock order violation */ but when the mutex is initialised.
const Mutex* m_mutex; @param[in] id Mutex ID
*/
/** Filename from where enter was called */ void init(latch_id_t id)
const char* m_filename;
/** Line mumber in filename */
unsigned m_line;
/** Thread ID of the thread that own(ed) the mutex */
ulint m_thread_id;
};
/** Constructor. */
MutexDebug()
:
m_magic_n(),
m_context()
UNIV_NOTHROW
{ {
/* No op */ ut_ad(id != LATCH_ID_NONE);
m_id= id;
m_debug_mutex.init();
set(0, 0, 0, os_thread_id_t(ULINT_UNDEFINED));
} }
/* Destructor */
virtual ~MutexDebug() { }
/** Mutex is being destroyed. */ /** Mutex is being destroyed. */
void destroy() UNIV_NOTHROW void destroy()
{ {
ut_ad((ulint)my_atomic_loadlint(&m_context.m_thread_id) == ULINT_UNDEFINED); assert_clean_context();
m_debug_mutex.destroy();
m_magic_n = 0;
m_context.m_thread_id = 0;
} }
/** Called when the mutex is "created". Note: Not from the constructor
but when the mutex is initialised.
@param[in] id Mutex ID */
void init(latch_id_t id) UNIV_NOTHROW;
/** Called when an attempt is made to lock the mutex /**
Called when an attempt is made to lock the mutex
@param[in] mutex Mutex instance to be locked @param[in] mutex Mutex instance to be locked
@param[in] filename Filename from where it was called @param[in] filename Filename from where it was called
@param[in] line Line number from where it was called */ @param[in] line Line number from where it was called
void enter( */
const Mutex* mutex, void enter(const Mutex &mutex, const char *filename, unsigned line)
const char* filename, {
unsigned line) MutexDebug context;
UNIV_NOTHROW; ut_ad(!is_owned());
context.init(m_id);
context.set(&mutex, filename, line, os_thread_get_curr_id());
/* Check for latch order violation. */
sync_check_lock_validate(&context);
context.set(0, 0, 0, os_thread_id_t(ULINT_UNDEFINED));
context.destroy();
}
/** Called when the mutex is locked /**
Called when the mutex is locked
@param[in] mutex Mutex instance that was locked @param[in] mutex Mutex instance that was locked
@param[in] filename Filename from where it was called @param[in] filename Filename from where it was called
@param[in] line Line number from where it was called */ @param[in] line Line number from where it was called
void locked( */
const Mutex* mutex, void locked(const Mutex &mutex, const char *filename, unsigned line)
const char* filename, {
unsigned line) assert_clean_context();
UNIV_NOTHROW; set(&mutex, filename, line, os_thread_get_curr_id());
sync_check_lock_granted(this);
}
/** Called when the mutex is released
@param[in] mutx Mutex that was released */
void release(const Mutex* mutex)
UNIV_NOTHROW;
/** @return true if thread owns the mutex */ /**
bool is_owned() const UNIV_NOTHROW Called when the mutex is released
@param[in] mutex Mutex that was released
*/
void release(const Mutex &mutex)
{ {
return(os_thread_eq( ut_ad(is_owned());
(os_thread_id_t)my_atomic_loadlint(&m_context.m_thread_id), set(0, 0, 0, os_thread_id_t(ULINT_UNDEFINED));
os_thread_get_curr_id())); sync_check_unlock(this);
} }
/** @return the name of the file from the mutex was acquired */
const char* get_enter_filename() const /** @return true if thread owns the mutex */
UNIV_NOTHROW bool is_owned() const
{ {
return(m_context.m_filename); return os_thread_eq(get_thread_id(), os_thread_get_curr_id());
} }
/** @return the name of the file from the mutex was acquired */ /** @return the name of the file from the mutex was acquired */
unsigned get_enter_line() const const char* get_enter_filename() const { return get().m_filename; }
UNIV_NOTHROW
{
return(m_context.m_line); /** @return the name of the file from the mutex was acquired */
} unsigned get_enter_line() const { return get().m_line; }
/** @return id of the thread that was trying to acquire the mutex */ /** @return id of the thread that was trying to acquire the mutex */
os_thread_id_t get_thread_id() const os_thread_id_t get_thread_id() const { return get().m_thread_id; }
UNIV_NOTHROW
/**
Print information about the latch
@return the string representation
*/
virtual std::string to_string() const
{ {
return((os_thread_id_t)my_atomic_loadlint(&m_context.m_thread_id)); std::ostringstream msg;
} const MutexDebug ctx= get();
/** Magic number to check for memory corruption. */ msg << m_mutex->policy().to_string();
ulint m_magic_n; if (ctx.m_mutex)
msg << " addr: " << ctx.m_mutex << " acquired: "
<< sync_basename(ctx.get_enter_filename()) << ":"
<< ctx.get_enter_line();
else
msg << "Not locked";
/** Latch state of the mutex owner */ return(msg.str());
Context m_context; }
}; };
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
/* Do nothing */
template <typename Mutex>
struct NoPolicy {
/** Default constructor. */
NoPolicy() { }
void init(const Mutex&, latch_id_t, const char*, uint32_t)
UNIV_NOTHROW { }
void destroy() UNIV_NOTHROW { }
void enter(const Mutex&, const char*, unsigned) UNIV_NOTHROW { }
void add(uint32_t, uint32_t) UNIV_NOTHROW { }
void locked(const Mutex&, const char*, ulint) UNIV_NOTHROW { }
void release(const Mutex&) UNIV_NOTHROW { }
std::string to_string() const { return(""); };
latch_id_t get_id() const;
};
/** Collect the metrics per mutex instance, no aggregation. */ /** Collect the metrics per mutex instance, no aggregation. */
template <typename Mutex> template <typename Mutex>
struct GenericPolicy struct GenericPolicy
#ifdef UNIV_DEBUG
: public MutexDebug<Mutex>
#endif /* UNIV_DEBUG */
{ {
public: public:
typedef Mutex MutexType;
/** Constructor. */
GenericPolicy()
UNIV_NOTHROW
:
#ifdef UNIV_DEBUG
MutexDebug<MutexType>(),
#endif /* UNIV_DEBUG */
m_count(),
m_id()
{ }
/** Destructor */
~GenericPolicy() { }
/** Called when the mutex is "created". Note: Not from the constructor /** Called when the mutex is "created". Note: Not from the constructor
but when the mutex is initialised. but when the mutex is initialised.
@param[in] id Mutex ID @param[in] id Mutex ID
...@@ -292,8 +221,6 @@ struct GenericPolicy ...@@ -292,8 +221,6 @@ struct GenericPolicy
meta.get_counter()->single_register(&m_count); meta.get_counter()->single_register(&m_count);
sync_file_created_register(this, filename, uint16_t(line)); sync_file_created_register(this, filename, uint16_t(line));
ut_d(MutexDebug<MutexType>::init(m_id));
} }
/** Called when the mutex is destroyed. */ /** Called when the mutex is destroyed. */
...@@ -305,8 +232,6 @@ struct GenericPolicy ...@@ -305,8 +232,6 @@ struct GenericPolicy
meta.get_counter()->single_deregister(&m_count); meta.get_counter()->single_deregister(&m_count);
sync_file_created_deregister(this); sync_file_created_deregister(this);
ut_d(MutexDebug<MutexType>::destroy());
} }
/** Called after a successful mutex acquire. /** Called after a successful mutex acquire.
...@@ -332,40 +257,6 @@ struct GenericPolicy ...@@ -332,40 +257,6 @@ struct GenericPolicy
++m_count.m_calls; ++m_count.m_calls;
} }
/** Called when an attempt is made to lock the mutex
@param[in] mutex Mutex instance to be locked
@param[in] filename Filename from where it was called
@param[in] line Line number from where it was called */
void enter(
const MutexType& mutex,
const char* filename,
unsigned line)
UNIV_NOTHROW
{
ut_d(MutexDebug<MutexType>::enter(&mutex, filename, line));
}
/** Called when the mutex is locked
@param[in] mutex Mutex instance that is locked
@param[in] filename Filename from where it was called
@param[in] line Line number from where it was called */
void locked(
const MutexType& mutex,
const char* filename,
unsigned line)
UNIV_NOTHROW
{
ut_d(MutexDebug<MutexType>::locked(&mutex, filename, line));
}
/** Called when the mutex is released
@param[in] mutex Mutex instance that is released */
void release(const MutexType& mutex)
UNIV_NOTHROW
{
ut_d(MutexDebug<MutexType>::release(&mutex));
}
/** Print the information about the latch /** Print the information about the latch
@return the string representation */ @return the string representation */
std::string print() const std::string print() const
...@@ -378,14 +269,18 @@ struct GenericPolicy ...@@ -378,14 +269,18 @@ struct GenericPolicy
return(m_id); return(m_id);
} }
/** @return the string representation */ /** @return the string representation */
std::string to_string() const; std::string to_string() const
{ return sync_mutex_to_string(get_id(), sync_file_created_get(this)); }
private: #ifdef UNIV_DEBUG
typedef latch_meta_t::CounterType Counter; MutexDebug<Mutex> context;
#endif
private:
/** The user visible counters, registered with the meta-data. */ /** The user visible counters, registered with the meta-data. */
Counter::Count m_count; latch_meta_t::CounterType::Count m_count;
/** Latch meta data ID */ /** Latch meta data ID */
latch_id_t m_id; latch_id_t m_id;
...@@ -395,29 +290,8 @@ struct GenericPolicy ...@@ -395,29 +290,8 @@ struct GenericPolicy
too many of them to count individually. */ too many of them to count individually. */
template <typename Mutex> template <typename Mutex>
class BlockMutexPolicy class BlockMutexPolicy
#ifdef UNIV_DEBUG
: public MutexDebug<Mutex>
#endif /* UNIV_DEBUG */
{ {
public: public:
typedef Mutex MutexType;
typedef typename latch_meta_t::CounterType::Count Count;
/** Default constructor. */
BlockMutexPolicy()
:
#ifdef UNIV_DEBUG
MutexDebug<MutexType>(),
#endif /* UNIV_DEBUG */
m_count(),
m_id()
{
/* Do nothing */
}
/** Destructor */
~BlockMutexPolicy() { }
/** Called when the mutex is "created". Note: Not from the constructor /** Called when the mutex is "created". Note: Not from the constructor
but when the mutex is initialised. but when the mutex is initialised.
@param[in] id Mutex ID */ @param[in] id Mutex ID */
...@@ -436,8 +310,6 @@ class BlockMutexPolicy ...@@ -436,8 +310,6 @@ class BlockMutexPolicy
ut_ad(meta.get_id() == id); ut_ad(meta.get_id() == id);
m_count = meta.get_counter()->sum_register(); m_count = meta.get_counter()->sum_register();
ut_d(MutexDebug<MutexType>::init(m_id));
} }
/** Called when the mutex is destroyed. */ /** Called when the mutex is destroyed. */
...@@ -445,7 +317,6 @@ class BlockMutexPolicy ...@@ -445,7 +317,6 @@ class BlockMutexPolicy
UNIV_NOTHROW UNIV_NOTHROW
{ {
m_count = NULL; m_count = NULL;
ut_d(MutexDebug<MutexType>::destroy());
} }
/** Called after a successful mutex acquire. /** Called after a successful mutex acquire.
...@@ -469,40 +340,6 @@ class BlockMutexPolicy ...@@ -469,40 +340,6 @@ class BlockMutexPolicy
++m_count->m_calls; ++m_count->m_calls;
} }
/** Called when the mutex is locked
@param[in] mutex Mutex instance that is locked
@param[in] filename Filename from where it was called
@param[in] line Line number from where it was called */
void locked(
const MutexType& mutex,
const char* filename,
unsigned line)
UNIV_NOTHROW
{
ut_d(MutexDebug<MutexType>::locked(&mutex, filename, line));
}
/** Called when the mutex is released
@param[in] mutex Mutex instance that is released */
void release(const MutexType& mutex)
UNIV_NOTHROW
{
ut_d(MutexDebug<MutexType>::release(&mutex));
}
/** Called when an attempt is made to lock the mutex
@param[in] mutex Mutex instance to be locked
@param[in] filename Filename from where it was called
@param[in] line Line number from where it was called */
void enter(
const MutexType& mutex,
const char* filename,
unsigned line)
UNIV_NOTHROW
{
ut_d(MutexDebug<MutexType>::enter(&mutex, filename, line));
}
/** Print the information about the latch /** Print the information about the latch
@return the string representation */ @return the string representation */
std::string print() const std::string print() const
...@@ -514,19 +351,26 @@ class BlockMutexPolicy ...@@ -514,19 +351,26 @@ class BlockMutexPolicy
return(m_id); return(m_id);
} }
/** @return the string representation */
std::string to_string() const;
private: /**
typedef latch_meta_t::CounterType Counter; 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 the string representation
*/
std::string to_string() const
{ return(sync_mutex_to_string(get_id(), "buf0buf.cc:0")); }
#ifdef UNIV_DEBUG
MutexDebug<Mutex> context;
#endif
private:
/** The user visible counters, registered with the meta-data. */ /** The user visible counters, registered with the meta-data. */
Counter::Count* m_count; latch_meta_t::CounterType::Count *m_count;
/** Latch meta data ID */ /** Latch meta data ID */
latch_id_t m_id; latch_id_t m_id;
}; };
#include "sync0policy.ic"
#endif /* sync0policy_h */ #endif /* sync0policy_h */
/*****************************************************************************
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);
if (!srv_read_only_mode) {
srv_wake_purge_thread_if_not_active(); 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