diff options
Diffstat (limited to 'storage/innobase/include/sync0policy.h')
-rw-r--r-- | storage/innobase/include/sync0policy.h | 550 |
1 files changed, 550 insertions, 0 deletions
diff --git a/storage/innobase/include/sync0policy.h b/storage/innobase/include/sync0policy.h new file mode 100644 index 00000000000..0eaefc7167a --- /dev/null +++ b/storage/innobase/include/sync0policy.h @@ -0,0 +1,550 @@ +/***************************************************************************** + +Copyright (c) 2013, 2015, Oracle and/or its affiliates. All Rights Reserved. + +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.h +Policies for mutexes. + +Created 2012-08-21 Sunny Bains. +***********************************************************************/ + +#ifndef sync0policy_h +#define sync0policy_h + +#include "univ.i" +#include "ut0rnd.h" +#include "os0thread.h" +#include "sync0types.h" +#include "srv0mon.h" + +#ifdef UNIV_DEBUG + +# define MUTEX_MAGIC_N 979585UL + +template <typename Mutex> +class MutexDebug { +public: + + /** For passing context to SyncDebug */ + struct Context : public latch_t { + + /** Constructor */ + Context() + : + m_mutex(), + m_filename(), + m_line(), + m_thread_id(os_thread_id_t(ULINT_UNDEFINED)) + { + /* No op */ + } + + /** Create the context for SyncDebug + @param[in] id ID of the latch to track */ + Context(latch_id_t id) + : + latch_t(id) + { + /* No op */ + } + + /** Set to locked state + @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, + ulint line) + UNIV_NOTHROW + { + m_mutex = mutex; + + m_thread_id = os_thread_get_curr_id(); + + m_filename = filename; + + m_line = line; + } + + /** Reset to unlock state */ + void release() + UNIV_NOTHROW + { + m_mutex = NULL; + + m_thread_id = os_thread_id_t(ULINT_UNDEFINED); + + m_filename = NULL; + + m_line = ULINT_UNDEFINED; + } + + /** Print information about the latch + @return the string representation */ + virtual std::string to_string() const + UNIV_NOTHROW + { + std::ostringstream msg; + + msg << m_mutex->policy().to_string(); + + if (os_thread_pf(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())); + } + + /** Mutex to check for lock order violation */ + const Mutex* m_mutex; + + /** Filename from where enter was called */ + const char* m_filename; + + /** Line mumber in filename */ + ulint m_line; + + /** Thread ID of the thread that own(ed) the mutex */ + os_thread_id_t m_thread_id; + }; + + /** Constructor. */ + MutexDebug() + : + m_magic_n(), + m_context() + UNIV_NOTHROW + { + /* No op */ + } + + /* Destructor */ + virtual ~MutexDebug() { } + + /** Mutex is being destroyed. */ + void destroy() UNIV_NOTHROW + { + ut_ad(m_context.m_thread_id == os_thread_id_t(ULINT_UNDEFINED)); + + 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 + @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 Mutex* mutex, + const char* filename, + ulint line) + UNIV_NOTHROW; + + /** Called when the mutex is locked + @param[in] mutex Mutex instance that was locked + @param[in] filename Filename from where it was called + @param[in] line Line number from where it was called */ + void locked( + const Mutex* mutex, + const char* filename, + ulint line) + UNIV_NOTHROW; + + /** 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 + { + return(os_thread_eq( + m_context.m_thread_id, + os_thread_get_curr_id())); + } + + /** @return the name of the file from the mutex was acquired */ + const char* get_enter_filename() const + UNIV_NOTHROW + { + return(m_context.m_filename); + } + + /** @return the name of the file from the mutex was acquired */ + ulint get_enter_line() const + UNIV_NOTHROW + { + return(m_context.m_line); + } + + /** @return id of the thread that was trying to acquire the mutex */ + os_thread_id_t get_thread_id() const + UNIV_NOTHROW + { + return(m_context.m_thread_id); + } + + /** Magic number to check for memory corruption. */ + ulint m_magic_n; + + /** Latch state of the mutex owner */ + Context m_context; +}; +#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*, ulint line) 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. */ +template <typename Mutex> +struct GenericPolicy +#ifdef UNIV_DEBUG +: public MutexDebug<Mutex> +#endif /* UNIV_DEBUG */ +{ +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 + but when the mutex is initialised. + @param[in] mutex Mutex instance to track + @param[in] id Mutex ID + @param[in] filename File where mutex was created + @param[in] line Line in filename */ + void init( + const MutexType& mutex, + latch_id_t id, + const char* filename, + uint32_t line) + UNIV_NOTHROW + { + m_id = id; + + latch_meta_t& meta = sync_latch_get_meta(id); + + ut_ad(meta.get_id() == id); + + meta.get_counter()->single_register(&m_count); + + sync_file_created_register(this, filename, line); + + ut_d(MutexDebug<MutexType>::init(m_id)); + } + + /** Called when the mutex is destroyed. */ + void destroy() + UNIV_NOTHROW + { + latch_meta_t& meta = sync_latch_get_meta(m_id); + + meta.get_counter()->single_deregister(&m_count); + + sync_file_created_deregister(this); + + ut_d(MutexDebug<MutexType>::destroy()); + } + + /** Called after a successful mutex acquire. + @param[in] n_spins Number of times the thread did + spins while trying to acquire the mutex + @param[in] n_waits Number of times the thread waited + in some type of OS queue */ + void add( + uint32_t n_spins, + uint32_t n_waits) + UNIV_NOTHROW + { + /* Currently global on/off. Keeps things simple and fast */ + + if (!m_count.m_enabled) { + + return; + } + + m_count.m_spins += n_spins; + m_count.m_waits += n_waits; + + ++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, + ulint 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, + ulint 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 + @return the string representation */ + std::string print() const + UNIV_NOTHROW; + + /** @return the latch ID */ + latch_id_t get_id() const + UNIV_NOTHROW + { + return(m_id); + } + + /** @return the string representation */ + std::string to_string() const; + +private: + typedef latch_meta_t::CounterType Counter; + + /** The user visible counters, registered with the meta-data. */ + Counter::Count m_count; + + /** Latch meta data ID */ + latch_id_t m_id; +}; + +/** Track agregate metrics policy, used by the page mutex. There are just +too many of them to count individually. */ +template <typename Mutex> +class BlockMutexPolicy +#ifdef UNIV_DEBUG +: public MutexDebug<Mutex> +#endif /* UNIV_DEBUG */ +{ +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 + but when the mutex is initialised. + @param[in] mutex Mutex instance to track + @param[in] id Mutex ID + @param[in] filename File where mutex was created + @param[in] line Line in filename */ + void init( + const MutexType& mutex, + latch_id_t id, + const char* filename, + uint32_t line) + UNIV_NOTHROW + { + /* It can be LATCH_ID_BUF_BLOCK_MUTEX or + LATCH_ID_BUF_POOL_ZIP. Unfortunately, they + are mapped to the same mutex type in the + buffer pool code. */ + + m_id = id; + + latch_meta_t& meta = sync_latch_get_meta(m_id); + + ut_ad(meta.get_id() == id); + + m_count = meta.get_counter()->sum_register(); + + ut_d(MutexDebug<MutexType>::init(m_id)); + } + + /** Called when the mutex is destroyed. */ + void destroy() + UNIV_NOTHROW + { + latch_meta_t& meta = sync_latch_get_meta(m_id); + + ut_ad(meta.get_id() == m_id); + + meta.get_counter()->sum_deregister(m_count); + + m_count = NULL; + + ut_d(MutexDebug<MutexType>::destroy()); + } + + /** Called after a successful mutex acquire. + @param[in] n_spins Number of times the thread did + spins while trying to acquire the mutex + @param[in] n_waits Number of times the thread waited + in some type of OS queue */ + void add( + uint32_t n_spins, + uint32_t n_waits) + UNIV_NOTHROW + { + if (!m_count->m_enabled) { + + return; + } + + m_count->m_spins += n_spins; + m_count->m_waits += n_waits; + + ++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, + ulint 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, + ulint line) + UNIV_NOTHROW + { + ut_d(MutexDebug<MutexType>::enter(&mutex, filename, line)); + } + + /** Print the information about the latch + @return the string representation */ + std::string print() const + UNIV_NOTHROW; + + /** @return the latch ID */ + latch_id_t get_id() const + { + return(m_id); + } + + /** @return the string representation */ + std::string to_string() const; + +private: + typedef latch_meta_t::CounterType Counter; + + /** The user visible counters, registered with the meta-data. */ + Counter::Count* m_count; + + /** Latch meta data ID */ + latch_id_t m_id; +}; + +#ifndef UNIV_NONINL +#include "sync0policy.ic" +#endif /* UNIV_NOINL */ + +#endif /* sync0policy_h */ |