diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2020-12-04 19:02:58 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2020-12-15 17:56:18 +0200 |
commit | ff5d306e296350e7489dd3decb01bad18d135411 (patch) | |
tree | 64e8673307ede8bf633e94947ed84e3dcaaa5b05 /storage/innobase/include | |
parent | db006a9a43b6e68c4b92d2762043fa76b313623c (diff) | |
download | mariadb-git-ff5d306e296350e7489dd3decb01bad18d135411.tar.gz |
MDEV-21452: Replace ib_mutex_t with mysql_mutex_t
SHOW ENGINE INNODB MUTEX functionality is completely removed,
as are the InnoDB latching order checks.
We will enforce innodb_fatal_semaphore_wait_threshold
only for dict_sys.mutex and lock_sys.mutex.
dict_sys_t::mutex_lock(): A single entry point for dict_sys.mutex.
lock_sys_t::mutex_lock(): A single entry point for lock_sys.mutex.
FIXME: srv_sys should be removed altogether; it is duplicating tpool
functionality.
fil_crypt_threads_init(): To prevent SAFE_MUTEX warnings, we must
not hold fil_system.mutex.
fil_close_all_files(): To prevent SAFE_MUTEX warnings for
fil_space_destroy_crypt_data(), we must not hold fil_system.mutex
while invoking fil_space_free_low() on a detached tablespace.
Diffstat (limited to 'storage/innobase/include')
39 files changed, 278 insertions, 2423 deletions
diff --git a/storage/innobase/include/buf0types.h b/storage/innobase/include/buf0types.h index 7460c07a7d9..4fb93e75515 100644 --- a/storage/innobase/include/buf0types.h +++ b/storage/innobase/include/buf0types.h @@ -24,9 +24,7 @@ The database buffer pool global types for the directory Created 11/17/1995 Heikki Tuuri *******************************************************/ -#ifndef buf0types_h -#define buf0types_h - +#pragma once #include "univ.i" /** Buffer page (uncompressed or compressed) */ @@ -228,5 +226,3 @@ public: }; #endif /* !UNIV_INNOCHECKSUM */ - -#endif /* buf0types.h */ diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h index 17263fdd48a..024a8652a12 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -1312,9 +1312,6 @@ dict_index_calc_min_rec_len( const dict_index_t* index) /*!< in: index */ MY_ATTRIBUTE((nonnull, warn_unused_result)); -#define dict_mutex_enter_for_mysql() mutex_enter(&dict_sys.mutex) -#define dict_mutex_exit_for_mysql() mutex_exit(&dict_sys.mutex) - /********************************************************************//** Checks if the database name in two table names is the same. @return TRUE if same db name */ @@ -1378,13 +1375,14 @@ constraint */ /* Buffers for storing detailed information about the latest foreign key and unique key errors */ extern FILE* dict_foreign_err_file; -extern ib_mutex_t dict_foreign_err_mutex; /* mutex protecting the - foreign key error messages */ +extern mysql_mutex_t dict_foreign_err_mutex; /** InnoDB data dictionary cache */ class dict_sys_t { -private: + /** The my_hrtime_coarse().val of the oldest mutex_lock_wait() start, or 0 */ + std::atomic<ulonglong> mutex_wait_start; + /** @brief the data dictionary rw-latch protecting dict_sys Table create, drop, etc. reserve this in X-mode (along with @@ -1399,14 +1397,11 @@ private: /** whether latch is being held in exclusive mode (by any thread) */ bool latch_ex; #endif + /** Mutex protecting dict_sys. Whenever latch is acquired + exclusively, also the mutex will be acquired. + FIXME: merge the mutex and the latch, once MDEV-23484 has been fixed */ + mysql_mutex_t mutex; public: - DictSysMutex mutex; /*!< mutex protecting the data - dictionary; protects also the - disk-based dictionary system tables; - this mutex serializes CREATE TABLE - and DROP TABLE, as well as reading - the dictionary data for a table from - system tables */ hash_table_t table_hash; /*!< hash table of the tables, based on name */ /** hash table of persistent table IDs */ @@ -1437,6 +1432,9 @@ private: /** The synchronization interval of row_id */ static constexpr size_t ROW_ID_WRITE_MARGIN= 256; public: + /** Diagnostic message for exceeding the mutex_lock_wait() timeout */ + static const char fatal_msg[]; + /** @return A new value for GEN_CLUST_INDEX(DB_ROW_ID) */ inline row_id_t get_new_row_id(); @@ -1461,7 +1459,7 @@ public: (should only happen during the rollback of CREATE...SELECT) */ dict_table_t* get_temporary_table(table_id_t id) { - ut_ad(mutex_own(&mutex)); + mysql_mutex_assert_owner(&mutex); dict_table_t* table; ulint fold = ut_fold_ull(id); HASH_SEARCH(id_hash, &temp_id_hash, fold, dict_table_t*, table, @@ -1480,7 +1478,7 @@ public: @retval NULL if not cached */ dict_table_t* get_table(table_id_t id) { - ut_ad(mutex_own(&mutex)); + mysql_mutex_assert_owner(&mutex); dict_table_t* table; ulint fold = ut_fold_ull(id); HASH_SEARCH(id_hash, &table_id_hash, fold, dict_table_t*, @@ -1515,7 +1513,7 @@ public: { ut_ad(table); ut_ad(table->can_be_evicted == in_lru); - ut_ad(mutex_own(&mutex)); + mysql_mutex_assert_owner(&mutex); for (const dict_table_t* t = UT_LIST_GET_FIRST(in_lru ? table_LRU : table_non_LRU); t; t = UT_LIST_GET_NEXT(table_LRU, t)) @@ -1546,25 +1544,44 @@ public: /** Acquire a reference to a cached table. */ inline void acquire(dict_table_t* table); -#ifdef UNIV_DEBUG - /** Assert that the data dictionary is locked */ - void assert_locked() { ut_ad(mutex_own(&mutex)); } + /** Assert that the mutex is locked */ + void assert_locked() const { mysql_mutex_assert_owner(&mutex); } + /** Assert that the mutex is not locked */ + void assert_not_locked() const { mysql_mutex_assert_not_owner(&mutex); } +#ifdef SAFE_MUTEX + bool mutex_is_locked() const { return mysql_mutex_is_owner(&mutex); } #endif +private: + /** Acquire the mutex */ + ATTRIBUTE_NOINLINE void mutex_lock_wait(); +public: + /** @return the my_hrtime_coarse().val of the oldest mutex_lock_wait() start, + assuming that requests are served on a FIFO basis */ + ulonglong oldest_wait() const + { return mutex_wait_start.load(std::memory_order_relaxed); } + +#ifdef HAVE_PSI_MUTEX_INTERFACE + /** Acquire the mutex */ + ATTRIBUTE_NOINLINE void mutex_lock(); + /** Release the mutex */ + ATTRIBUTE_NOINLINE void mutex_unlock(); +#else + /** Acquire the mutex */ + void mutex_lock() { if (mysql_mutex_trylock(&mutex)) mutex_lock_wait(); } + + /** Release the mutex */ + void mutex_unlock() { mysql_mutex_unlock(&mutex); } +#endif + /** Lock the data dictionary cache. */ - void lock(const char* file, unsigned line) - { - latch.wr_lock(SRW_LOCK_ARGS(file, line)); - ut_ad(!latch_ex); - ut_d(latch_ex= true); - mutex_enter_loc(&mutex, file, line); - } + void lock(SRW_LOCK_ARGS(const char *file, unsigned line)); /** Unlock the data dictionary cache. */ void unlock() { ut_ad(latch_ex); ut_d(latch_ex= false); - mutex_exit(&mutex); + mutex_unlock(); latch.wr_unlock(); } @@ -1595,7 +1612,7 @@ public: extern dict_sys_t dict_sys; #define dict_table_prevent_eviction(table) dict_sys.prevent_eviction(table) -#define dict_sys_lock() dict_sys.lock(__FILE__, __LINE__) +#define dict_sys_lock() dict_sys.lock(SRW_LOCK_CALL) #define dict_sys_unlock() dict_sys.unlock() /* Auxiliary structs for checking a table definition @{ */ diff --git a/storage/innobase/include/dict0dict.ic b/storage/innobase/include/dict0dict.ic index f97c65d5bfc..a494eefdc32 100644 --- a/storage/innobase/include/dict0dict.ic +++ b/storage/innobase/include/dict0dict.ic @@ -1139,12 +1139,10 @@ dict_table_is_file_per_table( } /** Acquire the table handle. */ -inline -void -dict_table_t::acquire() +inline void dict_table_t::acquire() { - ut_ad(mutex_own(&dict_sys.mutex)); - n_ref_count++; + dict_sys.assert_locked(); + n_ref_count++; } /** Release the table handle. diff --git a/storage/innobase/include/dict0priv.ic b/storage/innobase/include/dict0priv.ic index 2fcadc055e1..36d0ba66524 100644 --- a/storage/innobase/include/dict0priv.ic +++ b/storage/innobase/include/dict0priv.ic @@ -39,7 +39,7 @@ dict_table_get_low( dict_table_t* table; ut_ad(table_name); - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); table = dict_table_check_if_in_cache_low(table_name); @@ -79,7 +79,7 @@ dict_table_check_if_in_cache_low( ("table: '%s'", table_name)); ut_ad(table_name); - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); /* Look for the table name in the hash table */ table_fold = ut_fold_string(table_name); diff --git a/storage/innobase/include/dict0stats.ic b/storage/innobase/include/dict0stats.ic index 4972efe8961..cfc3c0e7e21 100644 --- a/storage/innobase/include/dict0stats.ic +++ b/storage/innobase/include/dict0stats.ic @@ -148,7 +148,7 @@ dict_stats_init( /*============*/ dict_table_t* table) /*!< in/out: table */ { - ut_ad(!mutex_own(&dict_sys.mutex)); + dict_sys.assert_not_locked(); if (table->stat_initialized) { return; @@ -174,7 +174,7 @@ dict_stats_deinit( /*==============*/ dict_table_t* table) /*!< in/out: table */ { - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); ut_a(table->get_ref_count() == 0); diff --git a/storage/innobase/include/dict0stats_bg.h b/storage/innobase/include/dict0stats_bg.h index b210a2ec357..5abbdf7fd25 100644 --- a/storage/innobase/include/dict0stats_bg.h +++ b/storage/innobase/include/dict0stats_bg.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2012, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2019, MariaDB Corporation. +Copyright (c) 2017, 2020, 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 @@ -31,7 +31,7 @@ Created Apr 26, 2012 Vasil Dimov #include "os0thread.h" #ifdef HAVE_PSI_INTERFACE -extern mysql_pfs_key_t dict_stats_recalc_pool_mutex_key; +extern mysql_pfs_key_t recalc_pool_mutex_key; #endif /* HAVE_PSI_INTERFACE */ #ifdef UNIV_DEBUG @@ -67,7 +67,7 @@ dict_stats_stop_bg( dict_table_t* table) /*!< in/out: table */ { ut_ad(!srv_read_only_mode); - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); if (!(table->stats_bg_flag & BG_STAT_IN_PROGRESS)) { return(true); diff --git a/storage/innobase/include/dict0types.h b/storage/innobase/include/dict0types.h index d0da45ab218..6db0f3ba65b 100644 --- a/storage/innobase/include/dict0types.h +++ b/storage/innobase/include/dict0types.h @@ -27,7 +27,7 @@ Created 1/8/1996 Heikki Tuuri #ifndef dict0types_h #define dict0types_h -#include <ut0mutex.h> +#include "univ.i" #include <rem0types.h> struct dict_col_t; @@ -90,10 +90,6 @@ enum ib_quiesce_t { QUIESCE_COMPLETE /*!< All done */ }; -#ifndef UNIV_INNOCHECKSUM -typedef ib_mutex_t DictSysMutex; -#endif /* !UNIV_INNOCHECKSUM */ - /** Prefix for tmp tables, adopted from sql/table.h */ #define TEMP_FILE_PREFIX "#sql" #define TEMP_FILE_PREFIX_LENGTH 4 diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index d9f36479a44..a342e0e24bf 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -1415,7 +1415,8 @@ public: std::vector<pfs_os_file_t> detach(fil_space_t *space, bool detach_handle= false); - ib_mutex_t mutex; /*!< The mutex protecting the cache */ + /** the mutex protecting most data fields, and some fields of fil_space_t */ + mysql_mutex_t mutex; fil_space_t* sys_space; /*!< The innodb_system tablespace */ fil_space_t* temp_space; /*!< The innodb_temporary tablespace */ /** Map of fil_space_t::id to fil_space_t* */ @@ -1467,14 +1468,18 @@ extern fil_system_t fil_system; inline void fil_space_t::reacquire() { ut_d(uint32_t n=) n_pending.fetch_add(1, std::memory_order_relaxed); - ut_d(if (mutex_own(&fil_system.mutex)) return); +#ifdef SAFE_MUTEX + if (mysql_mutex_is_owner(&fil_system.mutex)) return; ut_ad(n & PENDING); ut_ad(UT_LIST_GET_FIRST(chain)->is_open()); +#endif /* SAFE_MUTEX */ } inline bool fil_space_t::acquire_if_not_stopped(bool have_mutex) { - ut_ad(mutex_own(&fil_system.mutex) == have_mutex); +#ifdef SAFE_MUTEX + ut_ad(mysql_mutex_is_owner(&fil_system.mutex) == have_mutex); +#endif const uint32_t n= acquire_low(); if (UNIV_LIKELY(!(n & (STOPPING | CLOSING)))) return true; @@ -1484,7 +1489,7 @@ inline bool fil_space_t::acquire_if_not_stopped(bool have_mutex) /** Note that operations on the tablespace must stop or can resume */ inline void fil_space_t::set_stopping(bool stopping) { - ut_ad(mutex_own(&fil_system.mutex)); + mysql_mutex_assert_owner(&fil_system.mutex); ut_d(auto n=) n_pending.fetch_xor(STOPPING, std::memory_order_relaxed); ut_ad(!(n & STOPPING) == stopping); } @@ -1492,7 +1497,7 @@ inline void fil_space_t::set_stopping(bool stopping) /** Flush pending writes from the file system cache to the file. */ template<bool have_reference> inline void fil_space_t::flush() { - ut_ad(!mutex_own(&fil_system.mutex)); + mysql_mutex_assert_not_owner(&fil_system.mutex); ut_ad(!have_reference || (pending() & PENDING)); ut_ad(purpose == FIL_TYPE_TABLESPACE || purpose == FIL_TYPE_IMPORT); if (srv_file_flush_method == SRV_O_DIRECT_NO_FSYNC) @@ -1514,9 +1519,9 @@ inline uint32_t fil_space_t::get_size() { if (!size) { - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); read_page0(); - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); } return size; } @@ -1789,11 +1794,6 @@ char* fil_path_to_space_name( const char* filename); -/** Acquire the fil_system mutex. */ -#define fil_system_enter() mutex_enter(&fil_system.mutex) -/** Release the fil_system mutex. */ -#define fil_system_exit() mutex_exit(&fil_system.mutex) - /*******************************************************************//** Returns the table space by a given id, NULL if not found. */ fil_space_t* diff --git a/storage/innobase/include/fts0fts.h b/storage/innobase/include/fts0fts.h index 77649aa55ab..6c97c9ed868 100644 --- a/storage/innobase/include/fts0fts.h +++ b/storage/innobase/include/fts0fts.h @@ -377,12 +377,8 @@ extern ulong fts_min_token_size; need a sync to free some memory */ extern bool fts_need_sync; -#define fts_que_graph_free(graph) \ -do { \ - mutex_enter(&dict_sys.mutex); \ - que_graph_free(graph); \ - mutex_exit(&dict_sys.mutex); \ -} while (0) +/** Free a query graph */ +void fts_que_graph_free(que_t *graph); /******************************************************************//** Create a FTS cache. */ diff --git a/storage/innobase/include/gis0rtree.ic b/storage/innobase/include/gis0rtree.ic index 82747bdc95a..cb47c12da80 100644 --- a/storage/innobase/include/gis0rtree.ic +++ b/storage/innobase/include/gis0rtree.ic @@ -175,12 +175,12 @@ rtr_get_parent_node( return(NULL); } - mutex_enter(&btr_cur->rtr_info->rtr_path_mutex); + mysql_mutex_lock(&btr_cur->rtr_info->rtr_path_mutex); num = btr_cur->rtr_info->parent_path->size(); if (!num) { - mutex_exit(&btr_cur->rtr_info->rtr_path_mutex); + mysql_mutex_unlock(&btr_cur->rtr_info->rtr_path_mutex); return(NULL); } @@ -203,7 +203,7 @@ rtr_get_parent_node( } } - mutex_exit(&btr_cur->rtr_info->rtr_path_mutex); + mysql_mutex_unlock(&btr_cur->rtr_info->rtr_path_mutex); return(found_node); } diff --git a/storage/innobase/include/gis0type.h b/storage/innobase/include/gis0type.h index 55944bfcce3..4fccfdb6c26 100644 --- a/storage/innobase/include/gis0type.h +++ b/storage/innobase/include/gis0type.h @@ -72,7 +72,7 @@ typedef struct matched_rec { buf_block_t block; /*!< the shadow buffer block */ ulint used; /*!< memory used */ rtr_rec_vector* matched_recs; /*!< vector holding the matching rec */ - ib_mutex_t rtr_match_mutex;/*!< mutex protect the match_recs + mysql_mutex_t rtr_match_mutex;/*!< mutex protect the match_recs vector */ bool valid; /*!< whether result in matched_recs or this search is valid (page not @@ -103,7 +103,7 @@ typedef struct rtr_info{ /*!< vector holding parent pages during search */ matched_rec_t* matches;/*!< struct holding matching leaf records */ - ib_mutex_t rtr_path_mutex; + mysql_mutex_t rtr_path_mutex; /*!< mutex protect the "path" vector */ buf_block_t* tree_blocks[RTR_MAX_LEVELS + RTR_LEAF_LATCH_NUM]; /*!< tracking pages that would be locked @@ -137,7 +137,7 @@ typedef struct rtr_info{ struct rtr_info_track_t { /** Active search info */ std::forward_list<rtr_info_t*, ut_allocator<rtr_info_t*> > rtr_active; - ib_mutex_t rtr_active_mutex; + mysql_mutex_t rtr_active_mutex; /*!< mutex to protect rtr_active */ }; diff --git a/storage/innobase/include/hash0hash.h b/storage/innobase/include/hash0hash.h index 981ff5a0814..eed3107a082 100644 --- a/storage/innobase/include/hash0hash.h +++ b/storage/innobase/include/hash0hash.h @@ -26,6 +26,7 @@ Created 5/20/1997 Heikki Tuuri #pragma once #include "ut0rnd.h" +#include "ut0new.h" struct hash_table_t; struct hash_cell_t{ diff --git a/storage/innobase/include/ib0mutex.h b/storage/innobase/include/ib0mutex.h deleted file mode 100644 index b83a1aac419..00000000000 --- a/storage/innobase/include/ib0mutex.h +++ /dev/null @@ -1,610 +0,0 @@ -/***************************************************************************** - -Copyright (c) 2013, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2020, 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, Fifth Floor, Boston, MA 02110-1335 USA - -*****************************************************************************/ - -/******************************************************************//** -@file include/ib0mutex.h -Policy based mutexes. - -Created 2013-03-26 Sunny Bains. -***********************************************************************/ - -#ifndef UNIV_INNOCHECKSUM - -#ifndef ib0mutex_h -#define ib0mutex_h - -#include "my_cpu.h" - -/** OS mutex for tracking lock/unlock for debugging */ -template <template <typename> class Policy> -struct OSTrackMutex { - - typedef Policy<OSTrackMutex> MutexPolicy; - - explicit OSTrackMutex(bool destroy_mutex_at_exit = true) - UNIV_NOTHROW - { - ut_d(m_freed = true); - ut_d(m_locked = false); - ut_d(m_destroy_at_exit = destroy_mutex_at_exit); - } - - ~OSTrackMutex() UNIV_NOTHROW - { - ut_ad(!m_destroy_at_exit || !m_locked); - } - - /** Initialise the mutex. */ - void init(latch_id_t, const char*, uint32_t) UNIV_NOTHROW - { - ut_ad(m_freed); - ut_ad(!m_locked); - - m_mutex.init(); - - ut_d(m_freed = false); - } - - /** Destroy the mutex */ - void destroy() UNIV_NOTHROW - { - ut_ad(!m_locked); - ut_ad(!m_freed); - - m_mutex.destroy(); - - ut_d(m_freed = true); - } - - /** Release the mutex. */ - void exit() UNIV_NOTHROW - { - ut_ad(m_locked); - ut_d(m_locked = false); - ut_ad(!m_freed); - - m_mutex.exit(); - } - - /** Acquire the mutex. */ - void enter(uint32_t, uint32_t, const char*, uint32_t) - UNIV_NOTHROW - { - ut_ad(!m_freed); - - m_mutex.enter(); - - ut_ad(!m_locked); - ut_d(m_locked = true); - } - - /** @return true if locking succeeded */ - bool try_lock() UNIV_NOTHROW - { - ut_ad(!m_freed); - - bool locked = m_mutex.try_lock(); - - if (locked) { - ut_ad(!m_locked); - ut_d(m_locked = locked); - } - - return(locked); - } - - /** @return non-const version of the policy */ - MutexPolicy& policy() - UNIV_NOTHROW - { - return(m_policy); - } - - /** @return the const version of the policy */ - const MutexPolicy& policy() const - UNIV_NOTHROW - { - return(m_policy); - } - -private: -#ifdef UNIV_DEBUG - /** true if the mutex has not be initialized */ - bool m_freed; - - /** true if the mutex has been locked. */ - bool m_locked; - - /** Do/Dont destroy mutex at exit */ - bool m_destroy_at_exit; -#endif /* UNIV_DEBUG */ - - /** OS Mutex instance */ - OSMutex m_mutex; - - /** Policy data */ - MutexPolicy m_policy; -}; - - -#ifdef __linux__ - -#include <linux/futex.h> -#include <sys/syscall.h> - -/** Mutex implementation that used the Linux futex. */ -template <template <typename> class Policy> -struct TTASFutexMutex { - - typedef Policy<TTASFutexMutex> MutexPolicy; - - TTASFutexMutex() UNIV_NOTHROW - : - m_lock_word(MUTEX_STATE_UNLOCKED) - { - /* Check that lock_word is aligned. */ - ut_ad(!((ulint) &m_lock_word % sizeof(ulint))); - } - - ~TTASFutexMutex() - { - 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_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.load(std::memory_order_relaxed) - == MUTEX_STATE_UNLOCKED); - } - - /** Acquire the mutex. - @param[in] max_spins max number of spins - @param[in] max_delay max delay per spin */ - void enter(uint32_t max_spins, uint32_t max_delay, - const char*, uint32_t) UNIV_NOTHROW - { - uint32_t n_spins, n_waits; - - for (n_spins= 0; n_spins < max_spins; n_spins++) { - if (try_lock()) { - m_policy.add(n_spins, 0); - return; - } - - ut_delay(max_delay); - } - - for (n_waits= 0;; n_waits++) { - if (m_lock_word.exchange(MUTEX_STATE_WAITERS, - std::memory_order_acquire) - == MUTEX_STATE_UNLOCKED) { - break; - } - - syscall(SYS_futex, &m_lock_word, - FUTEX_WAIT_PRIVATE, MUTEX_STATE_WAITERS, - 0, 0, 0); - } - - m_policy.add(n_spins, n_waits); - } - - /** Release the mutex. */ - void exit() UNIV_NOTHROW - { - 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); - } - } - - /** Try and lock the mutex. - @return true if successful */ - bool try_lock() UNIV_NOTHROW - { - int32 oldval = MUTEX_STATE_UNLOCKED; - 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 */ - MutexPolicy& policy() UNIV_NOTHROW - { - return(m_policy); - } - - /** @return const version of the policy */ - const MutexPolicy& policy() const UNIV_NOTHROW - { - return(m_policy); - } -private: - /** Policy data */ - MutexPolicy m_policy; - - /** lock_word is the target of the atomic test-and-set instruction - when atomic operations are enabled. */ - std::atomic<int32> m_lock_word; -}; - -#endif /* __linux__ */ - -template <template <typename> class Policy> -struct TTASMutex { - - typedef Policy<TTASMutex> MutexPolicy; - - TTASMutex() UNIV_NOTHROW - : - m_lock_word(MUTEX_STATE_UNLOCKED) - { - /* Check that lock_word is aligned. */ - ut_ad(!((ulint) &m_lock_word % sizeof(ulint))); - } - - ~TTASMutex() - { - 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.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.load(std::memory_order_relaxed) - == MUTEX_STATE_UNLOCKED); - } - - /** Try and lock the mutex. - @return true on success */ - bool try_lock() UNIV_NOTHROW - { - 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.load(std::memory_order_relaxed) - == MUTEX_STATE_LOCKED); - m_lock_word.store(MUTEX_STATE_UNLOCKED, - std::memory_order_release); - } - - /** Acquire the mutex. - @param max_spins max number of spins - @param max_delay max delay per spin */ - void enter(uint32_t max_spins, uint32_t max_delay, - const char*, uint32_t) UNIV_NOTHROW - { - const uint32_t step = max_spins; - uint32_t n_spins = 0; - - while (!try_lock()) { - ut_delay(max_delay); - if (++n_spins == max_spins) { - os_thread_yield(); - max_spins+= step; - } - } - - m_policy.add(n_spins, 0); - } - - /** @return non-const version of the policy */ - MutexPolicy& policy() UNIV_NOTHROW - { - return(m_policy); - } - - /** @return const version of the policy */ - const MutexPolicy& policy() const UNIV_NOTHROW - { - return(m_policy); - } - -private: - // Disable copying - TTASMutex(const TTASMutex&); - TTASMutex& operator=(const TTASMutex&); - - /** Policy data */ - MutexPolicy m_policy; - - /** mutex state */ - std::atomic<uint32_t> m_lock_word; -}; - -/** Mutex interface for all policy mutexes. This class handles the interfacing -with the Performance Schema instrumentation. */ -template <typename MutexImpl> -struct PolicyMutex -{ - typedef typename MutexImpl::MutexPolicy Policy; - - PolicyMutex() UNIV_NOTHROW : m_impl() - { -#ifdef UNIV_PFS_MUTEX - m_ptr = 0; -#endif /* UNIV_PFS_MUTEX */ - } - - ~PolicyMutex() { } - - /** @return non-const version of the policy */ - Policy& policy() UNIV_NOTHROW - { - return(m_impl.policy()); - } - - /** @return const version of the policy */ - const Policy& policy() const UNIV_NOTHROW - { - return(m_impl.policy()); - } - - /** Release the mutex. */ - void exit() UNIV_NOTHROW - { -#ifdef UNIV_PFS_MUTEX - pfs_exit(); -#endif /* UNIV_PFS_MUTEX */ - - ut_d(policy().context.release(m_impl)); - - m_impl.exit(); - } - - /** Acquire the mutex. - @param n_spins max number of spins - @param n_delay max delay per spin - @param name filename where locked - @param line line number where locked */ - void enter( - uint32_t n_spins, - uint32_t n_delay, - const char* name, - uint32_t line) UNIV_NOTHROW - { -#ifdef UNIV_PFS_MUTEX - /* Note: locker is really an alias for state. That's why - it has to be in the same scope during pfs_end(). */ - - PSI_mutex_locker_state state; - PSI_mutex_locker* locker; - - locker = pfs_begin_lock(&state, name, line); -#endif /* UNIV_PFS_MUTEX */ - - ut_d(policy().context.enter(m_impl, name, line)); - - m_impl.enter(n_spins, n_delay, name, line); - - ut_d(policy().context.locked(m_impl, name, line)); -#ifdef UNIV_PFS_MUTEX - pfs_end(locker, 0); -#endif /* UNIV_PFS_MUTEX */ - } - - /** Try and lock the mutex, return 0 on SUCCESS and 1 otherwise. - @param name filename where locked - @param line line number where locked */ - int trylock(const char* name, uint32_t line) UNIV_NOTHROW - { -#ifdef UNIV_PFS_MUTEX - /* Note: locker is really an alias for state. That's why - it has to be in the same scope during pfs_end(). */ - - PSI_mutex_locker_state state; - PSI_mutex_locker* locker; - - locker = pfs_begin_trylock(&state, name, line); -#endif /* UNIV_PFS_MUTEX */ - - /* There is a subtlety here, we check the mutex ordering - after locking here. This is only done to avoid add and - then remove if the trylock was unsuccesful. */ - - int ret = m_impl.try_lock() ? 0 : 1; - - if (ret == 0) { - - ut_d(policy().context.enter(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 */ - - return(ret); - } - -#ifdef UNIV_DEBUG - /** @return true if the thread owns the mutex. */ - bool is_owned() const UNIV_NOTHROW - { - return(policy().context.is_owned()); - } -#endif /* UNIV_DEBUG */ - - /** - Initialise the mutex. - - @param[in] id Mutex ID - @param[in] filename file where created - @param[in] line line number in file where created */ - void init( - latch_id_t id, - const char* filename, - uint32_t line) - UNIV_NOTHROW - { -#ifdef UNIV_PFS_MUTEX - pfs_add(sync_latch_get_pfs_key(id)); -#endif /* UNIV_PFS_MUTEX */ - - m_impl.init(id, filename, line); - policy().init(m_impl, id, filename, line); - ut_d(policy().context.init(id)); - } - - /** Free resources (if any) */ - void destroy() UNIV_NOTHROW - { -#ifdef UNIV_PFS_MUTEX - pfs_del(); -#endif /* UNIV_PFS_MUTEX */ - m_impl.destroy(); - policy().destroy(); - ut_d(policy().context.destroy()); - } - - /** Required for os_event_t */ - operator sys_mutex_t*() UNIV_NOTHROW - { - return(m_impl.operator sys_mutex_t*()); - } - -#ifdef UNIV_PFS_MUTEX - /** Performance schema monitoring - register mutex with PFS. - - Note: This is public only because we want to get around an issue - with registering a subset of buffer pool pages with PFS when - PFS_GROUP_BUFFER_SYNC is defined. Therefore this has to then - be called by external code (see buf0buf.cc). - - @param key - Performance Schema key. */ - void pfs_add(mysql_pfs_key_t key) UNIV_NOTHROW - { - ut_ad(m_ptr == 0); - m_ptr = PSI_MUTEX_CALL(init_mutex)(key, this); - } - -private: - - /** Performance schema monitoring. - @param state - PFS locker state - @param name - file name where locked - @param line - line number in file where locked */ - PSI_mutex_locker* pfs_begin_lock( - PSI_mutex_locker_state* state, - const char* name, - uint32_t line) UNIV_NOTHROW - { - if (m_ptr != 0) { - return(PSI_MUTEX_CALL(start_mutex_wait)( - state, m_ptr, - PSI_MUTEX_LOCK, name, (uint) line)); - } - - return(0); - } - - /** Performance schema monitoring. - @param state - PFS locker state - @param name - file name where locked - @param line - line number in file where locked */ - PSI_mutex_locker* pfs_begin_trylock( - PSI_mutex_locker_state* state, - const char* name, - uint32_t line) UNIV_NOTHROW - { - if (m_ptr != 0) { - return(PSI_MUTEX_CALL(start_mutex_wait)( - state, m_ptr, - PSI_MUTEX_TRYLOCK, name, (uint) line)); - } - - return(0); - } - - /** Performance schema monitoring - @param locker - PFS identifier - @param ret - 0 for success and 1 for failure */ - void pfs_end(PSI_mutex_locker* locker, int ret) UNIV_NOTHROW - { - if (locker != 0) { - PSI_MUTEX_CALL(end_mutex_wait)(locker, ret); - } - } - - /** Performance schema monitoring - register mutex release */ - void pfs_exit() - { - if (m_ptr != 0) { - PSI_MUTEX_CALL(unlock_mutex)(m_ptr); - } - } - - /** Performance schema monitoring - deregister */ - void pfs_del() - { - if (m_ptr != 0) { - PSI_MUTEX_CALL(destroy_mutex)(m_ptr); - m_ptr = 0; - } - } -#endif /* UNIV_PFS_MUTEX */ - -private: - /** The mutex implementation */ - MutexImpl m_impl; - -#ifdef UNIV_PFS_MUTEX - /** The performance schema instrumentation hook. */ - PSI_mutex* m_ptr; -#endif /* UNIV_PFS_MUTEX */ - -}; - -#endif /* ib0mutex_h */ - -#endif /* !UNIV_INNOCHECKSUM */ diff --git a/storage/innobase/include/lock0lock.h b/storage/innobase/include/lock0lock.h index d224c216f04..910db0ab8ec 100644 --- a/storage/innobase/include/lock0lock.h +++ b/storage/innobase/include/lock0lock.h @@ -706,9 +706,15 @@ class lock_sys_t { bool m_initialised; -public: + /** The my_hrtime_coarse().val of the oldest mutex_lock_wait() start, or 0 */ + std::atomic<ulonglong> mutex_wait_start; + /** mutex proteting the locks */ MY_ALIGNED(CACHE_LINE_SIZE) mysql_mutex_t mutex; +public: + /** Diagnostic message for exceeding the mutex_lock_wait() timeout */ + static const char fatal_msg[]; + /** record locks */ hash_table_t rec_hash; /** predicate locks for SPATIAL INDEX */ @@ -741,6 +747,38 @@ public: bool is_initialised() { return m_initialised; } +private: + /** Acquire lock_sys.mutex */ + ATTRIBUTE_NOINLINE void mutex_lock_wait(); +public: +#ifdef HAVE_PSI_MUTEX_INTERFACE + /** Try to acquire lock_sys.mutex */ + ATTRIBUTE_NOINLINE int mutex_trylock(); + /** Acquire lock_sys.mutex */ + ATTRIBUTE_NOINLINE void mutex_lock(); + /** Release lock_sys.mutex */ + ATTRIBUTE_NOINLINE void mutex_unlock(); +#else + /** Try to acquire lock_sys.mutex */ + int mutex_trylock() { return mysql_mutex_trylock(&mutex); } + /** Aqcuire lock_sys.mutex */ + void mutex_lock() { if (mutex_trylock()) mutex_lock_wait(); } + /** Release lock_sys.mutex */ + void mutex_unlock() { mysql_mutex_unlock(&mutex); } +#endif + /** Assert that mutex_lock() has been invoked */ + void mutex_assert_locked() const { mysql_mutex_assert_owner(&mutex); } + /** Assert that mutex_lock() has not been invoked */ + void mutex_assert_unlocked() const { mysql_mutex_assert_not_owner(&mutex); } + + /** @return the my_hrtime_coarse().val of the oldest mutex_lock_wait() start, + assuming that requests are served on a FIFO basis */ + ulonglong oldest_wait() const + { return mutex_wait_start.load(std::memory_order_relaxed); } + + /** Wait for a lock to be granted */ + void wait_lock(lock_t **lock, mysql_cond_t *cond) + { while (*lock) mysql_cond_wait(cond, &mutex); } /** Creates the lock system at database start. diff --git a/storage/innobase/include/lock0priv.h b/storage/innobase/include/lock0priv.h index 226c9f84cbb..aa1cb964e53 100644 --- a/storage/innobase/include/lock0priv.h +++ b/storage/innobase/include/lock0priv.h @@ -629,7 +629,7 @@ inline void lock_set_lock_and_trx_wait(lock_t* lock, trx_t* trx) ut_ad(lock); ut_ad(lock->trx == trx); ut_ad(trx->lock.wait_lock == NULL); - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); trx->lock.wait_lock = lock; lock->type_mode |= LOCK_WAIT; @@ -640,7 +640,7 @@ inline void lock_set_lock_and_trx_wait(lock_t* lock, trx_t* trx) inline void lock_reset_lock_and_trx_wait(lock_t* lock) { ut_ad(lock_get_wait(lock)); - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); ut_ad(lock->trx->lock.wait_lock == NULL || lock->trx->lock.wait_lock == lock); lock->trx->lock.wait_lock = NULL; diff --git a/storage/innobase/include/lock0priv.ic b/storage/innobase/include/lock0priv.ic index 0930a8e5932..23e84b15e95 100644 --- a/storage/innobase/include/lock0priv.ic +++ b/storage/innobase/include/lock0priv.ic @@ -131,7 +131,7 @@ lock_rec_get_next( ulint heap_no,/*!< in: heap number of the record */ lock_t* lock) /*!< in: lock */ { - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); do { ut_ad(lock_get_type_low(lock) == LOCK_REC); @@ -206,7 +206,7 @@ lock_rec_get_next_on_page_const( /*============================*/ const lock_t* lock) /*!< in: a record lock */ { - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); ut_ad(lock_get_type_low(lock) == LOCK_REC); const page_id_t page_id(lock->un_member.rec_lock.page_id); diff --git a/storage/innobase/include/log0log.ic b/storage/innobase/include/log0log.ic index 0cf7470682c..aebe511d659 100644 --- a/storage/innobase/include/log0log.ic +++ b/storage/innobase/include/log0log.ic @@ -27,7 +27,6 @@ Created 12/9/1995 Heikki Tuuri #include "mach0data.h" #include "assume_aligned.h" #include "ut0crc32.h" -#include "sync0debug.h" extern ulong srv_log_buffer_size; @@ -305,17 +304,6 @@ log_free_check(void) are holding some latches. This is OK, as long as we are not holding any latches on buffer blocks. */ -#ifdef UNIV_DEBUG - static const latch_level_t latches[] = { - SYNC_DICT, /* dict_sys.mutex during - commit_try_rebuild() */ - }; -#endif /* UNIV_DEBUG */ - - ut_ad(!sync_check_iterate( - sync_allowed_latches(latches, - latches + UT_ARR_SIZE(latches)))); - if (log_sys.check_flush_or_checkpoint()) { log_check_margins(); diff --git a/storage/innobase/include/log0recv.h b/storage/innobase/include/log0recv.h index d29c8849b1b..c7e31f2d336 100644 --- a/storage/innobase/include/log0recv.h +++ b/storage/innobase/include/log0recv.h @@ -26,11 +26,10 @@ Created 9/20/1997 Heikki Tuuri #pragma once -#include "ut0byte.h" +#include "ut0new.h" #include "buf0types.h" #include "log0log.h" #include "mtr0types.h" -#include "ut0mutex.h" #include <deque> diff --git a/storage/innobase/include/mem0mem.ic b/storage/innobase/include/mem0mem.ic index 9236bbef05d..9906daf3eb9 100644 --- a/storage/innobase/include/mem0mem.ic +++ b/storage/innobase/include/mem0mem.ic @@ -24,6 +24,8 @@ The memory management Created 6/8/1994 Heikki Tuuri *************************************************************************/ +#include "ut0new.h" + #ifdef UNIV_DEBUG # define mem_heap_create_block(heap, n, type, file_name, line) \ mem_heap_create_block_func(heap, n, file_name, line, type) diff --git a/storage/innobase/include/mtr0types.h b/storage/innobase/include/mtr0types.h index b5cfcadbe75..5445dc0a763 100644 --- a/storage/innobase/include/mtr0types.h +++ b/storage/innobase/include/mtr0types.h @@ -24,14 +24,11 @@ Mini-transaction buffer global types Created 11/26/1995 Heikki Tuuri *******************************************************/ -#ifndef mtr0types_h -#define mtr0types_h +#pragma once -#ifndef UNIV_INNOCHECKSUM #include "buf0types.h" -#else -#include "univ.i" -#endif /* UNIV_INNOCHECKSUM */ + +#include "ut0byte.h" struct mtr_t; @@ -344,6 +341,4 @@ enum mtr_memo_type_t { /** wr_lock() on fil_space_t::latch */ MTR_MEMO_SPACE_S_LOCK = MTR_MEMO_SX_LOCK << 2 }; -#endif /* !UNIV_CHECKSUM */ - -#endif /* mtr0types_h */ +#endif /* !UNIV_INNOCHECKSUM */ diff --git a/storage/innobase/include/os0thread.h b/storage/innobase/include/os0thread.h index d784f624b07..f9eb4b15745 100644 --- a/storage/innobase/include/os0thread.h +++ b/storage/innobase/include/os0thread.h @@ -59,11 +59,6 @@ extern "C" { typedef void* (*os_thread_func_t)(void*); } /* Define a function pointer type to use in a typecast */ typedef void* (*os_posix_f_t) (void*); -#ifdef HAVE_PSI_INTERFACE -/* Define for performance schema registration key */ -typedef unsigned int mysql_pfs_key_t; -#endif /* HAVE_PSI_INTERFACE */ - #define os_thread_eq(a,b) IF_WIN(a == b, pthread_equal(a, b)) #define os_thread_yield() IF_WIN(SwitchToThread(), sched_yield()) #define os_thread_get_curr_id() IF_WIN(GetCurrentThreadId(), pthread_self()) diff --git a/storage/innobase/include/page0types.h b/storage/innobase/include/page0types.h index 6c5a681f3b5..4d6aabfd576 100644 --- a/storage/innobase/include/page0types.h +++ b/storage/innobase/include/page0types.h @@ -30,6 +30,7 @@ Created 2/2/1994 Heikki Tuuri #include "dict0types.h" #include "mtr0types.h" #include "rem0types.h" +#include "ut0new.h" #include <map> diff --git a/storage/innobase/include/page0zip.ic b/storage/innobase/include/page0zip.ic index ede61283f33..87af2cc3879 100644 --- a/storage/innobase/include/page0zip.ic +++ b/storage/innobase/include/page0zip.ic @@ -324,11 +324,7 @@ void page_zip_reset_stat_per_index() /*===========================*/ { - mutex_enter(&page_zip_stat_per_index_mutex); - - page_zip_stat_per_index.erase( - page_zip_stat_per_index.begin(), - page_zip_stat_per_index.end()); - - mutex_exit(&page_zip_stat_per_index_mutex); + mysql_mutex_lock(&page_zip_stat_per_index_mutex); + page_zip_stat_per_index.clear(); + mysql_mutex_unlock(&page_zip_stat_per_index_mutex); } diff --git a/storage/innobase/include/read0types.h b/storage/innobase/include/read0types.h index 21143ab609d..521097b5298 100644 --- a/storage/innobase/include/read0types.h +++ b/storage/innobase/include/read0types.h @@ -24,13 +24,15 @@ Cursor read Created 2/16/1997 Heikki Tuuri *******************************************************/ -#ifndef read0types_h -#define read0types_h +#pragma once #include "dict0mem.h" #include "trx0types.h" #include <algorithm> +#ifdef UNIV_PFS_MUTEX +extern mysql_pfs_key_t read_view_mutex_key; +#endif /** Read view lists the trx ids of those transactions for which a consistent read @@ -190,7 +192,7 @@ class ReadView: public ReadViewBase std::atomic<bool> m_open; /** For synchronisation with purge coordinator. */ - mutable ib_mutex_t m_mutex; + mutable mysql_mutex_t m_mutex; /** trx id of creating transaction. @@ -199,8 +201,9 @@ class ReadView: public ReadViewBase trx_id_t m_creator_trx_id; public: - ReadView(): m_open(false) { mutex_create(LATCH_ID_READ_VIEW, &m_mutex); } - ~ReadView() { mutex_free(&m_mutex); } + ReadView(): m_open(false) + { mysql_mutex_init(read_view_mutex_key, &m_mutex, nullptr); } + ~ReadView() { mysql_mutex_destroy(&m_mutex); } /** @@ -248,12 +251,12 @@ public: */ void print_limits(FILE *file) const { - mutex_enter(&m_mutex); + mysql_mutex_lock(&m_mutex); if (is_open()) fprintf(file, "Trx read view will not see trx with" " id >= " TRX_ID_FMT ", sees < " TRX_ID_FMT "\n", low_limit_id(), up_limit_id()); - mutex_exit(&m_mutex); + mysql_mutex_unlock(&m_mutex); } @@ -271,23 +274,19 @@ public: */ void append_to(ReadViewBase *to) const { - mutex_enter(&m_mutex); + mysql_mutex_lock(&m_mutex); if (is_open()) to->append(*this); - mutex_exit(&m_mutex); + mysql_mutex_unlock(&m_mutex); } - /** Declare the object mostly unaccessible. - innodb_monitor_set_option is operating also on freed transaction objects. */ void mem_noaccess() const { MEM_NOACCESS(&m_open, sizeof m_open); - /* m_mutex is accessed by innodb_show_mutex_status() - and innodb_monitor_update() even after trx_t::free() */ + /* m_mutex is accessed via trx_sys.rw_trx_hash */ MEM_NOACCESS(&m_creator_trx_id, sizeof m_creator_trx_id); } }; -#endif diff --git a/storage/innobase/include/row0mysql.h b/storage/innobase/include/row0mysql.h index 18114f18b14..6d189b6e580 100644 --- a/storage/innobase/include/row0mysql.h +++ b/storage/innobase/include/row0mysql.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2000, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2019, MariaDB Corporation. +Copyright (c) 2017, 2020, 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 @@ -316,11 +316,18 @@ data dictionary modification operation. */ void row_mysql_lock_data_dictionary_func( /*================================*/ - trx_t* trx, /*!< in/out: transaction */ +#ifdef UNIV_PFS_RWLOCK const char* file, /*!< in: file name */ - unsigned line); /*!< in: line number */ + unsigned line, /*!< in: line number */ +#endif + trx_t* trx); /*!< in/out: transaction */ +#ifdef UNIV_PFS_RWLOCK #define row_mysql_lock_data_dictionary(trx) \ - row_mysql_lock_data_dictionary_func(trx, __FILE__, __LINE__) + row_mysql_lock_data_dictionary_func(__FILE__, __LINE__, trx) +#else +#define row_mysql_lock_data_dictionary row_mysql_lock_data_dictionary_func +#endif + /*********************************************************************//** Unlocks the data dictionary exclusive lock. */ void diff --git a/storage/innobase/include/srv0mon.h b/storage/innobase/include/srv0mon.h index 6f75cdc0b64..66a91b87d60 100644 --- a/storage/innobase/include/srv0mon.h +++ b/storage/innobase/include/srv0mon.h @@ -38,7 +38,6 @@ Created 12/15/2009 Jimmy Yang #include <stdint.h> #include "my_atomic.h" -#include "my_atomic_wrapper.h" /** Possible status values for "mon_status" in "struct monitor_value" */ enum monitor_running_status { @@ -419,10 +418,6 @@ enum monitor_id_t { MONITOR_ICP_OUT_OF_RANGE, MONITOR_ICP_MATCH, - /* Mutex/RW-Lock related counters */ - MONITOR_MODULE_LATCHES, - MONITOR_LATCHES, - /* This is used only for control system to turn on/off and reset all monitor counters */ MONITOR_ALL_COUNTER, diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index 5aedd122a0f..8b87cb9014c 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -52,6 +52,29 @@ Created 10/10/1995 Heikki Tuuri #include <tpool.h> #include <memory> +/** Simple non-atomic counter +@tparam Type the integer type of the counter */ +template <typename Type> +struct MY_ALIGNED(CPU_LEVEL1_DCACHE_LINESIZE) simple_counter +{ + /** Increment the counter */ + Type inc() { return add(1); } + /** Decrement the counter */ + Type dec() { return add(Type(~0)); } + + /** Add to the counter + @param i amount to be added + @return the value of the counter after adding */ + Type add(Type i) { return m_counter += i; } + + /** @return the value of the counter */ + operator Type() const { return m_counter; } + +private: + /** The counter */ + Type m_counter; +}; + /** Global counters used inside InnoDB. */ struct srv_stats_t { @@ -210,15 +233,13 @@ at a time */ #define SRV_AUTO_EXTEND_INCREMENT (srv_sys_space.get_autoextend_increment()) /** Mutex protecting page_zip_stat_per_index */ -extern ib_mutex_t page_zip_stat_per_index_mutex; -/* Mutex for locking srv_monitor_file. Not created if srv_read_only_mode */ -extern ib_mutex_t srv_monitor_file_mutex; +extern mysql_mutex_t page_zip_stat_per_index_mutex; +/** Mutex for locking srv_monitor_file */ +extern mysql_mutex_t srv_monitor_file_mutex; /* Temporary file for innodb monitor output */ extern FILE* srv_monitor_file; -/* Mutex for locking srv_misc_tmpfile. Only created if !srv_read_only_mode. -This mutex has a very low rank; threads reserving it should not -acquire any further latches or sleep before releasing this one. */ -extern ib_mutex_t srv_misc_tmpfile_mutex; +/** Mutex for locking srv_misc_tmpfile */ +extern mysql_mutex_t srv_misc_tmpfile_mutex; /* Temporary file for miscellanous diagnostic output */ extern FILE* srv_misc_tmpfile; @@ -454,7 +475,6 @@ extern ulint srv_log_writes_and_flush; #ifdef UNIV_DEBUG extern my_bool innodb_evict_tables_on_commit_debug; -extern my_bool srv_sync_debug; extern my_bool srv_purge_view_update_only_debug; /** Value of MySQL global used to disable master thread. */ @@ -480,9 +500,6 @@ extern uint srv_n_purge_threads; /* the number of pages to purge in one batch */ extern ulong srv_purge_batch_size; -/* the number of sync wait arrays */ -extern ulong srv_sync_array_size; - /* print all user-level transactions deadlocks to mysqld stderr */ extern my_bool srv_print_all_deadlocks; diff --git a/storage/innobase/include/sync0debug.h b/storage/innobase/include/sync0debug.h deleted file mode 100644 index 1ccf95ea3a8..00000000000 --- a/storage/innobase/include/sync0debug.h +++ /dev/null @@ -1,78 +0,0 @@ -/***************************************************************************** - -Copyright (c) 2013, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2020, MariaDB Corporation. - -Portions of this file contain modifications contributed and copyrighted by -Google, Inc. Those modifications are gratefully acknowledged and are described -briefly in the InnoDB documentation. The contributions by Google are -incorporated with their permission, and subject to the conditions contained in -the file COPYING.Google. - -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, Fifth Floor, Boston, MA 02110-1335 USA - -*****************************************************************************/ - -/**************************************************//** -@file include/sync0debug.h -Debug checks for latches, header file - -Created 2012-08-21 Sunny Bains -*******************************************************/ - -#ifndef sync0debug_h -#define sync0debug_h - -#include "univ.i" - -/** Initializes the synchronization data structures. */ -void -sync_check_init(); - -/** Free the InnoDB synchronization data structures. */ -void -sync_check_close(); - -#ifdef UNIV_DEBUG -/** Check if it is OK to acquire the latch. -@param[in] latch latch type */ -void -sync_check_lock_validate(const latch_t* latch); - -/** Note that the lock has been granted -@param[in] latch latch type */ -void -sync_check_lock_granted(const latch_t* latch); - -/** Removes a latch from the thread level array if it is found there. -@param[in] latch to unlock */ -void -sync_check_unlock(const latch_t* latch); - -/** Checks if the level array for the current thread contains a -mutex or rw-latch at the specified level. -@param[in] level to find -@return a matching latch, or NULL if not found */ -const latch_t* -sync_check_find(latch_level_t level); - -/** Checks that the level array for the current thread is empty. -Terminate iteration if the functor returns true. -@param[in] functor called for each element. -@return true if the functor returns true for any element */ -bool -sync_check_iterate(const sync_check_functor_t& functor); - -#endif /* UNIV_DEBUG */ - -#endif /* !sync0debug_h */ diff --git a/storage/innobase/include/sync0policy.h b/storage/innobase/include/sync0policy.h deleted file mode 100644 index 68397827891..00000000000 --- a/storage/innobase/include/sync0policy.h +++ /dev/null @@ -1,296 +0,0 @@ -/***************************************************************************** - -Copyright (c) 2013, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2018, 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, Fifth Floor, 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 "ut0rnd.h" -#include "os0thread.h" -#include "srv0mon.h" -#include "sync0debug.h" - -#ifdef UNIV_DEBUG - -template <typename Mutex> class MutexDebug: public latch_t -{ - /** 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 */ - 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; - - - void set(const Mutex *mutex, const char *filename, unsigned line, - os_thread_id_t thread_id) - { - m_debug_mutex.enter(); - m_mutex= mutex; - m_filename= filename; - m_line= line; - m_thread_id= thread_id; - m_debug_mutex.exit(); - } - - - const MutexDebug get() const - { - MutexDebug ret; - m_debug_mutex.enter(); - ret.m_mutex= m_mutex; - ret.m_filename= m_filename; - ret.m_line= m_line; - ret.m_thread_id= m_thread_id; - m_debug_mutex.exit(); - return ret; - } - - - /** - Called either when mutex is locked or destroyed. Thus members are protected - from concurrent modification. - */ - void assert_clean_context() - { - ut_ad(!m_mutex); - ut_ad(!m_filename); - ut_ad(!m_line); - ut_ad(m_thread_id == os_thread_id_t(ULINT_UNDEFINED)); - } - - -public: - /** - 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) - { - ut_ad(id != LATCH_ID_NONE); - m_id= id; - m_debug_mutex.init(); - set(0, 0, 0, os_thread_id_t(ULINT_UNDEFINED)); - } - - - /** Mutex is being destroyed. */ - void destroy() - { - assert_clean_context(); - m_debug_mutex.destroy(); - } - - - /** - 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, unsigned line) - { - MutexDebug context; - 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 - @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, unsigned line) - { - assert_clean_context(); - set(&mutex, filename, line, os_thread_get_curr_id()); - sync_check_lock_granted(this); - } - - - /** - Called when the mutex is released - @param[in] mutex Mutex that was released - */ - void release(const Mutex &mutex) - { - ut_ad(is_owned()); - set(0, 0, 0, os_thread_id_t(ULINT_UNDEFINED)); - sync_check_unlock(this); - } - - - /** @return true if thread owns the mutex */ - bool is_owned() const - { - return os_thread_eq(get_thread_id(), os_thread_get_curr_id()); - } - - - /** @return the name of the file from the mutex was acquired */ - const char* get_enter_filename() const { return get().m_filename; } - - - /** @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 */ - os_thread_id_t get_thread_id() const { return get().m_thread_id; } - - - /** - Print information about the latch - @return the string representation - */ - virtual std::string to_string() const - { - std::ostringstream msg; - const MutexDebug ctx= get(); - - msg << m_mutex->policy().to_string(); - if (ctx.m_mutex) - msg << " addr: " << ctx.m_mutex << " acquired: " - << sync_basename(ctx.get_enter_filename()) << ":" - << ctx.get_enter_line(); - else - msg << "Not locked"; - - return(msg.str()); - } -}; -#endif /* UNIV_DEBUG */ - -/** Collect the metrics per mutex instance, no aggregation. */ -template <typename Mutex> -struct GenericPolicy -{ -public: - /** Called when the mutex is "created". Note: Not from the constructor - but when the mutex is initialised. - @param[in] id Mutex ID - @param[in] filename File where mutex was created - @param[in] line Line in filename */ - void init( - const 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); - - m_filename = filename; - m_line = line; - } - - /** 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); - } - - /** 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; - } - - /** 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 - { - return sync_mutex_to_string(get_id(), - std::string(m_filename) - .append(":") - .append(std::to_string(m_line))); - } - -#ifdef UNIV_DEBUG - MutexDebug<Mutex> context; -#endif - -private: - const char *m_filename; - uint32_t m_line; - - /** The user visible counters, registered with the meta-data. */ - latch_meta_t::CounterType::Count m_count; - - /** Latch meta data ID */ - latch_id_t m_id; -}; - -#endif /* sync0policy_h */ diff --git a/storage/innobase/include/sync0sync.h b/storage/innobase/include/sync0sync.h deleted file mode 100644 index 2d45b03e908..00000000000 --- a/storage/innobase/include/sync0sync.h +++ /dev/null @@ -1,96 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2008, Google Inc. -Copyright (c) 2012, Facebook Inc. -Copyright (c) 2020, MariaDB Corporation. - -Portions of this file contain modifications contributed and copyrighted by -Google, Inc. Those modifications are gratefully acknowledged and are described -briefly in the InnoDB documentation. The contributions by Google are -incorporated with their permission, and subject to the conditions contained in -the file COPYING.Google. - -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, Fifth Floor, Boston, MA 02110-1335 USA - -*****************************************************************************/ - -/**************************************************//** -@file include/sync0sync.h -Mutex, the basic synchronization primitive - -Created 9/5/1995 Heikki Tuuri -*******************************************************/ - -#ifndef sync0sync_h -#define sync0sync_h - -#include "univ.i" - -#ifdef UNIV_PFS_MUTEX -/* Key defines to register InnoDB mutexes with performance schema */ -extern mysql_pfs_key_t buf_pool_mutex_key; -extern mysql_pfs_key_t dict_foreign_err_mutex_key; -extern mysql_pfs_key_t dict_sys_mutex_key; -extern mysql_pfs_key_t fil_system_mutex_key; -extern mysql_pfs_key_t flush_list_mutex_key; -extern mysql_pfs_key_t fts_cache_mutex_key; -extern mysql_pfs_key_t fts_cache_init_mutex_key; -extern mysql_pfs_key_t fts_delete_mutex_key; -extern mysql_pfs_key_t fts_doc_id_mutex_key; -extern mysql_pfs_key_t fts_pll_tokenize_mutex_key; -extern mysql_pfs_key_t ibuf_bitmap_mutex_key; -extern mysql_pfs_key_t ibuf_mutex_key; -extern mysql_pfs_key_t ibuf_pessimistic_insert_mutex_key; -extern mysql_pfs_key_t log_sys_mutex_key; -extern mysql_pfs_key_t log_cmdq_mutex_key; -extern mysql_pfs_key_t log_flush_order_mutex_key; -extern mysql_pfs_key_t recalc_pool_mutex_key; -extern mysql_pfs_key_t purge_sys_pq_mutex_key; -extern mysql_pfs_key_t recv_sys_mutex_key; -extern mysql_pfs_key_t rtr_active_mutex_key; -extern mysql_pfs_key_t rtr_match_mutex_key; -extern mysql_pfs_key_t rtr_path_mutex_key; -extern mysql_pfs_key_t redo_rseg_mutex_key; -extern mysql_pfs_key_t noredo_rseg_mutex_key; -extern mysql_pfs_key_t page_zip_stat_per_index_mutex_key; -extern mysql_pfs_key_t srv_innodb_monitor_mutex_key; -extern mysql_pfs_key_t srv_misc_tmpfile_mutex_key; -extern mysql_pfs_key_t srv_monitor_file_mutex_key; -extern mysql_pfs_key_t buf_dblwr_mutex_key; -extern mysql_pfs_key_t trx_pool_mutex_key; -extern mysql_pfs_key_t trx_pool_manager_mutex_key; -extern mysql_pfs_key_t lock_mutex_key; -extern mysql_pfs_key_t lock_wait_mutex_key; -extern mysql_pfs_key_t trx_sys_mutex_key; -extern mysql_pfs_key_t srv_threads_mutex_key; -extern mysql_pfs_key_t sync_array_mutex_key; -extern mysql_pfs_key_t thread_mutex_key; -extern mysql_pfs_key_t row_drop_list_mutex_key; -extern mysql_pfs_key_t rw_trx_hash_element_mutex_key; -extern mysql_pfs_key_t read_view_mutex_key; -#endif /* UNIV_PFS_MUTEX */ - -#ifdef UNIV_PFS_RWLOCK -/* Following are rwlock keys used to register with MySQL -performance schema */ -extern mysql_pfs_key_t dict_operation_lock_key; -extern mysql_pfs_key_t fil_space_latch_key; -extern mysql_pfs_key_t trx_i_s_cache_lock_key; -extern mysql_pfs_key_t trx_purge_latch_key; -extern mysql_pfs_key_t index_tree_rw_lock_key; -extern mysql_pfs_key_t index_online_log_key; -extern mysql_pfs_key_t trx_sys_rw_lock_key; -#endif /* UNIV_PFS_RWLOCK */ - -#endif /* !sync0sync_h */ diff --git a/storage/innobase/include/sync0types.h b/storage/innobase/include/sync0types.h deleted file mode 100644 index f8df704c9d9..00000000000 --- a/storage/innobase/include/sync0types.h +++ /dev/null @@ -1,967 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2020, 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, Fifth Floor, Boston, MA 02110-1335 USA - -*****************************************************************************/ - -/**************************************************//** -@file include/sync0types.h -Global types for sync - -Created 9/5/1995 Heikki Tuuri -*******************************************************/ - -#ifndef sync0types_h -#define sync0types_h - -#include <vector> - -#include "ut0new.h" - -#ifdef _WIN32 -/** Native mutex */ -typedef CRITICAL_SECTION sys_mutex_t; -#else -/** Native mutex */ -typedef pthread_mutex_t sys_mutex_t; -#endif /* _WIN32 */ - -/** Mutex states. */ -enum mutex_state_t { - /** Mutex is free */ - MUTEX_STATE_UNLOCKED = 0, - - /** Mutex is acquired by some thread. */ - MUTEX_STATE_LOCKED = 1, - - /** Mutex is contended and there are threads waiting on the lock. */ - MUTEX_STATE_WAITERS = 2 -}; - -/* - LATCHING ORDER WITHIN THE DATABASE - ================================== - -The mutex or latch in the central memory object, for instance, a rollback -segment object, must be acquired before acquiring the latch or latches to -the corresponding file data structure. In the latching order below, these -file page object latches are placed immediately below the corresponding -central memory object latch or mutex. - -Synchronization object Notes ----------------------- ----- - -Dictionary mutex If we have a pointer to a dictionary -| object, e.g., a table, it can be -| accessed without reserving the -| dictionary mutex. We must have a -| reservation, a memoryfix, to the -| appropriate table object in this case, -| and the table must be explicitly -| released later. -V -Dictionary header -| -V -Secondary index tree latch The tree latch protects also all -| the B-tree non-leaf pages. These -V can be read with the page only -Secondary index non-leaf bufferfixed to save CPU time, -| no s-latch is needed on the page. -| Modification of a page requires an -| x-latch on the page, however. If a -| thread owns an x-latch to the tree, -| it is allowed to latch non-leaf pages -| even after it has acquired the fsp -| latch. -V -Secondary index leaf The latch on the secondary index leaf -| can be kept while accessing the -| clustered index, to save CPU time. -V -Clustered index tree latch To increase concurrency, the tree -| latch is usually released when the -| leaf page latch has been acquired. -V -Clustered index non-leaf -| -V -Clustered index leaf -| -V -Transaction system header -| -V -Rollback segment mutex The rollback segment mutex must be -| reserved, if, e.g., a new page must -| be added to an undo log. The rollback -| segment and the undo logs in its -| history list can be seen as an -| analogue of a B-tree, and the latches -| reserved similarly, using a version of -| lock-coupling. If an undo log must be -| extended by a page when inserting an -| undo log record, this corresponds to -| a pessimistic insert in a B-tree. -V -Rollback segment header -| -V -Purge system latch -| -V -Undo log pages If a thread owns the trx undo mutex, -| or for a log in the history list, the -| rseg mutex, it is allowed to latch -| undo log pages in any order, and even -| after it has acquired the fsp latch. -| If a thread does not have the -| appropriate mutex, it is allowed to -| latch only a single undo log page in -| a mini-transaction. -V -File space management latch If a mini-transaction must allocate -| several file pages, it can do that, -| because it keeps the x-latch to the -| file space management in its memo. -V -File system pages -| -V -lock_sys.wait_mutex Mutex protecting lock timeout data -| -V -lock_sys.mutex Mutex protecting lock_sys_t -| -V -trx_sys.mutex Mutex protecting trx_sys.trx_list -| -V -Threads mutex Background thread scheduling mutex -| -V -query_thr_mutex Mutex protecting query threads -| -V -trx_mutex Mutex protecting trx_t fields -| -V -Search system mutex -| -V -Buffer pool mutex -| -V -Log mutex -| -Any other latch -| -V -Memory pool mutex */ - -/** Latching order levels. If you modify these, you have to also update -LatchDebug internals in sync0debug.cc */ - -enum latch_level_t { - SYNC_UNKNOWN = 0, - - RW_LOCK_SX, - RW_LOCK_X_WAIT, - RW_LOCK_S, - RW_LOCK_X, - RW_LOCK_NOT_LOCKED, - - SYNC_ANY_LATCH, - - SYNC_POOL, - SYNC_POOL_MANAGER, - - SYNC_PURGE_QUEUE, - SYNC_RW_TRX_HASH_ELEMENT, - SYNC_READ_VIEW, - SYNC_TRX_SYS, - - SYNC_INDEX_ONLINE_LOG, - - SYNC_IBUF_BITMAP_MUTEX, - - SYNC_IBUF_MUTEX, - - SYNC_NOREDO_RSEG, - SYNC_REDO_RSEG, - SYNC_IBUF_PESS_INSERT_MUTEX, - - SYNC_STATS_AUTO_RECALC, - SYNC_DICT, - - /** This can be used to suppress order checking. */ - SYNC_NO_ORDER_CHECK, - - /** Maximum level value */ - SYNC_LEVEL_MAX = SYNC_NO_ORDER_CHECK -}; - -/** Each latch has an ID. This id is used for creating the latch and to look -up its meta-data. See sync0debug.cc. */ -enum latch_id_t { - LATCH_ID_NONE = 0, - LATCH_ID_DICT_FOREIGN_ERR, - LATCH_ID_DICT_SYS, - LATCH_ID_FIL_SYSTEM, - LATCH_ID_IBUF_BITMAP, - LATCH_ID_IBUF, - LATCH_ID_IBUF_PESSIMISTIC_INSERT, - LATCH_ID_PURGE_SYS_PQ, - LATCH_ID_RECALC_POOL, - LATCH_ID_REDO_RSEG, - LATCH_ID_NOREDO_RSEG, - LATCH_ID_RTR_ACTIVE_MUTEX, - LATCH_ID_RTR_MATCH_MUTEX, - LATCH_ID_RTR_PATH_MUTEX, - LATCH_ID_SRV_INNODB_MONITOR, - LATCH_ID_SRV_MISC_TMPFILE, - LATCH_ID_SRV_MONITOR_FILE, - LATCH_ID_TRX_POOL, - LATCH_ID_TRX_POOL_MANAGER, - LATCH_ID_TRX_SYS, - LATCH_ID_SRV_SYS_TASKS, - LATCH_ID_PAGE_ZIP_STAT_PER_INDEX, - LATCH_ID_SYNC_ARRAY_MUTEX, - LATCH_ID_ROW_DROP_LIST, - LATCH_ID_INDEX_ONLINE_LOG, - LATCH_ID_DICT_TABLE_STATS, - LATCH_ID_DEFRAGMENT_MUTEX, - LATCH_ID_RW_TRX_HASH_ELEMENT, - LATCH_ID_READ_VIEW, - LATCH_ID_MAX = LATCH_ID_READ_VIEW -}; - -#ifndef UNIV_INNOCHECKSUM -/** OS mutex, without any policy. It is a thin wrapper around the -system mutexes. The interface is different from the policy mutexes, -to ensure that it is called directly and not confused with the -policy mutexes. */ -struct OSMutex { - - /** Constructor */ - OSMutex() - UNIV_NOTHROW - { - ut_d(m_freed = true); - } - - /** Create the mutex by calling the system functions. */ - void init() - UNIV_NOTHROW - { - ut_ad(m_freed); - -#ifdef _WIN32 - InitializeCriticalSection((LPCRITICAL_SECTION) &m_mutex); -#else - { - int ret = pthread_mutex_init(&m_mutex, NULL); - ut_a(ret == 0); - } -#endif /* _WIN32 */ - - ut_d(m_freed = false); - } - - /** Destructor */ - ~OSMutex() { } - - /** Destroy the mutex */ - void destroy() - UNIV_NOTHROW - { - ut_ad(!m_freed); -#ifdef _WIN32 - DeleteCriticalSection((LPCRITICAL_SECTION) &m_mutex); -#else - int ret; - - ret = pthread_mutex_destroy(&m_mutex); - - if (ret != 0) { - - ib::error() - << "Return value " << ret << " when calling " - << "pthread_mutex_destroy()."; - } -#endif /* _WIN32 */ - ut_d(m_freed = true); - } - - /** Release the mutex. */ - void exit() - UNIV_NOTHROW - { - ut_ad(!m_freed); -#ifdef _WIN32 - LeaveCriticalSection(&m_mutex); -#else - int ret = pthread_mutex_unlock(&m_mutex); - ut_a(ret == 0); -#endif /* _WIN32 */ - } - - /** Acquire the mutex. */ - void enter() - UNIV_NOTHROW - { - ut_ad(!m_freed); -#ifdef _WIN32 - EnterCriticalSection((LPCRITICAL_SECTION) &m_mutex); -#else - int ret = pthread_mutex_lock(&m_mutex); - ut_a(ret == 0); -#endif /* _WIN32 */ - } - - /** @return true if locking succeeded */ - bool try_lock() - UNIV_NOTHROW - { - ut_ad(!m_freed); -#ifdef _WIN32 - return(TryEnterCriticalSection(&m_mutex) != 0); -#else - return(pthread_mutex_trylock(&m_mutex) == 0); -#endif /* _WIN32 */ - } - - /** Required for os_event_t */ - operator sys_mutex_t*() - UNIV_NOTHROW - { - return(&m_mutex); - } - -private: -#ifdef DBUG_ASSERT_EXISTS - /** true if the mutex has been freed/destroyed. */ - bool m_freed; -#endif /* DBUG_ASSERT_EXISTS */ - - sys_mutex_t m_mutex; -}; - -#ifdef UNIV_PFS_MUTEX -/** Latch element. -Used for mutexes which have PFS keys defined under UNIV_PFS_MUTEX. -@param[in] id Latch id -@param[in] level Latch level -@param[in] key PFS key */ -# define LATCH_ADD_MUTEX(id, level, key) latch_meta[LATCH_ID_ ## id] =\ - UT_NEW_NOKEY(latch_meta_t(LATCH_ID_ ## id, #id, level, #level, key)) - -#ifdef UNIV_PFS_RWLOCK -/** Latch element. -Used for rwlocks which have PFS keys defined under UNIV_PFS_RWLOCK. -@param[in] id Latch id -@param[in] level Latch level -@param[in] key PFS key */ -# define LATCH_ADD_RWLOCK(id, level, key) latch_meta[LATCH_ID_ ## id] =\ - UT_NEW_NOKEY(latch_meta_t(LATCH_ID_ ## id, #id, level, #level, key)) -#else -# define LATCH_ADD_RWLOCK(id, level, key) latch_meta[LATCH_ID_ ## id] =\ - UT_NEW_NOKEY(latch_meta_t(LATCH_ID_ ## id, #id, level, #level, \ - PSI_NOT_INSTRUMENTED)) -#endif /* UNIV_PFS_RWLOCK */ - -#else -# define LATCH_ADD_MUTEX(id, level, key) latch_meta[LATCH_ID_ ## id] =\ - UT_NEW_NOKEY(latch_meta_t(LATCH_ID_ ## id, #id, level, #level)) -# define LATCH_ADD_RWLOCK(id, level, key) latch_meta[LATCH_ID_ ## id] =\ - UT_NEW_NOKEY(latch_meta_t(LATCH_ID_ ## id, #id, level, #level)) -#endif /* UNIV_PFS_MUTEX */ - -/** Default latch counter */ -class LatchCounter { - -public: - /** The counts we collect for a mutex */ - struct Count { - - /** Constructor */ - Count() - UNIV_NOTHROW - : - m_spins(), - m_waits(), - m_calls(), - m_enabled() - { - /* No op */ - } - - /** Rest the values to zero */ - void reset() - UNIV_NOTHROW - { - m_spins = 0; - m_waits = 0; - m_calls = 0; - } - - /** Number of spins trying to acquire the latch. */ - uint32_t m_spins; - - /** Number of waits trying to acquire the latch */ - uint32_t m_waits; - - /** Number of times it was called */ - uint32_t m_calls; - - /** true if enabled */ - bool m_enabled; - }; - - /** Constructor */ - LatchCounter() - UNIV_NOTHROW - : - m_active(false) - { - m_mutex.init(); - } - - /** Destructor */ - ~LatchCounter() - UNIV_NOTHROW - { - m_mutex.destroy(); - - for (Counters::iterator it = m_counters.begin(); - it != m_counters.end(); - ++it) { - - Count* count = *it; - - UT_DELETE(count); - } - } - - /** Reset all counters to zero. It is not protected by any - mutex and we don't care about atomicity. Unless it is a - demonstrated problem. The information collected is not - required for the correct functioning of the server. */ - void reset() - UNIV_NOTHROW - { - m_mutex.enter(); - - Counters::iterator end = m_counters.end(); - - for (Counters::iterator it = m_counters.begin(); - it != end; - ++it) { - - (*it)->reset(); - } - - m_mutex.exit(); - } - - /** @return the aggregate counter */ - Count* sum_register() - UNIV_NOTHROW - { - m_mutex.enter(); - - Count* count; - - if (m_counters.empty()) { - count = UT_NEW_NOKEY(Count()); - m_counters.push_back(count); - } else { - ut_a(m_counters.size() == 1); - count = m_counters[0]; - } - - m_mutex.exit(); - - return(count); - } - - /** Register a single instance counter */ - void single_register(Count* count) - UNIV_NOTHROW - { - m_mutex.enter(); - - m_counters.push_back(count); - - m_mutex.exit(); - } - - /** Deregister a single instance counter - @param[in] count The count instance to deregister */ - void single_deregister(Count* count) - UNIV_NOTHROW - { - m_mutex.enter(); - - m_counters.erase( - std::remove( - m_counters.begin(), - m_counters.end(), count), - m_counters.end()); - - m_mutex.exit(); - } - - /** Iterate over the counters */ - template<typename C> void iterate(const C& callback) UNIV_NOTHROW - { - m_mutex.enter(); - - Counters::const_iterator end = m_counters.end(); - - for (Counters::const_iterator it = m_counters.begin(); - it != end; - ++it) { - - callback(*it); - } - - m_mutex.exit(); - } - - /** Disable the monitoring */ - void enable() - UNIV_NOTHROW - { - m_mutex.enter(); - - Counters::const_iterator end = m_counters.end(); - - for (Counters::const_iterator it = m_counters.begin(); - it != end; - ++it) { - - (*it)->m_enabled = true; - } - - m_active = true; - - m_mutex.exit(); - } - - /** Disable the monitoring */ - void disable() - UNIV_NOTHROW - { - m_mutex.enter(); - - Counters::const_iterator end = m_counters.end(); - - for (Counters::const_iterator it = m_counters.begin(); - it != end; - ++it) { - - (*it)->m_enabled = false; - } - - m_active = false; - - m_mutex.exit(); - } - - /** @return if monitoring is active */ - bool is_enabled() const - UNIV_NOTHROW - { - return(m_active); - } - -private: - /* Disable copying */ - LatchCounter(const LatchCounter&); - LatchCounter& operator=(const LatchCounter&); - -private: - typedef OSMutex Mutex; - typedef std::vector<Count*> Counters; - - /** Mutex protecting m_counters */ - Mutex m_mutex; - - /** Counters for the latches */ - Counters m_counters; - - /** if true then we collect the data */ - bool m_active; -}; - -/** Latch meta data */ -template <typename Counter = LatchCounter> -class LatchMeta { - -public: - typedef Counter CounterType; - -#ifdef UNIV_PFS_MUTEX - typedef mysql_pfs_key_t pfs_key_t; -#endif /* UNIV_PFS_MUTEX */ - - /** Constructor */ - LatchMeta() - : - m_id(LATCH_ID_NONE), - m_name(), - m_level(SYNC_UNKNOWN), - m_level_name() -#ifdef UNIV_PFS_MUTEX - ,m_pfs_key() -#endif /* UNIV_PFS_MUTEX */ - { - } - - /** Destructor */ - ~LatchMeta() { } - - /** Constructor - @param[in] id Latch id - @param[in] name Latch name - @param[in] level Latch level - @param[in] level_name Latch level text representation - @param[in] key PFS key */ - LatchMeta( - latch_id_t id, - const char* name, - latch_level_t level, - const char* level_name -#ifdef UNIV_PFS_MUTEX - ,pfs_key_t key -#endif /* UNIV_PFS_MUTEX */ - ) - : - m_id(id), - m_name(name), - m_level(level), - m_level_name(level_name) -#ifdef UNIV_PFS_MUTEX - ,m_pfs_key(key) -#endif /* UNIV_PFS_MUTEX */ - { - /* No op */ - } - - /* Less than operator. - @param[in] rhs Instance to compare against - @return true if this.get_id() < rhs.get_id() */ - bool operator<(const LatchMeta& rhs) const - { - return(get_id() < rhs.get_id()); - } - - /** @return the latch id */ - latch_id_t get_id() const - { - return(m_id); - } - - /** @return the latch name */ - const char* get_name() const - { - return(m_name); - } - - /** @return the latch level */ - latch_level_t get_level() const - { - return(m_level); - } - - /** @return the latch level name */ - const char* get_level_name() const - { - return(m_level_name); - } - -#ifdef UNIV_PFS_MUTEX - /** @return the PFS key for the latch */ - pfs_key_t get_pfs_key() const - { - return(m_pfs_key); - } -#endif /* UNIV_PFS_MUTEX */ - - /** @return the counter instance */ - Counter* get_counter() - { - return(&m_counter); - } - -private: - /** Latch id */ - latch_id_t m_id; - - /** Latch name */ - const char* m_name; - - /** Latch level in the ordering */ - latch_level_t m_level; - - /** Latch level text representation */ - const char* m_level_name; - -#ifdef UNIV_PFS_MUTEX - /** PFS key */ - pfs_key_t m_pfs_key; -#endif /* UNIV_PFS_MUTEX */ - - /** For gathering latch statistics */ - Counter m_counter; -}; - -typedef LatchMeta<LatchCounter> latch_meta_t; -typedef std::vector<latch_meta_t*, ut_allocator<latch_meta_t*> > LatchMetaData; - -/** Note: This is accessed without any mutex protection. It is initialised -at startup and elements should not be added to or removed from it after -that. See sync_latch_meta_init() */ -extern LatchMetaData latch_meta; - -/** Get the latch meta-data from the latch ID -@param[in] id Latch ID -@return the latch meta data */ -inline -latch_meta_t& -sync_latch_get_meta(latch_id_t id) -{ - ut_ad(static_cast<size_t>(id) < latch_meta.size()); - ut_ad(id == latch_meta[id]->get_id()); - - return(*latch_meta[id]); -} - -/** Fetch the counter for the latch -@param[in] id Latch ID -@return the latch counter */ -inline -latch_meta_t::CounterType* -sync_latch_get_counter(latch_id_t id) -{ - latch_meta_t& meta = sync_latch_get_meta(id); - - return(meta.get_counter()); -} - -/** Get the latch name from the latch ID -@param[in] id Latch ID -@return the name, will assert if not found */ -inline -const char* -sync_latch_get_name(latch_id_t id) -{ - const latch_meta_t& meta = sync_latch_get_meta(id); - - return(meta.get_name()); -} - -/** Get the latch ordering level -@param[in] id Latch id to lookup -@return the latch level */ -inline -latch_level_t -sync_latch_get_level(latch_id_t id) -{ - const latch_meta_t& meta = sync_latch_get_meta(id); - - return(meta.get_level()); -} - -#ifdef UNIV_PFS_MUTEX -/** Get the latch PFS key from the latch ID -@param[in] id Latch ID -@return the PFS key */ -inline -mysql_pfs_key_t -sync_latch_get_pfs_key(latch_id_t id) -{ - const latch_meta_t& meta = sync_latch_get_meta(id); - - return(meta.get_pfs_key()); -} -#endif - -/** String representation of the filename and line number where the -latch was created -@param[in] id Latch ID -@param[in] created Filename and line number where it was crated -@return the string representation */ -std::string -sync_mutex_to_string( - latch_id_t id, - const std::string& created); - -/** Get the latch name from a sync level -@param[in] level Latch level to lookup -@return 0 if not found. */ -const char* -sync_latch_get_name(latch_level_t level); - -/** Print the filename "basename" -@return the basename */ -const char* -sync_basename(const char* filename); - -#ifdef UNIV_DEBUG - -/** All (ordered) latches, used in debugging, must derive from this class. */ -struct latch_t { - - /** Constructor - @param[in] id The latch ID */ - explicit latch_t(latch_id_t id = LATCH_ID_NONE) - UNIV_NOTHROW - : m_id(id) {} - - /** Destructor */ - virtual ~latch_t() UNIV_NOTHROW { } - - /** @return the latch ID */ - latch_id_t get_id() const - { - return(m_id); - } - - /** Print the latch context - @return the string representation */ - virtual std::string to_string() const = 0; - - /** @return the latch level */ - latch_level_t get_level() const - UNIV_NOTHROW - { - ut_a(m_id != LATCH_ID_NONE); - - return(sync_latch_get_level(m_id)); - } - - /** @return the latch name, m_id must be set */ - const char* get_name() const - UNIV_NOTHROW - { - ut_a(m_id != LATCH_ID_NONE); - - return(sync_latch_get_name(m_id)); - } - - /** Latch ID */ - latch_id_t m_id; -}; - -/** Subclass this to iterate over a thread's acquired latch levels. */ -struct sync_check_functor_t { - virtual ~sync_check_functor_t() { } - virtual bool operator()(const latch_level_t) const = 0; -}; - -/** Check that no latch is being held. -@tparam some_allowed whether some latches are allowed to be held */ -template<bool some_allowed = false> -struct sync_checker : public sync_check_functor_t -{ - /** Check the latching constraints - @param[in] level The level held by the thread - @return whether a latch violation was detected */ - bool operator()(const latch_level_t level) const override - { - if (some_allowed) { - switch (level) { - case SYNC_DICT: - case SYNC_NO_ORDER_CHECK: - return(false); - default: - return(true); - } - } - - return(true); - } -}; - -/** The strict latch checker (no InnoDB latches may be held) */ -typedef struct sync_checker<false> sync_check; -/** The sloppy latch checker (can hold InnoDB dictionary or SQL latches) */ -typedef struct sync_checker<true> dict_sync_check; - -/** Functor to check for given latching constraints. */ -struct sync_allowed_latches : public sync_check_functor_t { - - /** Constructor - @param[in] from first element in an array of latch_level_t - @param[in] to last element in an array of latch_level_t */ - sync_allowed_latches( - const latch_level_t* from, - const latch_level_t* to) - : begin(from), end(to) { } - - /** Checks whether the given latch_t violates the latch constraint. - This object maintains a list of allowed latch levels, and if the given - latch belongs to a latch level that is not there in the allowed list, - then it is a violation. - - @param[in] latch The latch level to check - @return true if there is a latch violation */ - bool operator()(const latch_level_t level) const override - { - return(std::find(begin, end, level) == end); - } - -private: - /** First element in an array of allowed latch levels */ - const latch_level_t* const begin; - /** First element after the end of the array of allowed latch levels */ - const latch_level_t* const end; -}; - -/** Get the latch id from a latch name. -@param[in] id Latch name -@return LATCH_ID_NONE. */ -latch_id_t -sync_latch_get_id(const char* name); -#endif /* UNIV_DBEUG */ - -#endif /* UNIV_INNOCHECKSUM */ - -/** Simple non-atomic counter aligned to CACHE_LINE_SIZE -@tparam Type the integer type of the counter */ -template <typename Type> -struct MY_ALIGNED(CPU_LEVEL1_DCACHE_LINESIZE) simple_counter -{ - /** Increment the counter */ - Type inc() { return add(1); } - /** Decrement the counter */ - Type dec() { return add(Type(~0)); } - - /** Add to the counter - @param[in] i amount to be added - @return the value of the counter after adding */ - Type add(Type i) { return m_counter += i; } - - /** @return the value of the counter */ - operator Type() const { return m_counter; } - -private: - /** The counter */ - Type m_counter; -}; -#endif /* sync0types_h */ diff --git a/storage/innobase/include/trx0purge.h b/storage/innobase/include/trx0purge.h index 7af880ef21e..fd9ccfd386e 100644 --- a/storage/innobase/include/trx0purge.h +++ b/storage/innobase/include/trx0purge.h @@ -190,7 +190,7 @@ public: purge_pq_t purge_queue; /*!< Binary min-heap, ordered on TrxUndoRsegs::trx_no. It is protected by the pq_mutex */ - PQMutex pq_mutex; /*!< Mutex protecting purge_queue */ + mysql_mutex_t pq_mutex; /*!< Mutex protecting purge_queue */ /** Undo tablespace file truncation (only accessed by the srv_purge_coordinator_thread) */ diff --git a/storage/innobase/include/trx0rseg.h b/storage/innobase/include/trx0rseg.h index a3ccc90b630..a42c1a0433a 100644 --- a/storage/innobase/include/trx0rseg.h +++ b/storage/innobase/include/trx0rseg.h @@ -30,6 +30,11 @@ Created 3/26/1996 Heikki Tuuri #include "trx0sys.h" #include "fut0lst.h" +#ifdef UNIV_PFS_MUTEX +extern mysql_pfs_key_t redo_rseg_mutex_key; +extern mysql_pfs_key_t noredo_rseg_mutex_key; +#endif /* UNIV_PFS_MUTEX */ + /** Gets a rollback segment header. @param[in] space space where placed @param[in] page_no page number of the header @@ -100,7 +105,7 @@ struct trx_rseg_t { /** mutex protecting the fields in this struct except id,space,page_no which are constant */ - RsegMutex mutex; + mysql_mutex_t mutex; /** space where the rollback segment header is placed */ fil_space_t* space; diff --git a/storage/innobase/include/trx0sys.h b/storage/innobase/include/trx0sys.h index d9707eae4ae..f99ef4eb7ce 100644 --- a/storage/innobase/include/trx0sys.h +++ b/storage/innobase/include/trx0sys.h @@ -24,9 +24,7 @@ Transaction system Created 3/26/1996 Heikki Tuuri *******************************************************/ -#ifndef trx0sys_h -#define trx0sys_h - +#pragma once #include "buf0buf.h" #include "fil0fil.h" #include "trx0types.h" @@ -36,12 +34,17 @@ Created 3/26/1996 Heikki Tuuri #include "ut0lst.h" #include "read0types.h" #include "page0types.h" -#include "ut0mutex.h" #include "trx0trx.h" #ifdef WITH_WSREP #include "trx0xa.h" #endif /* WITH_WSREP */ #include "ilist.h" +#include "my_cpu.h" + +#ifdef UNIV_PFS_MUTEX +extern mysql_pfs_key_t trx_sys_mutex_key; +extern mysql_pfs_key_t rw_trx_hash_element_mutex_key; +#endif /** Checks if a page address is the trx sys header page. @param[in] page_id page id @@ -345,13 +348,13 @@ struct rw_trx_hash_element_t { rw_trx_hash_element_t(): trx(0) { - mutex_create(LATCH_ID_RW_TRX_HASH_ELEMENT, &mutex); + mysql_mutex_init(rw_trx_hash_element_mutex_key, &mutex, nullptr); } ~rw_trx_hash_element_t() { - mutex_free(&mutex); + mysql_mutex_destroy(&mutex); } @@ -365,7 +368,7 @@ struct rw_trx_hash_element_t */ Atomic_counter<trx_id_t> no; trx_t *trx; - ib_mutex_t mutex; + mysql_mutex_t mutex; }; @@ -534,10 +537,10 @@ class rw_trx_hash_t static my_bool debug_iterator(rw_trx_hash_element_t *element, debug_iterator_arg<T> *arg) { - mutex_enter(&element->mutex); + mysql_mutex_lock(&element->mutex); if (element->trx) validate_element(element->trx); - mutex_exit(&element->mutex); + mysql_mutex_unlock(&element->mutex); return arg->action(element, arg->argument); } #endif @@ -639,7 +642,7 @@ public: sizeof(trx_id_t))); if (element) { - mutex_enter(&element->mutex); + mysql_mutex_lock(&element->mutex); lf_hash_search_unpin(pins); if ((trx= element->trx)) { DBUG_ASSERT(trx_id == trx->id); @@ -660,7 +663,7 @@ public: trx->reference(); } } - mutex_exit(&element->mutex); + mysql_mutex_unlock(&element->mutex); } if (!caller_trx) lf_hash_put_pins(pins); @@ -694,9 +697,9 @@ public: void erase(trx_t *trx) { ut_d(validate_element(trx)); - mutex_enter(&trx->rw_trx_hash_element->mutex); + mysql_mutex_lock(&trx->rw_trx_hash_element->mutex); trx->rw_trx_hash_element->trx= 0; - mutex_exit(&trx->rw_trx_hash_element->mutex); + mysql_mutex_unlock(&trx->rw_trx_hash_element->mutex); int res= lf_hash_delete(&hash, get_pins(trx), reinterpret_cast<const void*>(&trx->id), sizeof(trx_id_t)); @@ -730,12 +733,12 @@ public: May return element with committed transaction. If caller doesn't like to see committed transactions, it has to skip those under element mutex: - mutex_enter(&element->mutex); + mysql_mutex_lock(&element->mutex); if (trx_t trx= element->trx) { // trx is protected against commit in this branch } - mutex_exit(&element->mutex); + mysql_mutex_unlock(&element->mutex); May miss concurrently inserted transactions. @@ -796,44 +799,44 @@ public: class thread_safe_trx_ilist_t { public: - void create() { mutex_create(LATCH_ID_TRX_SYS, &mutex); } - void close() { mutex_free(&mutex); } + void create() { mysql_mutex_init(trx_sys_mutex_key, &mutex, nullptr); } + void close() { mysql_mutex_destroy(&mutex); } bool empty() const { - mutex_enter(&mutex); + mysql_mutex_lock(&mutex); auto result= trx_list.empty(); - mutex_exit(&mutex); + mysql_mutex_unlock(&mutex); return result; } void push_front(trx_t &trx) { - mutex_enter(&mutex); + mysql_mutex_lock(&mutex); trx_list.push_front(trx); - mutex_exit(&mutex); + mysql_mutex_unlock(&mutex); } void remove(trx_t &trx) { - mutex_enter(&mutex); + mysql_mutex_lock(&mutex); trx_list.remove(trx); - mutex_exit(&mutex); + mysql_mutex_unlock(&mutex); } template <typename Callable> void for_each(Callable &&callback) const { - mutex_enter(&mutex); + mysql_mutex_lock(&mutex); for (const auto &trx : trx_list) callback(trx); - mutex_exit(&mutex); + mysql_mutex_unlock(&mutex); } - void freeze() const { mutex_enter(&mutex); } - void unfreeze() const { mutex_exit(&mutex); } + void freeze() const { mysql_mutex_lock(&mutex); } + void unfreeze() const { mysql_mutex_unlock(&mutex); } private: - alignas(CACHE_LINE_SIZE) mutable TrxSysMutex mutex; + alignas(CACHE_LINE_SIZE) mutable mysql_mutex_t mutex; alignas(CACHE_LINE_SIZE) ilist<trx_t> trx_list; }; @@ -1148,11 +1151,11 @@ private: { if (element->id < *id) { - mutex_enter(&element->mutex); + mysql_mutex_lock(&element->mutex); /* We don't care about read-only transactions here. */ if (element->trx && element->trx->rsegs.m_redo.rseg) *id= element->id; - mutex_exit(&element->mutex); + mysql_mutex_unlock(&element->mutex); } return 0; } @@ -1217,5 +1220,3 @@ private: /** The transaction system */ extern trx_sys_t trx_sys; - -#endif diff --git a/storage/innobase/include/trx0types.h b/storage/innobase/include/trx0types.h index 24e07e7ebbf..aa5293ca996 100644 --- a/storage/innobase/include/trx0types.h +++ b/storage/innobase/include/trx0types.h @@ -24,11 +24,9 @@ Transaction system global type definitions Created 3/26/1996 Heikki Tuuri *******************************************************/ -#ifndef trx0types_h -#define trx0types_h - -#include "ut0byte.h" -#include "ut0mutex.h" +#pragma once +#include "univ.i" +#include "ut0new.h" #include <vector> @@ -135,9 +133,4 @@ typedef byte trx_undo_rec_t; /* @} */ -typedef ib_mutex_t RsegMutex; -typedef ib_mutex_t PQMutex; -typedef ib_mutex_t TrxSysMutex; - typedef std::vector<trx_id_t, ut_allocator<trx_id_t> > trx_ids_t; -#endif /* trx0types_h */ diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i index 18c228e56c3..2091bd70500 100644 --- a/storage/innobase/include/univ.i +++ b/storage/innobase/include/univ.i @@ -31,8 +31,7 @@ Version control for database, common definitions, and include files Created 1/20/1994 Heikki Tuuri ****************************************************************************/ -#ifndef univ_i -#define univ_i +#pragma once /* aux macros to convert M into "123" (string) if M is defined like #define M 123 */ @@ -194,8 +193,6 @@ using the call command. */ related stuff. */ #define UNIV_SEARCH_PERF_STAT /* statistics for the adaptive hash index */ -#define UNIV_SRV_PRINT_LATCH_WAITS /* enable diagnostic output - in sync0sync.cc */ #define UNIV_BTR_PRINT /* enable functions for printing B-trees */ #define UNIV_ZIP_DEBUG /* extensive consistency checks @@ -563,7 +560,6 @@ typedef void* os_thread_ret_t; #include "ut0dbg.h" #include "ut0lst.h" #include "ut0ut.h" -#include "sync0types.h" extern ulong srv_page_size_shift; extern ulong srv_page_size; @@ -572,4 +568,53 @@ extern ulong srv_page_size; myisam/sp_defs.h. We only support 2 dimension data */ #define SPDIMS 2 -#endif +#ifdef HAVE_PSI_INTERFACE +typedef unsigned int mysql_pfs_key_t; + +# ifdef UNIV_PFS_MUTEX +extern mysql_pfs_key_t buf_pool_mutex_key; +extern mysql_pfs_key_t dict_foreign_err_mutex_key; +extern mysql_pfs_key_t dict_sys_mutex_key; +extern mysql_pfs_key_t fil_system_mutex_key; +extern mysql_pfs_key_t flush_list_mutex_key; +extern mysql_pfs_key_t fts_cache_mutex_key; +extern mysql_pfs_key_t fts_cache_init_mutex_key; +extern mysql_pfs_key_t fts_delete_mutex_key; +extern mysql_pfs_key_t fts_doc_id_mutex_key; +extern mysql_pfs_key_t fts_pll_tokenize_mutex_key; +extern mysql_pfs_key_t ibuf_bitmap_mutex_key; +extern mysql_pfs_key_t ibuf_mutex_key; +extern mysql_pfs_key_t ibuf_pessimistic_insert_mutex_key; +extern mysql_pfs_key_t log_sys_mutex_key; +extern mysql_pfs_key_t log_cmdq_mutex_key; +extern mysql_pfs_key_t log_flush_order_mutex_key; +extern mysql_pfs_key_t recalc_pool_mutex_key; +extern mysql_pfs_key_t purge_sys_pq_mutex_key; +extern mysql_pfs_key_t recv_sys_mutex_key; +extern mysql_pfs_key_t rtr_active_mutex_key; +extern mysql_pfs_key_t rtr_match_mutex_key; +extern mysql_pfs_key_t rtr_path_mutex_key; +extern mysql_pfs_key_t page_zip_stat_per_index_mutex_key; +extern mysql_pfs_key_t srv_innodb_monitor_mutex_key; +extern mysql_pfs_key_t srv_misc_tmpfile_mutex_key; +extern mysql_pfs_key_t srv_monitor_file_mutex_key; +extern mysql_pfs_key_t buf_dblwr_mutex_key; +extern mysql_pfs_key_t trx_pool_mutex_key; +extern mysql_pfs_key_t trx_pool_manager_mutex_key; +extern mysql_pfs_key_t lock_mutex_key; +extern mysql_pfs_key_t lock_wait_mutex_key; +extern mysql_pfs_key_t srv_threads_mutex_key; +extern mysql_pfs_key_t thread_mutex_key; +extern mysql_pfs_key_t row_drop_list_mutex_key; +# endif /* UNIV_PFS_MUTEX */ + +# ifdef UNIV_PFS_RWLOCK +extern mysql_pfs_key_t dict_operation_lock_key; +extern mysql_pfs_key_t fil_space_latch_key; +extern mysql_pfs_key_t trx_i_s_cache_lock_key; +extern mysql_pfs_key_t trx_purge_latch_key; +extern mysql_pfs_key_t index_tree_rw_lock_key; +extern mysql_pfs_key_t index_online_log_key; +extern mysql_pfs_key_t trx_sys_rw_lock_key; +# endif /* UNIV_PFS_RWLOCK */ +#endif /* HAVE_PSI_INTERFACE */ diff --git a/storage/innobase/include/ut0mutex.h b/storage/innobase/include/ut0mutex.h deleted file mode 100644 index 89c903b48f1..00000000000 --- a/storage/innobase/include/ut0mutex.h +++ /dev/null @@ -1,174 +0,0 @@ -/***************************************************************************** - -Copyright (c) 2012, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2020, 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, Fifth Floor, Boston, MA 02110-1335 USA - -*****************************************************************************/ - -/******************************************************************//** -@file include/ut0mutex.h -Policy based mutexes. - -Created 2012-03-24 Sunny Bains. -***********************************************************************/ - -#pragma once -#ifndef UNIV_INNOCHECKSUM -#include "sync0policy.h" -#include "ib0mutex.h" - -/** Create a typedef using the MutexType<PolicyType> -@param[in] M Mutex type -@param[in[ P Policy type -@param[in] T The resulting typedef alias */ -#define UT_MUTEX_TYPE(M, P, T) typedef PolicyMutex<M<P> > T; - -# ifdef __linux__ -UT_MUTEX_TYPE(TTASFutexMutex, GenericPolicy, FutexMutex); -# endif /* __linux__ */ - -UT_MUTEX_TYPE(TTASMutex, GenericPolicy, SpinMutex); -UT_MUTEX_TYPE(OSTrackMutex, GenericPolicy, SysMutex); - -#ifdef MUTEX_FUTEX -/** The default mutex type. */ -typedef FutexMutex ib_mutex_t; -#define MUTEX_TYPE "Uses futexes" -#elif defined(MUTEX_SYS) -typedef SysMutex ib_mutex_t; -#define MUTEX_TYPE "Uses system mutexes" -#else -#error "ib_mutex_t type is unknown" -#endif /* MUTEX_FUTEX */ - -extern uint srv_spin_wait_delay; -extern ulong srv_n_spin_wait_rounds; - -#define mutex_create(I, M) mutex_init((M), (I), \ - __FILE__, __LINE__) - -#define mutex_enter_loc(M,file,line) (M)->enter( \ - uint32_t(srv_n_spin_wait_rounds), \ - uint32_t(srv_spin_wait_delay), \ - file, line) -#define mutex_enter(M) mutex_enter_loc(M, __FILE__, __LINE__) - -#define mutex_enter_nospin(M) (M)->enter( \ - 0, \ - 0, \ - __FILE__, uint32_t(__LINE__)) - -#define mutex_enter_nowait(M) (M)->trylock(__FILE__, \ - uint32_t(__LINE__)) - -#define mutex_exit(M) (M)->exit() - -#define mutex_free(M) mutex_destroy(M) - -#ifdef UNIV_DEBUG -/** -Checks that the mutex has been initialized. */ -#define mutex_validate(M) (M)->validate() - -/** -Checks that the current thread owns the mutex. Works only -in the debug version. */ -#define mutex_own(M) (M)->is_owned() -#else -#define mutex_own(M) /* No op */ -#define mutex_validate(M) /* No op */ -#endif /* UNIV_DEBUG */ - -/** Iterate over the mutex meta data */ -class MutexMonitor { -public: - /** Constructor */ - MutexMonitor() { } - - /** Destructor */ - ~MutexMonitor() { } - - /** Enable the mutex monitoring */ - void enable(); - - /** Disable the mutex monitoring */ - void disable(); - - /** Reset the mutex monitoring values */ - void reset(); - - /** Invoke the callback for each active mutex collection - @param[in,out] callback Functor to call - @return false if callback returned false */ - template<typename Callback> - bool iterate(Callback& callback) const - UNIV_NOTHROW - { - LatchMetaData::iterator end = latch_meta.end(); - - for (LatchMetaData::iterator it = latch_meta.begin(); - it != end; - ++it) { - - /* Some of the slots will be null in non-debug mode */ - - if (latch_meta_t* l= *it) { - if (!callback(*l)) { - return false; - } - } - } - - return(true); - } -}; - -/** Defined in sync0sync.cc */ -extern MutexMonitor mutex_monitor; - -/** -Creates, or rather, initializes a mutex object in a specified memory -location (which must be appropriately aligned). The mutex is initialized -in the reset state. Explicit freeing of the mutex with mutex_free is -necessary only if the memory block containing it is freed. -Add the mutex instance to the global mutex list. -@param[in,out] mutex mutex to initialise -@param[in] id The mutex ID (Latch ID) -@param[in] filename Filename from where it was called -@param[in] line Line number in filename from where called */ -template <typename Mutex> -void mutex_init( - Mutex* mutex, - latch_id_t id, - const char* file_name, - uint32_t line) -{ - new(mutex) Mutex(); - - mutex->init(id, file_name, line); -} - -/** -Removes a mutex instance from the mutex list. The mutex is checked to -be in the reset state. -@param[in,out] mutex mutex instance to destroy */ -template <typename Mutex> -void mutex_destroy( - Mutex* mutex) -{ - mutex->destroy(); -} - -#endif /* UNIV_INNOCHECKSUM */ diff --git a/storage/innobase/include/ut0new.h b/storage/innobase/include/ut0new.h index 3fc7664c34e..47198dbff99 100644 --- a/storage/innobase/include/ut0new.h +++ b/storage/innobase/include/ut0new.h @@ -878,9 +878,6 @@ constexpr const char* const auto_event_names[] = "row0mysql", "row0sel", "srv0start", - "sync0debug", - "sync0start", - "sync0types", "trx0i_s", "trx0i_s", "trx0roll", diff --git a/storage/innobase/include/ut0wqueue.h b/storage/innobase/include/ut0wqueue.h index 5c9fd98ea9c..dff8183b6c9 100644 --- a/storage/innobase/include/ut0wqueue.h +++ b/storage/innobase/include/ut0wqueue.h @@ -33,7 +33,6 @@ processing. #pragma once #include "ut0list.h" -#include "ut0mutex.h" #include "mem0mem.h" // Forward declaration |