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 | |
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')
108 files changed, 1482 insertions, 5016 deletions
diff --git a/storage/innobase/CMakeLists.txt b/storage/innobase/CMakeLists.txt index 5a5c268763a..2b0ab4ec0b1 100644 --- a/storage/innobase/CMakeLists.txt +++ b/storage/innobase/CMakeLists.txt @@ -163,7 +163,6 @@ SET(INNOBASE_SOURCES include/ha0storage.ic include/handler0alter.h include/hash0hash.h - include/ib0mutex.h include/ibuf0ibuf.h include/ibuf0ibuf.ic include/ibuf0types.h @@ -238,11 +237,7 @@ SET(INNOBASE_SOURCES include/srv0mon.ic include/srv0srv.h include/srv0start.h - include/sync0debug.h - include/sync0policy.h include/sux_lock.h - include/sync0sync.h - include/sync0types.h include/trx0i_s.h include/trx0purge.h include/trx0rec.h @@ -267,7 +262,6 @@ SET(INNOBASE_SOURCES include/ut0lst.h include/ut0mem.h include/ut0mem.ic - include/ut0mutex.h include/ut0new.h include/ut0pool.h include/ut0rbt.h @@ -324,8 +318,6 @@ SET(INNOBASE_SOURCES srv/srv0srv.cc srv/srv0start.cc sync/srw_lock.cc - sync/sync0debug.cc - sync/sync0sync.cc trx/trx0i_s.cc trx/trx0purge.cc trx/trx0rec.cc diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc index 1892dae01f5..ded701af612 100644 --- a/storage/innobase/btr/btr0btr.cc +++ b/storage/innobase/btr/btr0btr.cc @@ -388,11 +388,11 @@ btr_root_adjust_on_import( tf &= ~FSP_FLAGS_MEM_MASK; if (fil_space_t::is_flags_equal(tf, sf) || fil_space_t::is_flags_equal(sf, tf)) { - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); table->space->flags = (table->space->flags & ~FSP_FLAGS_MEM_MASK) | (tf & FSP_FLAGS_MEM_MASK); - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); err = DB_SUCCESS; } else { err = DB_CORRUPTION; @@ -3293,10 +3293,10 @@ btr_lift_page_up( if (!dict_table_is_locking_disabled(index->table)) { /* Free predicate page locks on the block */ if (dict_index_is_spatial(index)) { - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); lock_prdt_page_free_from_discard( block, &lock_sys.prdt_page_hash); - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); } lock_update_copy_and_discard(father_block, block); } @@ -3546,11 +3546,11 @@ retry: } /* No GAP lock needs to be worrying about */ - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); lock_prdt_page_free_from_discard( block, &lock_sys.prdt_page_hash); lock_rec_free_all_from_discard_page(block); - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); } else { btr_cur_node_ptr_delete(&father_cursor, mtr); if (!dict_table_is_locking_disabled(index->table)) { @@ -3699,11 +3699,11 @@ retry: offsets2, offsets, merge_page, mtr); } - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); lock_prdt_page_free_from_discard( block, &lock_sys.prdt_page_hash); lock_rec_free_all_from_discard_page(block); - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); } else { compressed = btr_cur_pessimistic_delete(&err, TRUE, diff --git a/storage/innobase/btr/btr0bulk.cc b/storage/innobase/btr/btr0bulk.cc index e763acd777a..0dbcfd7af25 100644 --- a/storage/innobase/btr/btr0bulk.cc +++ b/storage/innobase/btr/btr0bulk.cc @@ -1222,8 +1222,6 @@ BtrBulk::finish(dberr_t err) ut_ad(err == DB_SUCCESS); } - ut_ad(!sync_check_iterate(dict_sync_check())); - ut_ad(err != DB_SUCCESS || btr_validate_index(m_index, NULL) == DB_SUCCESS); return(err); diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index 33d7c833819..2f4db18ca50 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -1997,11 +1997,11 @@ retry_page_get: trx_t* trx = thr_get_trx(cursor->thr); lock_prdt_t prdt; - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); lock_init_prdt_from_mbr( &prdt, &cursor->rtr_info->mbr, mode, trx->lock.lock_heap); - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); if (rw_latch == RW_NO_LATCH && height != 0) { block->lock.s_lock(); diff --git a/storage/innobase/btr/btr0sea.cc b/storage/innobase/btr/btr0sea.cc index 87f896ee8b8..e29e4a35d72 100644 --- a/storage/innobase/btr/btr0sea.cc +++ b/storage/innobase/btr/btr0sea.cc @@ -223,12 +223,12 @@ void btr_search_disable() { dict_table_t* table; - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); btr_search_x_lock_all(); if (!btr_search_enabled) { - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); btr_search_x_unlock_all(); return; } @@ -249,7 +249,7 @@ void btr_search_disable() btr_search_disable_ref_count(table); } - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); /* Set all block->index = NULL. */ buf_pool.clear_hash_index(); @@ -1250,7 +1250,7 @@ retry: ut_ad(page_is_leaf(block->frame)); /* We must not dereference block->index here, because it could be freed - if (index->table->n_ref_count == 0 && !mutex_own(&dict_sys.mutex)). + if (index->table->n_ref_count == 0). Determine the ahi_slot based on the block contents. */ const index_id_t index_id @@ -1410,8 +1410,10 @@ void btr_search_drop_page_hash_when_freed(const page_id_t page_id) /* In all our callers, the table handle should be open, or we should be in the process of dropping the table (preventing eviction). */ - ut_ad(block->index->table->get_ref_count() > 0 - || mutex_own(&dict_sys.mutex)); +#ifdef SAFE_MUTEX + DBUG_ASSERT(block->index->table->get_ref_count() + || dict_sys.mutex_is_locked()); +#endif /* SAFE_MUTEX */ btr_search_drop_page_hash_index(block); } } diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 04d48bbc217..d15794e2856 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -63,7 +63,6 @@ Created 11/5/1995 Heikki Tuuri #include "fil0pagecompress.h" #endif /* !UNIV_INNOCHECKSUM */ #include "page0zip.h" -#include "sync0sync.h" #include "buf0dump.h" #include <map> #include <sstream> @@ -2035,11 +2034,11 @@ withdraw_retry: message_interval *= 2; } - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); bool found = false; trx_sys.trx_list.for_each(find_interesting_trx{ found, withdraw_started, current_time}); - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); withdraw_started = current_time; } diff --git a/storage/innobase/buf/buf0dblwr.cc b/storage/innobase/buf/buf0dblwr.cc index c1d343be50a..c13e41b600d 100644 --- a/storage/innobase/buf/buf0dblwr.cc +++ b/storage/innobase/buf/buf0dblwr.cc @@ -29,7 +29,6 @@ Created 2011/12/19 #include "buf0checksum.h" #include "srv0start.h" #include "srv0srv.h" -#include "sync0sync.h" #include "page0zip.h" #include "trx0sys.h" #include "fil0crypt.h" diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index c92c3264535..07606cb682c 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -241,8 +241,6 @@ void buf_flush_remove_pages(ulint id) @return number dirty pages that there were for this tablespace */ ulint buf_flush_dirty_pages(ulint id) { - ut_ad(!sync_check_iterate(dict_sync_check())); - ulint n= 0; mysql_mutex_lock(&buf_pool.flush_list_mutex); @@ -2289,8 +2287,6 @@ ATTRIBUTE_COLD void buf_flush_buffer_pool() NOTE: The calling thread is not allowed to hold any buffer page latches! */ void buf_flush_sync() { - ut_ad(!sync_check_iterate(dict_sync_check())); - for (;;) { const ulint n_flushed= buf_flush_lists(srv_max_io_capacity, LSN_MAX); diff --git a/storage/innobase/buf/buf0lru.cc b/storage/innobase/buf/buf0lru.cc index 020275850f2..3faba416ee4 100644 --- a/storage/innobase/buf/buf0lru.cc +++ b/storage/innobase/buf/buf0lru.cc @@ -37,6 +37,7 @@ Created 11/5/1995 Heikki Tuuri #include "log0recv.h" #include "srv0srv.h" #include "srv0mon.h" +#include "my_cpu.h" /** Flush this many pages in buf_LRU_get_free_block() */ size_t innodb_lru_flush_size; diff --git a/storage/innobase/dict/dict0boot.cc b/storage/innobase/dict/dict0boot.cc index cace5166ad9..e9c900a9f1c 100644 --- a/storage/innobase/dict/dict0boot.cc +++ b/storage/innobase/dict/dict0boot.cc @@ -235,7 +235,7 @@ dict_boot(void) heap = mem_heap_create(450); - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); /* Get the dictionary header */ const byte* dict_hdr = &dict_hdr_get(&mtr)->frame[DICT_HDR]; @@ -429,7 +429,7 @@ dict_boot(void) dict_load_sys_table(dict_sys.sys_fields); } - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); return(err); } diff --git a/storage/innobase/dict/dict0crea.cc b/storage/innobase/dict/dict0crea.cc index a57d06d127a..563a37181fd 100644 --- a/storage/innobase/dict/dict0crea.cc +++ b/storage/innobase/dict/dict0crea.cc @@ -343,7 +343,7 @@ dict_build_table_def_step( que_thr_t* thr, /*!< in: query thread */ tab_node_t* node) /*!< in: table create node */ { - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); dict_table_t* table = node->table; trx_t* trx = thr_get_trx(thr); ut_ad(!table->is_temporary()); @@ -483,7 +483,7 @@ dict_create_sys_indexes_tuple( dfield_t* dfield; byte* ptr; - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); ut_ad(index); ut_ad(index->table->space || index->table->file_unreadable); ut_ad(!index->table->space @@ -712,7 +712,7 @@ dict_build_index_def_step( dtuple_t* row; trx_t* trx; - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); trx = thr_get_trx(thr); @@ -763,7 +763,7 @@ dict_build_index_def( dict_index_t* index, /*!< in/out: index */ trx_t* trx) /*!< in/out: InnoDB transaction handle */ { - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); if (trx->table_id == 0) { /* Record only the first table id. */ @@ -811,7 +811,7 @@ dict_create_index_tree_step( dict_index_t* index; dtuple_t* search_tuple; - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); index = node->index; @@ -880,7 +880,7 @@ dict_create_index_tree_in_mem( { mtr_t mtr; - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); ut_ad(!(index->type & DICT_FTS)); mtr_start(&mtr); @@ -910,7 +910,7 @@ void dict_drop_index_tree(btr_pcur_t* pcur, trx_t* trx, mtr_t* mtr) byte* ptr; ulint len; - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); ut_a(!dict_table_is_comp(dict_sys.sys_indexes)); ptr = rec_get_nth_field_old(rec, DICT_FLD__SYS_INDEXES__PAGE_NO, &len); @@ -1056,7 +1056,7 @@ dict_create_table_step( trx_t* trx; ut_ad(thr); - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); trx = thr_get_trx(thr); @@ -1199,7 +1199,7 @@ dict_create_index_step( trx_t* trx; ut_ad(thr); - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); trx = thr_get_trx(thr); @@ -1359,7 +1359,7 @@ dict_check_if_system_table_exists( ut_ad(!srv_any_background_activity()); - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); sys_table = dict_table_get_low(tablename); @@ -1377,7 +1377,7 @@ dict_check_if_system_table_exists( dict_table_prevent_eviction(sys_table); } - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); return(error); } @@ -1545,9 +1545,9 @@ dict_create_or_check_sys_virtual() "SYS_VIRTUAL", DICT_NUM_FIELDS__SYS_VIRTUAL + 1, 1); if (err == DB_SUCCESS) { - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); dict_sys.sys_virtual = dict_table_get_low("SYS_VIRTUAL"); - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); return(DB_SUCCESS); } @@ -1620,9 +1620,9 @@ dict_create_or_check_sys_virtual() dberr_t sys_virtual_err = dict_check_if_system_table_exists( "SYS_VIRTUAL", DICT_NUM_FIELDS__SYS_VIRTUAL + 1, 1); ut_a(sys_virtual_err == DB_SUCCESS); - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); dict_sys.sys_virtual = dict_table_get_low("SYS_VIRTUAL"); - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); return(err); } @@ -1646,7 +1646,7 @@ dict_foreign_eval_sql( error = que_eval_sql(info, sql, FALSE, trx); if (error == DB_DUPLICATE_KEY) { - mutex_enter(&dict_foreign_err_mutex); + mysql_mutex_lock(&dict_foreign_err_mutex); rewind(ef); ut_print_timestamp(ef); fputs(" Error in foreign key constraint creation for table ", @@ -1666,7 +1666,7 @@ dict_foreign_eval_sql( "explicitly with unique names.\n", ef); - mutex_exit(&dict_foreign_err_mutex); + mysql_mutex_unlock(&dict_foreign_err_mutex); return(error); } @@ -1675,7 +1675,7 @@ dict_foreign_eval_sql( ib::error() << "Foreign key constraint creation failed: " << error; - mutex_enter(&dict_foreign_err_mutex); + mysql_mutex_lock(&dict_foreign_err_mutex); ut_print_timestamp(ef); fputs(" Internal error in foreign key constraint creation" " for table ", ef); @@ -1683,7 +1683,7 @@ dict_foreign_eval_sql( fputs(".\n" "See the MySQL .err log in the datadir" " for more information.\n", ef); - mutex_exit(&dict_foreign_err_mutex); + mysql_mutex_unlock(&dict_foreign_err_mutex); return(error); } @@ -2019,7 +2019,7 @@ dict_create_add_foreigns_to_dictionary( dict_foreign_t* foreign; dberr_t error; - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); if (NULL == dict_table_get_low("SYS_FOREIGN")) { diff --git a/storage/innobase/dict/dict0defrag_bg.cc b/storage/innobase/dict/dict0defrag_bg.cc index 0d9cb185b81..26f38c9de40 100644 --- a/storage/innobase/dict/dict0defrag_bg.cc +++ b/storage/innobase/dict/dict0defrag_bg.cc @@ -30,11 +30,7 @@ Created 25/08/2016 Jan Lindström #include "btr0btr.h" #include "srv0start.h" -static ib_mutex_t defrag_pool_mutex; - -#ifdef MYSQL_PFS -static mysql_pfs_key_t defrag_pool_mutex_key; -#endif +static mysql_mutex_t defrag_pool_mutex; /** Iterator type for iterating over the elements of objects of type defrag_pool_t. */ @@ -52,9 +48,7 @@ dict_defrag_pool_init(void) /*=======================*/ { ut_ad(!srv_read_only_mode); - - /* We choose SYNC_STATS_DEFRAG to be below SYNC_FSP_PAGE. */ - mutex_create(LATCH_ID_DEFRAGMENT_MUTEX, &defrag_pool_mutex); + mysql_mutex_init(0, &defrag_pool_mutex, nullptr); } /*****************************************************************//** @@ -66,7 +60,7 @@ dict_defrag_pool_deinit(void) { ut_ad(!srv_read_only_mode); - mutex_free(&defrag_pool_mutex); + mysql_mutex_destroy(&defrag_pool_mutex); } /*****************************************************************//** @@ -84,10 +78,10 @@ dict_stats_defrag_pool_get( { ut_ad(!srv_read_only_mode); - mutex_enter(&defrag_pool_mutex); + mysql_mutex_lock(&defrag_pool_mutex); if (defrag_pool.empty()) { - mutex_exit(&defrag_pool_mutex); + mysql_mutex_unlock(&defrag_pool_mutex); return(false); } @@ -97,7 +91,7 @@ dict_stats_defrag_pool_get( defrag_pool.pop_back(); - mutex_exit(&defrag_pool_mutex); + mysql_mutex_unlock(&defrag_pool_mutex); return(true); } @@ -117,7 +111,7 @@ dict_stats_defrag_pool_add( ut_ad(!srv_read_only_mode); - mutex_enter(&defrag_pool_mutex); + mysql_mutex_lock(&defrag_pool_mutex); /* quit if already in the list */ for (defrag_pool_iterator_t iter = defrag_pool.begin(); @@ -125,7 +119,7 @@ dict_stats_defrag_pool_add( ++iter) { if ((*iter).table_id == index->table->id && (*iter).index_id == index->id) { - mutex_exit(&defrag_pool_mutex); + mysql_mutex_unlock(&defrag_pool_mutex); return; } } @@ -137,7 +131,7 @@ dict_stats_defrag_pool_add( /* Kick off dict stats optimizer work */ dict_stats_schedule_now(); } - mutex_exit(&defrag_pool_mutex); + mysql_mutex_unlock(&defrag_pool_mutex); } /*****************************************************************//** @@ -151,9 +145,9 @@ dict_stats_defrag_pool_del( { ut_a((table && !index) || (!table && index)); ut_ad(!srv_read_only_mode); - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); - mutex_enter(&defrag_pool_mutex); + mysql_mutex_lock(&defrag_pool_mutex); defrag_pool_iterator_t iter = defrag_pool.begin(); while (iter != defrag_pool.end()) { @@ -170,7 +164,7 @@ dict_stats_defrag_pool_del( } } - mutex_exit(&defrag_pool_mutex); + mysql_mutex_unlock(&defrag_pool_mutex); } /*****************************************************************//** @@ -193,7 +187,7 @@ dict_stats_process_entry_from_defrag_pool() dict_table_t* table; - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); /* If the table is no longer cached, we've already lost the in memory stats so there's nothing really to write to disk. */ @@ -208,11 +202,11 @@ dict_stats_process_entry_from_defrag_pool() if (table) { dict_table_close(table, TRUE, FALSE); } - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); return; } - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); dict_stats_save_defrag_stats(index); dict_table_close(table, FALSE, FALSE); } diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 0edaafc8503..f545bc5a7d6 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -72,7 +72,6 @@ extern uint ibuf_debug; #include "row0upd.h" #include "srv0mon.h" #include "srv0start.h" -#include "sync0sync.h" #include "trx0undo.h" #include <vector> @@ -81,6 +80,12 @@ extern uint ibuf_debug; /** the dictionary system */ dict_sys_t dict_sys; +/** Diagnostic message for exceeding the mutex_lock_wait() timeout */ +const char dict_sys_t::fatal_msg[]= + "innodb_fatal_semaphore_wait_threshold was exceeded for dict_sys.mutex. " + "Please refer to " + "https://mariadb.com/kb/en/how-to-produce-a-full-stack-trace-for-mysqld/"; + /** Percentage of compression failures that are allowed in a single round */ ulong zip_failure_threshold_pct = 5; @@ -168,7 +173,7 @@ dict_lru_validate(void); and unique key errors. Only created if !srv_read_only_mode */ FILE* dict_foreign_err_file = NULL; /* mutex protecting the foreign and unique error buffers */ -ib_mutex_t dict_foreign_err_mutex; +mysql_mutex_t dict_foreign_err_mutex; /********************************************************************//** Checks if the database name in two table names is the same. @@ -288,11 +293,11 @@ dict_table_try_drop_aborted_and_mutex_exit( was aborted. */ table_id_t table_id = table->id; - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); dict_table_try_drop_aborted(table, table_id, 1); } else { - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); } } @@ -313,10 +318,10 @@ dict_table_close( MDL_ticket* mdl) { if (!dict_locked) { - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); } - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); ut_a(table->get_ref_count() > 0); const bool last_handle = table->release(); @@ -343,7 +348,7 @@ dict_table_close( && table->drop_aborted && dict_table_get_first_index(table); - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); /* dict_table_try_drop_aborted() can generate undo logs. So it should be avoided after shutdown of background @@ -738,9 +743,8 @@ bool dict_table_t::parse_name(char (&db_name)[NAME_LEN + 1], char tbl_buf[MAX_TABLE_NAME_LEN + 1]; if (!dict_locked) - mutex_enter(&dict_sys.mutex); /* protect against renaming */ - else - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.mutex_lock(); /* protect against renaming */ + dict_sys.assert_locked(); const size_t db_len= name.dblen(); ut_ad(db_len <= MAX_DATABASE_NAME_LEN); @@ -761,7 +765,7 @@ bool dict_table_t::parse_name(char (&db_name)[NAME_LEN + 1], tbl_buf[tbl_len]= 0; if (!dict_locked) - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); *db_name_len= filename_to_tablename(db_buf, db_name, MAX_DATABASE_NAME_LEN + 1, true); @@ -801,13 +805,13 @@ dict_acquire_mdl_shared(dict_table_t *table, if (trylock) { - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); db_len= dict_get_db_name_len(table->name.m_name); - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); } else { - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); db_len= dict_get_db_name_len(table->name.m_name); } @@ -846,7 +850,7 @@ is_unaccessible: return nullptr; if (!trylock) - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); { MDL_request request; MDL_REQUEST_INIT(&request,MDL_key::TABLE, db_buf, tbl_buf, MDL_SHARED, MDL_EXPLICIT); @@ -867,7 +871,7 @@ is_unaccessible: } if (!trylock) - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); else if (!*mdl) return nullptr; @@ -940,10 +944,10 @@ dict_table_open_on_id(table_id_t table_id, bool dict_locked, ut_ad(!dict_locked || !thd); if (!dict_locked) { - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); } - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); dict_table_t* table = dict_table_open_on_id_low( table_id, @@ -1029,7 +1033,7 @@ void dict_sys_t::create() UT_LIST_INIT(table_LRU, &dict_table_t::table_LRU); UT_LIST_INIT(table_non_LRU, &dict_table_t::table_LRU); - mutex_create(LATCH_ID_DICT_SYS, &mutex); + mysql_mutex_init(dict_sys_mutex_key, &mutex, nullptr); const ulint hash_size = buf_pool_get_curr_size() / (DICT_POOL_PER_TABLE_HASH * UNIV_WORD_SIZE); @@ -1046,9 +1050,11 @@ void dict_sys_t::create() ut_a(dict_foreign_err_file); } - mutex_create(LATCH_ID_DICT_FOREIGN_ERR, &dict_foreign_err_mutex); + mysql_mutex_init(dict_foreign_err_mutex_key, &dict_foreign_err_mutex, + nullptr); } + /** Acquire a reference to a cached table. */ inline void dict_sys_t::acquire(dict_table_t* table) { @@ -1062,6 +1068,54 @@ inline void dict_sys_t::acquire(dict_table_t* table) table->acquire(); } +void dict_sys_t::mutex_lock_wait() +{ + ulonglong now= my_hrtime_coarse().val, old= 0; + if (mutex_wait_start.compare_exchange_strong + (old, now, std::memory_order_relaxed, std::memory_order_relaxed)) + { + mysql_mutex_lock(&mutex); + mutex_wait_start.store(0, std::memory_order_relaxed); + return; + } + + ut_ad(old); + /* We could have old > now due to our use of my_hrtime_coarse(). */ + ulong waited= old <= now ? static_cast<ulong>((now - old) / 1000000) : 0; + const ulong threshold= srv_fatal_semaphore_wait_threshold; + + if (waited >= threshold) + ib::fatal() << fatal_msg; + + if (waited > threshold / 4) + ib::warn() << "A long wait (" << waited + << " seconds) was observed for dict_sys.mutex"; + mysql_mutex_lock(&mutex); +} + +#ifdef HAVE_PSI_MUTEX_INTERFACE +/** Acquire the mutex */ +void dict_sys_t::mutex_lock() +{ + if (mysql_mutex_trylock(&mutex)) + mutex_lock_wait(); +} + +/** Release the mutex */ +void dict_sys_t::mutex_unlock() { mysql_mutex_unlock(&mutex); } +#endif + +/** Lock the data dictionary cache. */ +void dict_sys_t::lock(SRW_LOCK_ARGS(const char *file, unsigned line)) +{ + ut_ad(this == &dict_sys); + ut_ad(is_initialised()); + latch.wr_lock(SRW_LOCK_ARGS(file, line)); + ut_ad(!latch_ex); + ut_d(latch_ex= true); + mutex_lock(); +} + /**********************************************************************//** Returns a table object and increment its open handle count. NOTE! This is a high-level function to be used mainly from outside the @@ -1085,11 +1139,11 @@ dict_table_open_on_name( DBUG_PRINT("dict_table_open_on_name", ("table: '%s'", table_name)); if (!dict_locked) { - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); } 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); @@ -1113,7 +1167,7 @@ dict_table_open_on_name( << " is corrupted. Please " "drop the table and recreate."; if (!dict_locked) { - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); } DBUG_RETURN(NULL); @@ -1122,7 +1176,7 @@ dict_table_open_on_name( dict_sys.acquire(table); if (!dict_locked) { - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); } DBUG_RETURN(table); @@ -1509,7 +1563,7 @@ dict_table_rename_in_cache( char old_name[MAX_FULL_NAME_LEN + 1]; os_file_type_t ftype; - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); /* store the old/current name to an automatic variable */ ut_a(strlen(table->name.m_name) < sizeof old_name); @@ -1890,7 +1944,7 @@ dict_table_change_id_in_cache( dict_table_t* table, /*!< in/out: table object already in cache */ table_id_t new_id) /*!< in: new id to set */ { - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); ut_ad(!table->is_temporary()); @@ -2049,7 +2103,7 @@ dict_index_add_to_cache( ulint n_ord; ulint i; - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); ut_ad(index->n_def == index->n_fields); ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); ut_ad(!dict_index_is_online_ddl(index)); @@ -2180,7 +2234,7 @@ dict_index_remove_from_cache_low( ut_ad(table && index); ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); ut_ad(table->id); #ifdef BTR_CUR_HASH_ADAPT ut_ad(!index->freed()); @@ -2200,9 +2254,9 @@ dict_index_remove_from_cache_low( /* The index is being dropped, remove any compression stats for it. */ if (!lru_evict && DICT_TF_GET_ZIP_SSIZE(index->table->flags)) { - mutex_enter(&page_zip_stat_per_index_mutex); + mysql_mutex_lock(&page_zip_stat_per_index_mutex); page_zip_stat_per_index.erase(index->id); - mutex_exit(&page_zip_stat_per_index_mutex); + mysql_mutex_unlock(&page_zip_stat_per_index_mutex); } /* Remove the index from affected virtual column index list */ @@ -2260,7 +2314,7 @@ dict_index_find_cols( const dict_table_t* table = index->table; ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); for (ulint i = 0; i < index->n_fields; i++) { ulint j; @@ -2529,7 +2583,7 @@ dict_index_build_internal_clust( ut_ad(dict_index_is_clust(index)); ut_ad(!dict_index_is_ibuf(index)); - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); /* Create a new index object with certainly enough fields */ new_index = dict_mem_index_create(index->table, index->name, @@ -2684,7 +2738,7 @@ dict_index_build_internal_non_clust( ut_ad(table && index); ut_ad(!dict_index_is_clust(index)); ut_ad(!dict_index_is_ibuf(index)); - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); /* The clustered index should be the first in the list of indexes */ clust_index = UT_LIST_GET_FIRST(table->indexes); @@ -2778,7 +2832,7 @@ dict_index_build_internal_fts( dict_index_t* new_index; ut_ad(index->type == DICT_FTS); - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); /* Create a new index */ new_index = dict_mem_index_create(index->table, index->name, @@ -2830,7 +2884,7 @@ dict_foreign_remove_from_cache( /*===========================*/ dict_foreign_t* foreign) /*!< in, own: foreign constraint */ { - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); ut_a(foreign); if (foreign->referenced_table != NULL) { @@ -2855,7 +2909,7 @@ dict_foreign_find( dict_table_t* table, /*!< in: table object */ dict_foreign_t* foreign) /*!< in: foreign constraint */ { - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); ut_ad(dict_foreign_set_validate(table->foreign_set)); ut_ad(dict_foreign_set_validate(table->referenced_set)); @@ -2909,7 +2963,7 @@ dict_foreign_find_index( /*!< out: index where error happened */ { - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); if (error) { *error = FK_INDEX_NOT_FOUND; @@ -2962,7 +3016,7 @@ dict_foreign_error_report( const char* msg) /*!< in: the error message */ { std::string fk_str; - mutex_enter(&dict_foreign_err_mutex); + mysql_mutex_lock(&dict_foreign_err_mutex); dict_foreign_error_report_low(file, fk->foreign_table_name); fputs(msg, file); fputs(" Constraint:\n", file); @@ -2974,7 +3028,7 @@ dict_foreign_error_report( " %s\n%s\n", fk->foreign_index->name(), FOREIGN_KEY_CONSTRAINTS_MSG); } - mutex_exit(&dict_foreign_err_mutex); + mysql_mutex_unlock(&dict_foreign_err_mutex); } /**********************************************************************//** @@ -3007,7 +3061,7 @@ dict_foreign_add_to_cache( DBUG_ENTER("dict_foreign_add_to_cache"); DBUG_PRINT("dict_foreign_add_to_cache", ("id: %s", foreign->id)); - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); for_table = dict_table_check_if_in_cache_low( foreign->foreign_table_name_lookup); @@ -3652,7 +3706,7 @@ dict_foreign_parse_drop_constraints( ptr = str; - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); loop: ptr = dict_scan_to(ptr, "DROP"); @@ -3711,7 +3765,7 @@ loop: if (!srv_read_only_mode) { FILE* ef = dict_foreign_err_file; - mutex_enter(&dict_foreign_err_mutex); + mysql_mutex_lock(&dict_foreign_err_mutex); rewind(ef); ut_print_timestamp(ef); fputs(" Error in dropping of a foreign key" @@ -3720,7 +3774,7 @@ loop: fprintf(ef, ",\nin SQL command\n%s" "\nCannot find a constraint with the" " given id %s.\n", str, id); - mutex_exit(&dict_foreign_err_mutex); + mysql_mutex_unlock(&dict_foreign_err_mutex); } ut_free(str); @@ -3734,7 +3788,7 @@ syntax_error: if (!srv_read_only_mode) { FILE* ef = dict_foreign_err_file; - mutex_enter(&dict_foreign_err_mutex); + mysql_mutex_lock(&dict_foreign_err_mutex); rewind(ef); ut_print_timestamp(ef); fputs(" Syntax error in dropping of a" @@ -3742,7 +3796,7 @@ syntax_error: ut_print_name(ef, NULL, table->name.m_name); fprintf(ef, ",\n" "close to:\n%s\n in SQL command\n%s\n", ptr, str); - mutex_exit(&dict_foreign_err_mutex); + mysql_mutex_unlock(&dict_foreign_err_mutex); } ut_free(str); @@ -3761,7 +3815,7 @@ dict_index_get_if_in_cache_low( /*===========================*/ index_id_t index_id) /*!< in: index id */ { - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); return(dict_index_find_on_id_low(index_id)); } @@ -3781,11 +3835,11 @@ dict_index_get_if_in_cache( return(NULL); } - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); index = dict_index_get_if_in_cache_low(index_id); - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); return(index); } @@ -4066,7 +4120,7 @@ dict_print_info_on_foreign_keys( dict_foreign_t* foreign; std::string str; - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); for (dict_foreign_set::iterator it = table->foreign_set.begin(); it != table->foreign_set.end(); @@ -4133,7 +4187,7 @@ dict_print_info_on_foreign_keys( } } - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); return str; } @@ -4231,10 +4285,9 @@ dict_set_corrupted( row_mysql_lock_data_dictionary(trx); } - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); ut_ad(!dict_table_is_comp(dict_sys.sys_tables)); ut_ad(!dict_table_is_comp(dict_sys.sys_indexes)); - ut_ad(!sync_check_iterate(dict_sync_check())); /* Mark the table as corrupted only if the clustered index is corrupted */ @@ -4320,7 +4373,7 @@ dict_set_corrupted_index_cache_only( { ut_ad(index != NULL); ut_ad(index->table != NULL); - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); ut_ad(!dict_table_is_comp(dict_sys.sys_tables)); ut_ad(!dict_table_is_comp(dict_sys.sys_indexes)); @@ -4430,14 +4483,14 @@ void dict_set_merge_threshold_all_debug( uint merge_threshold_all) { - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); dict_set_merge_threshold_list_debug( &dict_sys.table_LRU, merge_threshold_all); dict_set_merge_threshold_list_debug( &dict_sys.table_non_LRU, merge_threshold_all); - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); } #endif /* UNIV_DEBUG */ @@ -4555,7 +4608,7 @@ dict_table_check_for_dup_indexes( const dict_index_t* index1; const dict_index_t* index2; - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); /* The primary index _must_ exist */ ut_a(UT_LIST_GET_LEN(table->indexes) > 0); @@ -4632,7 +4685,7 @@ dict_table_schema_check( dict_table_t* table; ulint i; - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); table = dict_table_get_low(req_schema->table_name); @@ -4881,7 +4934,7 @@ void dict_sys_t::resize() { ut_ad(this == &dict_sys); ut_ad(is_initialised()); - mutex_enter(&mutex); + mutex_lock(); /* all table entries are in table_LRU and table_non_LRU lists */ table_hash.free(); @@ -4919,7 +4972,7 @@ void dict_sys_t::resize() HASH_INSERT(dict_table_t, id_hash, id_hash, id_fold, table); } - mutex_exit(&mutex); + mutex_unlock(); } /** Close the data dictionary cache on shutdown. */ @@ -4928,7 +4981,7 @@ void dict_sys_t::close() ut_ad(this == &dict_sys); if (!is_initialised()) return; - mutex_enter(&mutex); + mutex_lock(); /* Free the hash elements. We don't remove them from the table because we are going to destroy the table anyway. */ @@ -4946,11 +4999,11 @@ void dict_sys_t::close() /* No temporary tables should exist at this point. */ temp_id_hash.free(); - mutex_exit(&mutex); - mutex_free(&mutex); + mutex_unlock(); + mysql_mutex_destroy(&mutex); latch.destroy(); - mutex_free(&dict_foreign_err_mutex); + mysql_mutex_destroy(&dict_foreign_err_mutex); if (dict_foreign_err_file) { @@ -4972,7 +5025,7 @@ dict_lru_validate(void) { dict_table_t* table; - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); for (table = UT_LIST_GET_FIRST(dict_sys.table_LRU); table != NULL; diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc index f80a9bd93aa..5e1a9deec4f 100644 --- a/storage/innobase/dict/dict0load.cc +++ b/storage/innobase/dict/dict0load.cc @@ -218,7 +218,7 @@ dict_get_first_table_name_in_db( ulint len; mtr_t mtr; - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); heap = mem_heap_create(1000); @@ -673,7 +673,7 @@ dict_sys_tables_rec_check( const byte* field; ulint len; - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); if (rec_get_deleted_flag(rec, 0)) { return("delete-marked record in SYS_TABLES"); @@ -1397,7 +1397,7 @@ dict_load_columns( mtr_t mtr; ulint n_skipped = 0; - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); mtr_start(&mtr); @@ -1513,7 +1513,7 @@ dict_load_virtual_one_col( mtr_t mtr; ulint skipped = 0; - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); if (v_col->num_base == 0) { return; @@ -1746,7 +1746,7 @@ dict_load_fields( mtr_t mtr; dberr_t error; - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); mtr_start(&mtr); @@ -1977,7 +1977,7 @@ dict_load_indexes( mtr_t mtr; dberr_t error = DB_SUCCESS; - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); mtr_start(&mtr); @@ -2271,7 +2271,7 @@ dict_save_data_dir_path( dict_table_t* table, /*!< in/out: table */ const char* filepath) /*!< in: filepath of tablespace */ { - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); ut_a(DICT_TF_HAS_DATA_DIR(table->flags)); ut_a(!table->data_dir_path); @@ -2308,7 +2308,7 @@ dict_get_and_save_data_dir_path( if (!table->data_dir_path && table->space_id && table->space) { if (!dict_mutex_own) { - dict_mutex_enter_for_mysql(); + dict_sys.mutex_lock(); } table->flags |= 1 << DICT_TF_POS_DATA_DIR @@ -2327,7 +2327,7 @@ dict_get_and_save_data_dir_path( } if (!dict_mutex_own) { - dict_mutex_exit_for_mysql(); + dict_sys.mutex_unlock(); } } } @@ -2351,7 +2351,7 @@ dict_table_t* dict_load_table(const char* name, dict_err_ignore_t ignore_err) DBUG_ENTER("dict_load_table"); DBUG_PRINT("dict_load_table", ("loading table: '%s'", name)); - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); result = dict_table_check_if_in_cache_low(name); @@ -2484,7 +2484,7 @@ dict_load_table_one( DBUG_ENTER("dict_load_table_one"); DBUG_PRINT("dict_load_table_one", ("table: %s", name.m_name)); - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); heap = mem_heap_create(32000); @@ -2730,7 +2730,7 @@ dict_load_table_on_id( dict_table_t* table; mtr_t mtr; - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); table = NULL; @@ -2815,7 +2815,7 @@ dict_load_sys_table( { mem_heap_t* heap; - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); heap = mem_heap_create(1000); @@ -2852,7 +2852,7 @@ dict_load_foreign_cols( mtr_t mtr; size_t id_len; - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); id_len = strlen(foreign->id); @@ -2998,7 +2998,7 @@ dict_load_foreign( DBUG_PRINT("dict_load_foreign", ("id: '%s', check_recursive: %d", id, check_recursive)); - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); id_len = strlen(id); @@ -3173,7 +3173,7 @@ dict_load_foreigns( DBUG_ENTER("dict_load_foreigns"); - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); sys_foreign = dict_table_get_low("SYS_FOREIGN"); @@ -3332,7 +3332,7 @@ dict_load_table_id_on_index_id( bool found = false; mtr_t mtr; - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); /* NOTE that the operation of this function is protected by the dictionary mutex, and therefore no deadlocks can occur diff --git a/storage/innobase/dict/dict0mem.cc b/storage/innobase/dict/dict0mem.cc index 96f2d7b6e3b..c9d86139741 100644 --- a/storage/innobase/dict/dict0mem.cc +++ b/storage/innobase/dict/dict0mem.cc @@ -35,7 +35,6 @@ Created 1/8/1996 Heikki Tuuri #include "dict0dict.h" #include "fts0priv.h" #include "lock0lock.h" -#include "sync0sync.h" #include "row0row.h" #include "sql_string.h" #include <iostream> @@ -791,8 +790,8 @@ dict_mem_index_create( index->rtr_track = new (mem_heap_alloc(heap, sizeof *index->rtr_track)) rtr_info_track_t(); - mutex_create(LATCH_ID_RTR_ACTIVE_MUTEX, - &index->rtr_track->rtr_active_mutex); + mysql_mutex_init(rtr_active_mutex_key, + &index->rtr_track->rtr_active_mutex, nullptr); } return(index); @@ -1101,7 +1100,7 @@ dict_mem_index_free( rtr_info->index = NULL; } - mutex_destroy(&index->rtr_track->rtr_active_mutex); + mysql_mutex_destroy(&index->rtr_track->rtr_active_mutex); index->rtr_track->~rtr_info_track_t(); } diff --git a/storage/innobase/dict/dict0stats.cc b/storage/innobase/dict/dict0stats.cc index f0b3a568955..8b61eec485c 100644 --- a/storage/innobase/dict/dict0stats.cc +++ b/storage/innobase/dict/dict0stats.cc @@ -33,7 +33,6 @@ Created Jan 06, 2010 Vasil Dimov #include "pars0pars.h" #include <mysql_com.h> #include "btr0btr.h" -#include "sync0sync.h" #include <algorithm> #include <map> @@ -236,10 +235,10 @@ dict_stats_persistent_storage_check( dberr_t ret; if (!caller_has_dict_sys_mutex) { - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); } - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); /* first check table_stats */ ret = dict_table_schema_check(&table_stats_schema, errstr, @@ -251,7 +250,7 @@ dict_stats_persistent_storage_check( } if (!caller_has_dict_sys_mutex) { - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); } if (ret != DB_SUCCESS && ret != DB_STATS_DO_NOT_EXIST) { @@ -511,7 +510,7 @@ dict_stats_empty_index( { ut_ad(!(index->type & DICT_FTS)); ut_ad(!dict_index_is_ibuf(index)); - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); ulint n_uniq = index->n_uniq; @@ -541,7 +540,7 @@ dict_stats_empty_table( bool empty_defrag_stats) /*!< in: whether to empty defrag stats */ { - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); /* Zero the stats members */ table->stat_n_rows = 0; @@ -567,7 +566,7 @@ dict_stats_empty_table( } table->stat_initialized = TRUE; - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); } /*********************************************************************//** @@ -666,7 +665,7 @@ dict_stats_copy( to have the same statistics as if the table was empty */ { - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); dst->stats_last_recalc = src->stats_last_recalc; dst->stat_n_rows = src->stat_n_rows; @@ -783,7 +782,7 @@ dict_table_t* dict_stats_snapshot_create( dict_table_t* table) { - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); dict_stats_assert_initialized(table); @@ -798,7 +797,7 @@ dict_stats_snapshot_create( t->stats_sample_pages = table->stats_sample_pages; t->stats_bg_flag = table->stats_bg_flag; - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); return(t); } @@ -837,14 +836,14 @@ dict_stats_update_transient_for_index( Initialize some bogus index cardinality statistics, so that the data can be queried in various means, also via secondary indexes. */ - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); dict_stats_empty_index(index, false); - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); #if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG } else if (ibuf_debug && !dict_index_is_clust(index)) { - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); dict_stats_empty_index(index, false); - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); #endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ } else { mtr_t mtr; @@ -865,9 +864,9 @@ dict_stats_update_transient_for_index( switch (size) { case ULINT_UNDEFINED: - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); dict_stats_empty_index(index, false); - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); return; case 0: /* The root node of the tree is a leaf */ @@ -884,8 +883,7 @@ dict_stats_update_transient_for_index( index); if (!stats.empty()) { - ut_ad(!mutex_own(&dict_sys.mutex)); - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); for (size_t i = 0; i < stats.size(); ++i) { index->stat_n_diff_key_vals[i] = stats[i].n_diff_key_vals; @@ -894,7 +892,7 @@ dict_stats_update_transient_for_index( index->stat_n_non_null_key_vals[i] = stats[i].n_non_null_key_vals; } - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); } } } @@ -912,7 +910,7 @@ dict_stats_update_transient( /*========================*/ dict_table_t* table) /*!< in/out: table */ { - ut_ad(!mutex_own(&dict_sys.mutex)); + dict_sys.assert_not_locked(); dict_index_t* index; ulint sum_of_index_sizes = 0; @@ -945,9 +943,9 @@ dict_stats_update_transient( if (dict_stats_should_ignore_index(index) || !index->is_readable()) { - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); dict_stats_empty_index(index, false); - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); continue; } @@ -956,7 +954,7 @@ dict_stats_update_transient( sum_of_index_sizes += index->stat_index_size; } - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); index = dict_table_get_first_index(table); @@ -974,7 +972,7 @@ dict_stats_update_transient( table->stat_initialized = TRUE; - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); } /* @{ Pseudo code about the relation between the following functions @@ -1932,7 +1930,7 @@ static index_stats_t dict_stats_analyze_index(dict_index_t* index) DBUG_PRINT("info", ("index: %s, online status: %d", index->name(), dict_index_get_online_status(index))); - ut_ad(!mutex_own(&dict_sys.mutex)); // because this function is slow + dict_sys.assert_not_locked(); // this function is slow ut_ad(index->table->get_ref_count()); /* Disable update statistic for Rtree */ @@ -2004,14 +2002,14 @@ static index_stats_t dict_stats_analyze_index(dict_index_t* index) mtr.commit(); - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); for (ulint i = 0; i < n_uniq; i++) { result.stats[i].n_diff_key_vals = index->stat_n_diff_key_vals[i]; result.stats[i].n_sample_sizes = total_pages; result.stats[i].n_non_null_key_vals = index->stat_n_non_null_key_vals[i]; } result.n_leaf_pages = index->stat_n_leaf_pages; - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); DBUG_RETURN(result); } @@ -2245,13 +2243,13 @@ dict_stats_update_persistent( } ut_ad(!dict_index_is_ibuf(index)); - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); dict_stats_empty_index(index, false); - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); index_stats_t stats = dict_stats_analyze_index(index); - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); index->stat_index_size = stats.index_size; index->stat_n_leaf_pages = stats.n_leaf_pages; for (size_t i = 0; i < stats.stats.size(); ++i) { @@ -2287,9 +2285,9 @@ dict_stats_update_persistent( } if (!(table->stats_bg_flag & BG_STAT_SHOULD_QUIT)) { - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); stats = dict_stats_analyze_index(index); - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); index->stat_index_size = stats.index_size; index->stat_n_leaf_pages = stats.n_leaf_pages; @@ -2315,7 +2313,7 @@ dict_stats_update_persistent( dict_stats_assert_initialized(table); - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); return(DB_SUCCESS); } @@ -2991,8 +2989,6 @@ dict_stats_fetch_from_ps( char db_utf8[MAX_DB_UTF8_LEN]; char table_utf8[MAX_TABLE_UTF8_LEN]; - ut_ad(!mutex_own(&dict_sys.mutex)); - /* Initialize all stats to dummy values before fetching because if the persistent storage contains incomplete stats (e.g. missing stats for some index) then we would end up with (partially) uninitialized @@ -3127,13 +3123,13 @@ dict_stats_update_for_index( { DBUG_ENTER("dict_stats_update_for_index"); - ut_ad(!mutex_own(&dict_sys.mutex)); + dict_sys.assert_not_locked(); if (dict_stats_is_persistent_enabled(index->table)) { if (dict_stats_persistent_storage_check(false)) { index_stats_t stats = dict_stats_analyze_index(index); - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); index->stat_index_size = stats.index_size; index->stat_n_leaf_pages = stats.n_leaf_pages; for (size_t i = 0; i < stats.stats.size(); ++i) { @@ -3146,7 +3142,7 @@ dict_stats_update_for_index( } index->table->stat_sum_of_other_index_sizes += index->stat_index_size; - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); dict_stats_save(index->table, &index->id); DBUG_VOID_RETURN; @@ -3187,7 +3183,7 @@ dict_stats_update( the persistent statistics storage */ { - ut_ad(!mutex_own(&dict_sys.mutex)); + dict_sys.assert_not_locked(); if (!table->is_readable()) { return (dict_stats_report_error(table)); @@ -3322,7 +3318,7 @@ dict_stats_update( switch (err) { case DB_SUCCESS: - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); /* Pass reset_ignored_indexes=true as parameter to dict_stats_copy. This will cause statictics @@ -3331,7 +3327,7 @@ dict_stats_update( dict_stats_assert_initialized(table); - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); dict_stats_table_clone_free(t); @@ -3417,7 +3413,7 @@ dict_stats_drop_index( pars_info_t* pinfo; dberr_t ret; - ut_ad(!mutex_own(&dict_sys.mutex)); + dict_sys.assert_not_locked(); /* skip indexes whose table names do not contain a database name e.g. if we are dropping an index from SYS_TABLES */ @@ -3953,7 +3949,7 @@ test_dict_table_schema_check() /* prevent any data dictionary modifications while we are checking the tables' structure */ - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); /* check that a valid table is reported as valid */ schema.n_cols = 7; @@ -4029,7 +4025,7 @@ test_dict_table_schema_check() test_dict_table_schema_check_end: - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); } /* @} */ diff --git a/storage/innobase/dict/dict0stats_bg.cc b/storage/innobase/dict/dict0stats_bg.cc index 67769647624..8b9cc02484c 100644 --- a/storage/innobase/dict/dict0stats_bg.cc +++ b/storage/innobase/dict/dict0stats_bg.cc @@ -51,7 +51,7 @@ my_bool innodb_dict_stats_disabled_debug; #endif /* UNIV_DEBUG */ /** This mutex protects the "recalc_pool" variable. */ -static ib_mutex_t recalc_pool_mutex; +static mysql_mutex_t recalc_pool_mutex; /** Allocator type, used by std::vector */ typedef ut_allocator<table_id_t> @@ -112,7 +112,7 @@ dict_stats_recalc_pool_add( { ut_ad(!srv_read_only_mode); - mutex_enter(&recalc_pool_mutex); + mysql_mutex_lock(&recalc_pool_mutex); /* quit if already in the list */ for (recalc_pool_iterator_t iter = recalc_pool.begin(); @@ -120,7 +120,7 @@ dict_stats_recalc_pool_add( ++iter) { if (*iter == table->id) { - mutex_exit(&recalc_pool_mutex); + mysql_mutex_unlock(&recalc_pool_mutex); return; } } @@ -129,7 +129,7 @@ dict_stats_recalc_pool_add( if (recalc_pool.size() == 1 && schedule_dict_stats_task) { dict_stats_schedule_now(); } - mutex_exit(&recalc_pool_mutex); + mysql_mutex_unlock(&recalc_pool_mutex); } @@ -147,7 +147,7 @@ void dict_stats_update_if_needed_func(dict_table_t *table) #endif { ut_ad(table->stat_initialized); - ut_ad(!mutex_own(&dict_sys.mutex)); + dict_sys.assert_not_locked(); ulonglong counter = table->stat_modified_counter++; ulonglong n_rows = dict_table_get_n_rows(table); @@ -215,10 +215,10 @@ dict_stats_recalc_pool_get( { ut_ad(!srv_read_only_mode); - mutex_enter(&recalc_pool_mutex); + mysql_mutex_lock(&recalc_pool_mutex); if (recalc_pool.empty()) { - mutex_exit(&recalc_pool_mutex); + mysql_mutex_unlock(&recalc_pool_mutex); return(false); } @@ -226,7 +226,7 @@ dict_stats_recalc_pool_get( recalc_pool.erase(recalc_pool.begin()); - mutex_exit(&recalc_pool_mutex); + mysql_mutex_unlock(&recalc_pool_mutex); return(true); } @@ -240,9 +240,9 @@ dict_stats_recalc_pool_del( const dict_table_t* table) /*!< in: table to remove */ { ut_ad(!srv_read_only_mode); - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); - mutex_enter(&recalc_pool_mutex); + mysql_mutex_lock(&recalc_pool_mutex); ut_ad(table->id > 0); @@ -257,7 +257,7 @@ dict_stats_recalc_pool_del( } } - mutex_exit(&recalc_pool_mutex); + mysql_mutex_unlock(&recalc_pool_mutex); } /*****************************************************************//** @@ -286,26 +286,10 @@ Initialize global variables needed for the operation of dict_stats_thread() Must be called before dict_stats_thread() is started. */ void dict_stats_init() { - ut_ad(!srv_read_only_mode); - - /* The recalc_pool_mutex is acquired from: - 1) the background stats gathering thread before any other latch - and released without latching anything else in between (thus - any level would do here) - 2) from dict_stats_update_if_needed() - and released without latching anything else in between. We know - that dict_sys.mutex (SYNC_DICT) is not acquired when - dict_stats_update_if_needed() is called and it may be acquired - inside that function (thus a level <=SYNC_DICT would do). - 3) from row_drop_table_for_mysql() after dict_sys.mutex (SYNC_DICT) - and dict_sys.latch have been locked - (thus a level <SYNC_DICT would do) - So we choose SYNC_STATS_AUTO_RECALC to be about below SYNC_DICT. */ - - mutex_create(LATCH_ID_RECALC_POOL, &recalc_pool_mutex); - - dict_defrag_pool_init(); - stats_initialised = true; + ut_ad(!srv_read_only_mode); + mysql_mutex_init(recalc_pool_mutex_key, &recalc_pool_mutex, nullptr); + dict_defrag_pool_init(); + stats_initialised= true; } /*****************************************************************//** @@ -323,7 +307,7 @@ void dict_stats_deinit() dict_stats_recalc_pool_deinit(); dict_defrag_pool_deinit(); - mutex_free(&recalc_pool_mutex); + mysql_mutex_destroy(&recalc_pool_mutex); } /** @@ -345,28 +329,28 @@ next_table_id: dict_table_t* table; - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); table = dict_table_open_on_id(table_id, TRUE, DICT_TABLE_OP_NORMAL); if (table == NULL) { /* table does not exist, must have been DROPped after its id was enqueued */ - mutex_exit(&dict_sys.mutex); - goto next_table_id; + goto no_table; } ut_ad(!table->is_temporary()); if (!table->is_accessible()) { dict_table_close(table, TRUE, FALSE); - mutex_exit(&dict_sys.mutex); +no_table: + dict_sys.mutex_unlock(); goto next_table_id; } table->stats_bg_flag |= BG_STAT_IN_PROGRESS; - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); /* time() could be expensive, the current function is called once every time a table has been changed more than 10% and @@ -391,13 +375,13 @@ next_table_id: ret = true; } - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); table->stats_bg_flag = BG_STAT_NONE; dict_table_close(table, TRUE, FALSE); - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); return ret; } diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc index c4a9b1810e5..846e6ab223c 100644 --- a/storage/innobase/fil/fil0crypt.cc +++ b/storage/innobase/fil/fil0crypt.cc @@ -353,7 +353,7 @@ void fil_crypt_parse(fil_space_t* space, const byte* data) static_cast<fil_encryption_t> (data[10 + MY_AES_BLOCK_SIZE])); memcpy(crypt_data->iv, data + 2, MY_AES_BLOCK_SIZE); - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); if (space->crypt_data) { fil_space_merge_crypt_data(space->crypt_data, crypt_data); @@ -362,7 +362,7 @@ void fil_crypt_parse(fil_space_t* space, const byte* data) } else { space->crypt_data = crypt_data; } - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); } } @@ -997,12 +997,12 @@ fil_crypt_read_crypt_data(fil_space_t* space) mtr.start(); if (buf_block_t* block = buf_page_get(page_id_t(space->id, 0), zip_size, RW_S_LATCH, &mtr)) { - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); if (!space->crypt_data) { space->crypt_data = fil_space_read_crypt_data( zip_size, block->frame); } - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); } mtr.commit(); } @@ -1063,12 +1063,12 @@ func_exit: crypt_data->rotate_state.starting = true; crypt_data->rotate_state.active_threads = 1; - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); const bool stopping = space->is_stopping(); if (!stopping) { space->crypt_data = crypt_data; } - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); if (stopping) { goto abort; @@ -1404,7 +1404,7 @@ the encryption parameters were changed inline fil_space_t *fil_system_t::keyrotate_next(fil_space_t *space, bool recheck, bool encrypt) { - ut_ad(mutex_own(&mutex)); + mysql_mutex_assert_owner(&mutex); sized_ilist<fil_space_t, rotation_list_tag_t>::iterator it= space && space->is_in_rotation_list ? space : rotation_list.begin(); @@ -1456,7 +1456,7 @@ encryption parameters were changed inline fil_space_t *fil_space_t::next(fil_space_t *space, bool recheck, bool encrypt) { - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); if (!srv_fil_crypt_rotate_key_age) space= fil_system.keyrotate_next(space, recheck, encrypt); @@ -1483,7 +1483,7 @@ inline fil_space_t *fil_space_t::next(fil_space_t *space, bool recheck, } } - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); return space; } @@ -2143,7 +2143,7 @@ fil_crypt_set_thread_cnt( if innodb_encryption_rotate_key_age=0. */ static void fil_crypt_rotation_list_fill() { - ut_ad(mutex_own(&fil_system.mutex)); + mysql_mutex_assert_owner(&fil_system.mutex); for (fil_space_t* space = UT_LIST_GET_FIRST(fil_system.space_list); space != NULL; @@ -2193,11 +2193,11 @@ Adjust max key age void fil_crypt_set_rotate_key_age(uint val) { mysql_mutex_lock(&fil_crypt_threads_mutex); - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); srv_fil_crypt_rotate_key_age= val; if (val == 0) fil_crypt_rotation_list_fill(); - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); mysql_cond_broadcast(&fil_crypt_threads_cond); mysql_mutex_unlock(&fil_crypt_threads_mutex); } @@ -2220,13 +2220,13 @@ void fil_crypt_set_encrypt_tables(ulong val) { mysql_mutex_lock(&fil_crypt_threads_mutex); - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); srv_encrypt_tables= val; if (srv_fil_crypt_rotate_key_age == 0) fil_crypt_rotation_list_fill(); - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); mysql_cond_broadcast(&fil_crypt_threads_cond); mysql_mutex_unlock(&fil_crypt_threads_mutex); @@ -2234,9 +2234,7 @@ void fil_crypt_set_encrypt_tables(ulong val) /********************************************************************* Init threads for key rotation */ -UNIV_INTERN -void -fil_crypt_threads_init() +void fil_crypt_threads_init() { if (!fil_crypt_threads_inited) { mysql_cond_init(0, &fil_crypt_cond, nullptr); @@ -2290,7 +2288,7 @@ fil_space_crypt_close_tablespace( mysql_mutex_unlock(&crypt_data->mutex); /* release dict mutex so that scrub threads can release their * table references */ - dict_mutex_exit_for_mysql(); + dict_sys.mutex_unlock(); /* wakeup throttle (all) sleepers */ mysql_mutex_lock(&fil_crypt_threads_mutex); @@ -2299,7 +2297,7 @@ fil_space_crypt_close_tablespace( mysql_mutex_unlock(&fil_crypt_threads_mutex); os_thread_sleep(20000); - dict_mutex_enter_for_mysql(); + dict_sys.mutex_lock(); mysql_mutex_lock(&crypt_data->mutex); time_t now = time(0); diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index a2f78ef6352..c96bf6772b9 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -46,7 +46,6 @@ Created 10/25/1995 Heikki Tuuri #include "trx0purge.h" #include "buf0lru.h" #include "ibuf0ibuf.h" -#include "sync0sync.h" #include "buf0flu.h" #ifdef UNIV_LINUX # include <sys/types.h> @@ -68,7 +67,7 @@ inline bool fil_is_user_tablespace_id(ulint space_id) @return whether a file was closed */ bool fil_space_t::try_to_close(bool print_info) { - ut_ad(mutex_own(&fil_system.mutex)); + mysql_mutex_assert_owner(&fil_system.mutex); for (fil_space_t *space= UT_LIST_GET_FIRST(fil_system.space_list); space; space= UT_LIST_GET_NEXT(space_list, space)) { @@ -239,7 +238,7 @@ fil_space_get_by_id( fil_space_t* space; ut_ad(fil_system.is_initialised()); - ut_ad(mutex_own(&fil_system.mutex)); + mysql_mutex_assert_owner(&fil_system.mutex); HASH_SEARCH(hash, &fil_system.spaces, id, fil_space_t*, space, @@ -261,9 +260,9 @@ fil_space_t* fil_space_get( ulint id) { - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); fil_space_t* space = fil_space_get_by_id(id); - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); return(space); } @@ -343,7 +342,7 @@ fil_node_t* fil_space_t::add(const char* name, pfs_os_file_t handle, node->atomic_write = atomic_write; - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); this->size += size; UT_LIST_ADD_LAST(chain, node); if (node->is_open()) { @@ -354,7 +353,7 @@ fil_node_t* fil_space_t::add(const char* name, pfs_os_file_t handle, release(); } } - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); return node; } @@ -366,7 +365,7 @@ static bool fil_node_open_file_low(fil_node_t *node) { ut_ad(!node->is_open()); ut_ad(node->space->is_closing()); - ut_ad(mutex_own(&fil_system.mutex)); + mysql_mutex_assert_owner(&fil_system.mutex); const auto flags= node->space->flags; bool o_direct_possible= !FSP_FLAGS_HAS_PAGE_COMPRESSION(flags); static_assert(((UNIV_ZIP_SIZE_MIN >> 1) << 3) == 4096, "compatibility"); @@ -423,7 +422,7 @@ static bool fil_node_open_file_low(fil_node_t *node) @return whether the file was successfully opened */ static bool fil_node_open_file(fil_node_t *node) { - ut_ad(mutex_own(&fil_system.mutex)); + mysql_mutex_assert_owner(&fil_system.mutex); ut_ad(!node->is_open()); ut_ad(fil_is_user_tablespace_id(node->space->id) || srv_operation == SRV_OPERATION_BACKUP || @@ -445,11 +444,11 @@ static bool fil_node_open_file(fil_node_t *node) } else { - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); os_thread_sleep(20000); /* Flush tablespaces so that we can close modified files. */ fil_flush_file_spaces(); - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); } } @@ -478,7 +477,7 @@ pfs_os_file_t fil_node_t::detach() void fil_node_t::prepare_to_close_or_detach() { - ut_ad(mutex_own(&fil_system.mutex)); + mysql_mutex_assert_owner(&fil_system.mutex); ut_ad(space->is_ready_to_close() || srv_operation == SRV_OPERATION_BACKUP || srv_operation == SRV_OPERATION_RESTORE_DELTA); ut_a(is_open()); @@ -493,7 +492,7 @@ void fil_node_t::prepare_to_close_or_detach() /** Flush any writes cached by the file system. */ void fil_space_t::flush_low() { - ut_ad(!mutex_own(&fil_system.mutex)); + mysql_mutex_assert_not_owner(&fil_system.mutex); uint32_t n= 1; while (!n_pending.compare_exchange_strong(n, n | NEEDS_FSYNC, @@ -522,13 +521,13 @@ void fil_space_t::flush_low() if (is_in_unflushed_spaces) { - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); if (is_in_unflushed_spaces) { is_in_unflushed_spaces= false; fil_system.unflushed_spaces.remove(*this); } - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); } clear_flush(); @@ -549,7 +548,7 @@ fil_space_extend_must_retry( uint32_t size, bool* success) { - ut_ad(mutex_own(&fil_system.mutex)); + mysql_mutex_assert_owner(&fil_system.mutex); ut_ad(UT_LIST_GET_LAST(space->chain) == node); ut_ad(size >= FIL_IBD_FILE_INITIAL_SIZE); ut_ad(node->space == space); @@ -567,7 +566,7 @@ fil_space_extend_must_retry( for it to finish. It'd have been better to use event driven mechanism but the entire module is peppered with polling stuff. */ - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); os_thread_sleep(100000); return(true); } @@ -577,7 +576,7 @@ fil_space_extend_must_retry( /* At this point it is safe to release fil_system.mutex. No other thread can rename, delete, close or extend the file because we have set the node->being_extended flag. */ - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); ut_ad(size >= space->size); @@ -609,7 +608,7 @@ fil_space_extend_must_retry( last_page_no = uint32_t(fsize / page_size) + file_start_page_no; } - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); ut_a(node->being_extended); node->being_extended = false; @@ -629,10 +628,10 @@ fil_space_extend_must_retry( srv_sys_space.set_last_file_size(pages_in_MiB); do_flush: space->reacquire(); - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); space->flush_low(); space->release(); - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); break; default: ut_ad(space->purpose == FIL_TYPE_TABLESPACE @@ -656,8 +655,8 @@ ATTRIBUTE_COLD bool fil_space_t::prepare(bool have_mutex) { ut_ad(referenced()); if (!have_mutex) - mutex_enter(&fil_system.mutex); - ut_ad(mutex_own(&fil_system.mutex)); + mysql_mutex_lock(&fil_system.mutex); + mysql_mutex_assert_owner(&fil_system.mutex); fil_node_t *node= UT_LIST_GET_LAST(chain); ut_ad(!id || purpose == FIL_TYPE_TEMPORARY || node == UT_LIST_GET_FIRST(chain)); @@ -670,9 +669,9 @@ ATTRIBUTE_COLD bool fil_space_t::prepare(bool have_mutex) { bool success; while (fil_space_extend_must_retry(this, node, desired_size, &success)) - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); - ut_ad(mutex_own(&fil_system.mutex)); + mysql_mutex_assert_owner(&fil_system.mutex); /* Crash recovery requires the file extension to succeed. */ ut_a(success); /* InnoDB data files cannot shrink. */ @@ -702,7 +701,7 @@ clear: n_pending.fetch_and(~CLOSING, std::memory_order_relaxed); if (!have_mutex) - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); return is_open; } @@ -715,14 +714,14 @@ bool fil_space_extend(fil_space_t *space, uint32_t size) ut_ad(!srv_read_only_mode || space->purpose == FIL_TYPE_TEMPORARY); bool success= false; const bool acquired= space->acquire(); - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); if (acquired || space->is_being_truncated) { while (fil_space_extend_must_retry(space, UT_LIST_GET_LAST(space->chain), size, &success)) - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); } - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); if (acquired) space->release(); return success; @@ -731,7 +730,7 @@ bool fil_space_extend(fil_space_t *space, uint32_t size) /** Prepare to free a file from fil_system. */ inline pfs_os_file_t fil_node_t::close_to_free(bool detach_handle) { - ut_ad(mutex_own(&fil_system.mutex)); + mysql_mutex_assert_owner(&fil_system.mutex); ut_a(magic_n == FIL_NODE_MAGIC_N); ut_a(!being_extended); @@ -740,10 +739,10 @@ inline pfs_os_file_t fil_node_t::close_to_free(bool detach_handle) std::memory_order_acquire) & fil_space_t::PENDING)) { - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); while (space->referenced()) os_thread_sleep(100); - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); } while (is_open()) @@ -775,7 +774,7 @@ inline pfs_os_file_t fil_node_t::close_to_free(bool detach_handle) std::vector<pfs_os_file_t> fil_system_t::detach(fil_space_t *space, bool detach_handle) { - ut_ad(mutex_own(&fil_system.mutex)); + mysql_mutex_assert_owner(&fil_system.mutex); HASH_DELETE(fil_space_t, hash, &spaces, space->id, space); if (space->is_in_unflushed_spaces) @@ -871,14 +870,14 @@ fil_space_free( { ut_ad(id != TRX_SYS_SPACE); - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); fil_space_t* space = fil_space_get_by_id(id); if (space != NULL) { fil_system.detach(space); } - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); if (space != NULL) { if (x_latched) { @@ -967,14 +966,14 @@ fil_space_t *fil_space_t::create(const char *name, ulint id, ulint flags, space->atomic_write_supported = true; } - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); if (const fil_space_t *old_space = fil_space_get_by_id(id)) { ib::error() << "Trying to add tablespace '" << name << "' with id " << id << " to the tablespace memory cache, but tablespace '" << old_space->name << "' already exists in the cache!"; - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); space->~fil_space_t(); ut_free(space->name); ut_free(space); @@ -1019,7 +1018,7 @@ fil_space_t *fil_space_t::create(const char *name, ulint id, ulint flags, space->is_in_rotation_list = true; } - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); if (rotate) { fil_crypt_threads_signal(); @@ -1041,7 +1040,7 @@ fil_assign_new_space_id( ulint id; bool success; - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); id = *space_id; @@ -1073,7 +1072,7 @@ fil_assign_new_space_id( *space_id = ULINT_UNDEFINED; } - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); return(success); } @@ -1083,7 +1082,7 @@ fil_assign_new_space_id( bool fil_space_t::read_page0() { ut_ad(fil_system.is_initialised()); - ut_ad(mutex_own(&fil_system.mutex)); + mysql_mutex_assert_owner(&fil_system.mutex); if (size) return true; @@ -1114,7 +1113,7 @@ static fil_space_t *fil_space_get_space(ulint id) void fil_space_set_recv_size_and_flags(ulint id, uint32_t size, uint32_t flags) { ut_ad(id < SRV_SPACE_ID_UPPER_BOUND); - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); if (fil_space_t *space= fil_space_get_space(id)) { if (size) @@ -1122,7 +1121,7 @@ void fil_space_set_recv_size_and_flags(ulint id, uint32_t size, uint32_t flags) if (flags != FSP_FLAGS_FCRC32_MASK_MARKER) space->flags= flags; } - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); } /** Open each file. Never invoked on .ibd files. @@ -1136,7 +1135,7 @@ bool fil_space_t::open(bool create_new_db) bool success= true; bool skip_read= create_new_db; - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); for (fil_node_t *node= UT_LIST_GET_FIRST(chain); node; node= UT_LIST_GET_NEXT(chain, node)) @@ -1169,7 +1168,7 @@ err_exit: if (!create_new_db) committed_size= size; - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); return success; } @@ -1180,7 +1179,7 @@ void fil_space_t::close() return; } - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); ut_ad(this == fil_system.temp_space || srv_operation == SRV_OPERATION_BACKUP || srv_operation == SRV_OPERATION_RESTORE @@ -1194,7 +1193,7 @@ void fil_space_t::close() } } - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); } void fil_system_t::create(ulint hash_size) @@ -1212,7 +1211,7 @@ void fil_system_t::create(ulint hash_size) ut_ad(hash_size > 0); - mutex_create(LATCH_ID_FIL_SYSTEM, &mutex); + mysql_mutex_init(fil_system_mutex_key, &mutex, nullptr); spaces.create(hash_size); @@ -1291,7 +1290,7 @@ void fil_system_t::close() { m_initialised= false; spaces.free(); - mutex_free(&mutex); + mysql_mutex_destroy(&mutex); fil_space_crypt_cleanup(); } @@ -1318,7 +1317,7 @@ void fil_space_t::close_all() || UT_LIST_GET_LEN(fil_system.named_spaces) == 0); fil_flush_file_spaces(); - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); for (space = UT_LIST_GET_FIRST(fil_system.space_list); space; ) { fil_node_t* node; @@ -1338,9 +1337,9 @@ next: node->close(); goto next; } - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); os_thread_sleep(100); - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); if (!node->is_open()) { goto next; } @@ -1353,10 +1352,12 @@ next: space = UT_LIST_GET_NEXT(space_list, space); fil_system.detach(prev_space); + mysql_mutex_unlock(&fil_system.mutex); fil_space_free_low(prev_space); + mysql_mutex_lock(&fil_system.mutex); } - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); ut_ad(srv_fast_shutdown == 2 || !srv_was_started @@ -1375,14 +1376,14 @@ fil_set_max_space_id_if_bigger( ib::fatal() << "Max tablespace id is too high, " << max_id; } - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); if (fil_system.max_assigned_id < max_id) { fil_system.max_assigned_id = max_id; } - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); } /** Write the flushed LSN to the page header of the first page in the @@ -1433,10 +1434,10 @@ fil_write_flushed_lsn( @retval nullptr if the tablespace is missing or inaccessible */ fil_space_t *fil_space_t::get(ulint id) { - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); fil_space_t *space= fil_space_get_by_id(id); const uint32_t n= space ? space->acquire_low() : 0; - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); if (n & STOPPING) space= nullptr; @@ -1644,7 +1645,7 @@ fil_op_replay_rename( @return 0 if no operations else count + 1. */ static ulint fil_check_pending_ops(const fil_space_t* space, ulint count) { - ut_ad(mutex_own(&fil_system.mutex)); + mysql_mutex_assert_owner(&fil_system.mutex); if (!space) { return 0; @@ -1677,7 +1678,7 @@ fil_check_pending_io( fil_node_t** node, /*!< out: Node in space list */ ulint count) /*!< in: number of attempts so far */ { - ut_ad(mutex_own(&fil_system.mutex)); + mysql_mutex_assert_owner(&fil_system.mutex); /* The following code must change when InnoDB supports multiple datafiles per tablespace. */ @@ -1716,16 +1717,16 @@ fil_check_pending_operations( ulint count = 0; ut_a(!is_system_tablespace(id)); - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); fil_space_t* sp = fil_space_get_by_id(id); if (sp) { sp->set_stopping(true); if (sp->crypt_data) { sp->reacquire(); - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); fil_space_crypt_close_tablespace(sp); - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); sp->release(); } } @@ -1735,7 +1736,7 @@ fil_check_pending_operations( do { count = fil_check_pending_ops(sp, count); - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); if (count) { os_thread_sleep(20000); // Wait 0.02 seconds @@ -1743,7 +1744,7 @@ fil_check_pending_operations( return nullptr; } - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); sp = fil_space_get_by_id(id); } while (count); @@ -1763,18 +1764,18 @@ fil_check_pending_operations( *path = mem_strdup(node->name); } - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); if (count == 0) { break; } os_thread_sleep(20000); // Wait 0.02 seconds - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); sp = fil_space_get_by_id(id); if (!sp) { - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); break; } } @@ -1902,7 +1903,7 @@ dberr_t fil_delete_tablespace(ulint id, bool if_exists, RemoteDatafile::delete_link_file(space->name); } - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); /* Double check the sanity of pending ops after reacquiring the fil_system::mutex. */ @@ -1915,7 +1916,7 @@ dberr_t fil_delete_tablespace(ulint id, bool if_exists, if (detached_handles) { *detached_handles = std::move(handles); } - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); mysql_mutex_lock(&log_sys.mutex); @@ -1937,7 +1938,7 @@ dberr_t fil_delete_tablespace(ulint id, bool if_exists, err = DB_IO_ERROR; } } else { - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); err = DB_TABLESPACE_NOT_FOUND; } @@ -2107,7 +2108,7 @@ fil_rename_tablespace_check( a possibly existing tablespace that is associated with the new tablespace file. */ retry: - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); for (fil_space_t* space = UT_LIST_GET_FIRST(fil_system.space_list); space; space = UT_LIST_GET_NEXT(space_list, space)) { ulint id = space->id; @@ -2117,7 +2118,7 @@ retry: UT_LIST_GET_FIRST(space->chain)->name)) { ib::info() << "TRUNCATE rollback: " << id << "," << new_path; - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); dberr_t err = fil_delete_tablespace(id); if (err != DB_SUCCESS) { return err; @@ -2125,7 +2126,7 @@ retry: goto retry; } } - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); fil_delete_file(new_path); return(DB_SUCCESS); @@ -2172,7 +2173,7 @@ fil_rename_tablespace( ut_ad(strchr(new_name, '/') != NULL); - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); space = fil_space_get_by_id(id); @@ -2181,7 +2182,7 @@ fil_rename_tablespace( << " in the tablespace memory cache, though the file '" << old_path << "' in a rename operation should have that id."; - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); return(false); } @@ -2191,7 +2192,7 @@ fil_rename_tablespace( node = UT_LIST_GET_FIRST(space->chain); space->reacquire(); - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); char* new_file_name = new_path_in == NULL ? fil_make_filepath(NULL, new_name, IBD, false) @@ -2210,7 +2211,7 @@ fil_rename_tablespace( /* log_sys.mutex is above fil_system.mutex in the latching order */ mysql_mutex_assert_owner(&log_sys.mutex); - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); space->release(); ut_ad(space->name == old_space_name); ut_ad(node->name == old_file_name); @@ -2244,7 +2245,7 @@ skip_second_rename: old_space_name = new_space_name; } - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); ut_free(old_file_name); ut_free(old_space_name); @@ -2493,7 +2494,7 @@ fil_ibd_open( const char* path_in, dberr_t* err) { - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); if (fil_space_t* space = fil_space_get_by_id(id)) { if (strcmp(space->name, tablename.m_name)) { table_name_t space_name; @@ -2506,7 +2507,7 @@ fil_ibd_open( if (err) *err = DB_TABLESPACE_EXISTS; } else if (err) *err = DB_SUCCESS; - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); if (space && validate && !srv_read_only_mode) { fsp_flags_try_adjust(space, @@ -2515,7 +2516,7 @@ fil_ibd_open( return space; } - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); Datafile df_default; /* default location */ RemoteDatafile df_remote; /* remote location */ @@ -2730,7 +2731,7 @@ fil_space_read_name_and_filepath( *name = NULL; *filepath = NULL; - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); fil_space_t* space = fil_space_get_by_id(space_id); @@ -2743,7 +2744,7 @@ fil_space_read_name_and_filepath( success = true; } - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); return(success); } @@ -2923,9 +2924,9 @@ fil_ibd_load( { /* If the a space is already in the file system cache with this space ID, then there is nothing to do. */ - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); space = fil_space_get_by_id(space_id); - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); if (space != NULL) { /* Compare the filename we are trying to open with the @@ -3152,7 +3153,7 @@ fil_space_for_table_exists_in_mem( { const ulint expected_flags = dict_tf_to_fsp_flags(table_flags); - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); if (fil_space_t* space = fil_space_get_by_id(id)) { ulint tf = expected_flags & ~FSP_FLAGS_MEM_MASK; ulint sf = space->flags & ~FSP_FLAGS_MEM_MASK; @@ -3177,7 +3178,7 @@ fil_space_for_table_exists_in_mem( FSP_SPACE_FLAGS will not be written back here. */ space->flags = (space->flags & ~FSP_FLAGS_MEM_MASK) | (expected_flags & FSP_FLAGS_MEM_MASK); - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); if (!srv_read_only_mode) { fsp_flags_try_adjust(space, expected_flags & ~FSP_FLAGS_MEM_MASK); @@ -3186,7 +3187,7 @@ fil_space_for_table_exists_in_mem( } func_exit: - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); return NULL; } @@ -3207,19 +3208,19 @@ fil_report_invalid_page_access(const char *name, /** Update the data structures on write completion */ inline void fil_node_t::complete_write() { - ut_ad(!mutex_own(&fil_system.mutex)); + mysql_mutex_assert_not_owner(&fil_system.mutex); if (space->purpose != FIL_TYPE_TEMPORARY && srv_file_flush_method != SRV_O_DIRECT_NO_FSYNC && space->set_needs_flush()) { - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); if (!space->is_in_unflushed_spaces) { space->is_in_unflushed_spaces= true; fil_system.unflushed_spaces.push_front(*space); } - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); } } @@ -3381,28 +3382,28 @@ void fil_flush_file_spaces() { if (srv_file_flush_method == SRV_O_DIRECT_NO_FSYNC) { - ut_d(mutex_enter(&fil_system.mutex)); + ut_d(mysql_mutex_lock(&fil_system.mutex)); ut_ad(fil_system.unflushed_spaces.empty()); - ut_d(mutex_exit(&fil_system.mutex)); + ut_d(mysql_mutex_unlock(&fil_system.mutex)); return; } rescan: - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); for (fil_space_t &space : fil_system.unflushed_spaces) { if (space.needs_flush_not_stopping()) { space.reacquire(); - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); space.flush_low(); space.release(); goto rescan; } } - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); } /** Functor to validate the file node list of a tablespace. */ @@ -3428,7 +3429,7 @@ struct Check { @return number of open file nodes */ static ulint validate(const fil_space_t* space) { - ut_ad(mutex_own(&fil_system.mutex)); + mysql_mutex_assert_owner(&fil_system.mutex); Check check; ut_list_validate(space->chain, check); ut_a(space->size == check.size); @@ -3457,7 +3458,7 @@ bool fil_validate() { ulint n_open = 0; - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); for (fil_space_t *space = UT_LIST_GET_FIRST(fil_system.space_list); space != NULL; @@ -3467,7 +3468,7 @@ bool fil_validate() ut_a(fil_system.n_open == n_open); - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); return(true); } @@ -3516,7 +3517,7 @@ void fil_space_validate_for_mtr_commit( const fil_space_t* space) { - ut_ad(!mutex_own(&fil_system.mutex)); + mysql_mutex_assert_not_owner(&fil_system.mutex); ut_ad(space != NULL); ut_ad(space->purpose == FIL_TYPE_TABLESPACE); ut_ad(!is_predefined_tablespace(space->id)); diff --git a/storage/innobase/fil/fil0pagecompress.cc b/storage/innobase/fil/fil0pagecompress.cc index 909e8092f99..ffa2563d338 100644 --- a/storage/innobase/fil/fil0pagecompress.cc +++ b/storage/innobase/fil/fil0pagecompress.cc @@ -48,7 +48,6 @@ Updated 14/02/2015 #include "row0mysql.h" #include "buf0lru.h" #include "ibuf0ibuf.h" -#include "sync0sync.h" #include "zlib.h" #ifdef __linux__ #include <linux/fs.h> diff --git a/storage/innobase/fts/fts0config.cc b/storage/innobase/fts/fts0config.cc index 9e2b40911ae..4fa1c0c609b 100644 --- a/storage/innobase/fts/fts0config.cc +++ b/storage/innobase/fts/fts0config.cc @@ -119,11 +119,7 @@ fts_config_get_value( trx->op_info = "getting FTS config value"; error = fts_eval_sql(trx, graph); - - mutex_enter(&dict_sys.mutex); - que_graph_free(graph); - mutex_exit(&dict_sys.mutex); - + fts_que_graph_free(graph); return(error); } diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index 225662d4c46..773436159f0 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -37,7 +37,6 @@ Full Text Search interface #include "dict0priv.h" #include "dict0stats.h" #include "btr0pcur.h" -#include "sync0sync.h" static const ulint FTS_MAX_ID_LEN = 32; @@ -189,6 +188,14 @@ struct fts_tokenize_param_t { ulint add_pos; /*!< Added position for tokens */ }; +/** Free a query graph */ +void fts_que_graph_free(que_t *graph) +{ + dict_sys.mutex_lock(); + que_graph_free(graph); + dict_sys.mutex_unlock(); +} + /** Run SYNC on the table, i.e., write out data from the cache to the FTS auxiliary INDEX table and clear the cache at the end. @param[in,out] sync sync state @@ -454,7 +461,7 @@ fts_load_user_stopword( fts_stopword_t* stopword_info) /*!< in: Stopword info */ { if (!fts->dict_locked) { - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); } /* Validate the user table existence in the right format */ @@ -463,7 +470,7 @@ fts_load_user_stopword( if (!stopword_info->charset) { cleanup: if (!fts->dict_locked) { - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); } return ret; @@ -905,15 +912,15 @@ fts_que_graph_free_check_lock( } if (!has_dict) { - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); } - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); que_graph_free(graph); if (!has_dict) { - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); } } @@ -3514,7 +3521,9 @@ fts_add_doc_by_id( "fts_instrument_sync", fts_optimize_request_sync_table(table); mysql_mutex_lock(&cache->lock); - mysql_cond_wait(&cache->sync->cond, + if (cache->sync->in_progress) + mysql_cond_wait( + &cache->sync->cond, &cache->lock); mysql_mutex_unlock(&cache->lock); ); @@ -4311,7 +4320,7 @@ end_sync: ut_ad(sync->in_progress); sync->interrupted = false; sync->in_progress = false; - mysql_cond_signal(&sync->cond); + mysql_cond_broadcast(&sync->cond); mysql_mutex_unlock(&cache->lock); /* We need to check whether an optimize is required, for that @@ -5720,7 +5729,7 @@ fts parent table id and index id. index id */ static void fil_get_fts_spaces(fts_space_set_t& fts_space_set) { - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); for (fil_space_t *space= UT_LIST_GET_FIRST(fil_system.space_list); space; @@ -5734,7 +5743,7 @@ static void fil_get_fts_spaces(fts_space_set_t& fts_space_set) fts_space_set.insert(std::make_pair(table_id, index_id)); } - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); } /** Check whether the parent table id and index id of fts auxilary @@ -6205,7 +6214,7 @@ fts_init_index( fts_cache_t* cache = table->fts->cache; bool need_init = false; - ut_ad(!mutex_own(&dict_sys.mutex)); + dict_sys.assert_not_locked(); /* First check cache->get_docs is initialized */ if (!has_cache_lock) { @@ -6270,10 +6279,10 @@ func_exit: } if (need_init) { - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); /* Register the table with the optimize thread. */ fts_optimize_add_table(table); - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); } } diff --git a/storage/innobase/fts/fts0opt.cc b/storage/innobase/fts/fts0opt.cc index 5dcc4dc5a0a..ed9bfa58333 100644 --- a/storage/innobase/fts/fts0opt.cc +++ b/storage/innobase/fts/fts0opt.cc @@ -1005,10 +1005,7 @@ fts_table_fetch_doc_ids( error = fts_eval_sql(trx, graph); fts_sql_commit(trx); - - mutex_enter(&dict_sys.mutex); - que_graph_free(graph); - mutex_exit(&dict_sys.mutex); + fts_que_graph_free(graph); if (error == DB_SUCCESS) { ib_vector_sort(doc_ids->doc_ids, fts_doc_id_cmp); @@ -2594,7 +2591,7 @@ fts_optimize_remove_table( if (table->fts->in_queue) { - ut_ad(!mutex_own(&dict_sys.mutex)); + dict_sys.assert_not_locked(); fts_msg_t *msg= fts_optimize_create_msg(FTS_MSG_DEL_TABLE, nullptr); mysql_cond_t cond; mysql_cond_init(0, &cond, nullptr); @@ -2938,7 +2935,7 @@ fts_optimize_init(void) /* Add fts tables to fts_slots which could be skipped during dict_load_table_one() because fts_optimize_thread wasn't even started. */ - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); for (dict_table_t* table = UT_LIST_GET_FIRST(dict_sys.table_LRU); table != NULL; table = UT_LIST_GET_NEXT(table_LRU, table)) { @@ -2953,7 +2950,7 @@ fts_optimize_init(void) fts_optimize_new_table(table); table->fts->in_queue = true; } - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); mysql_cond_init(0, &fts_opt_shutdown_cond, nullptr); last_check_sync_time = time(NULL); @@ -2967,13 +2964,13 @@ fts_optimize_shutdown() /* If there is an ongoing activity on dictionary, such as srv_master_evict_from_table_cache(), wait for it */ - dict_mutex_enter_for_mysql(); + dict_sys.mutex_lock(); mysql_mutex_lock(&fts_optimize_wq->mutex); /* Tells FTS optimizer system that we are exiting from optimizer thread, message send their after will not be processed */ fts_opt_start_shutdown = true; - dict_mutex_exit_for_mysql(); + dict_sys.mutex_unlock(); /* We tell the OPTIMIZE thread to switch to state done, we can't delete the work queue here because the add thread needs diff --git a/storage/innobase/fts/fts0sql.cc b/storage/innobase/fts/fts0sql.cc index 180500f64a5..8dbb52e2fac 100644 --- a/storage/innobase/fts/fts0sql.cc +++ b/storage/innobase/fts/fts0sql.cc @@ -93,7 +93,7 @@ char* fts_get_table_name_prefix(const fts_table_t* fts_table) char table_id[FTS_AUX_MIN_TABLE_ID_LENGTH]; const size_t table_id_len = size_t(fts_get_table_id(fts_table, table_id)) + 1; - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); /* Include the separator as well. */ const size_t dbname_len = fts_table->table->name.dblen() + 1; ut_ad(dbname_len > 1); @@ -101,7 +101,7 @@ char* fts_get_table_name_prefix(const fts_table_t* fts_table) char* prefix_name = static_cast<char*>( ut_malloc_nokey(prefix_name_len)); memcpy(prefix_name, fts_table->table->name.m_name, dbname_len); - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); memcpy(prefix_name + dbname_len, "FTS_", 4); memcpy(prefix_name + dbname_len + 4, table_id, table_id_len); return prefix_name; @@ -115,15 +115,15 @@ void fts_get_table_name(const fts_table_t* fts_table, char* table_name, bool dict_locked) { if (!dict_locked) { - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); } - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); /* Include the separator as well. */ const size_t dbname_len = fts_table->table->name.dblen() + 1; ut_ad(dbname_len > 1); memcpy(table_name, fts_table->table->name.m_name, dbname_len); if (!dict_locked) { - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); } memcpy(table_name += dbname_len, "FTS_", 4); table_name += 4; @@ -152,17 +152,15 @@ fts_parse_sql( && fts_table->table->fts->dict_locked); if (!dict_locked) { - ut_ad(!mutex_own(&dict_sys.mutex)); - /* The InnoDB SQL parser is not re-entrant. */ - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); } graph = pars_sql(info, str); ut_a(graph); if (!dict_locked) { - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); } ut_free(str); @@ -182,7 +180,7 @@ fts_parse_sql_no_dict_lock( char* str; que_t* graph; - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); str = ut_str3cat(fts_sql_begin, sql, fts_sql_end); diff --git a/storage/innobase/gis/gis0sea.cc b/storage/innobase/gis/gis0sea.cc index e70d3cedf7d..9c4f91716a4 100644 --- a/storage/innobase/gis/gis0sea.cc +++ b/storage/innobase/gis/gis0sea.cc @@ -158,7 +158,7 @@ rtr_pcur_getnext_from_path( ulint rw_latch = RW_X_LATCH; ulint tree_idx; - mutex_enter(&rtr_info->rtr_path_mutex); + mysql_mutex_lock(&rtr_info->rtr_path_mutex); next_rec = rtr_info->path->back(); rtr_info->path->pop_back(); level = next_rec.level; @@ -201,7 +201,7 @@ rtr_pcur_getnext_from_path( == rtr_info->parent_path->back().child_no); } - mutex_exit(&rtr_info->rtr_path_mutex); + mysql_mutex_unlock(&rtr_info->rtr_path_mutex); skip_parent = false; new_split = false; @@ -386,11 +386,11 @@ rtr_pcur_getnext_from_path( trx_t* trx = thr_get_trx( btr_cur->rtr_info->thr); - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); lock_init_prdt_from_mbr( &prdt, &btr_cur->rtr_info->mbr, mode, trx->lock.lock_heap); - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); if (rw_latch == RW_NO_LATCH) { block->lock.s_lock(); @@ -479,13 +479,13 @@ rtr_pcur_move_to_next( ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED); - mutex_enter(&rtr_info->matches->rtr_match_mutex); + mysql_mutex_lock(&rtr_info->matches->rtr_match_mutex); /* First retrieve the next record on the current page */ if (!rtr_info->matches->matched_recs->empty()) { rtr_rec_t rec; rec = rtr_info->matches->matched_recs->back(); rtr_info->matches->matched_recs->pop_back(); - mutex_exit(&rtr_info->matches->rtr_match_mutex); + mysql_mutex_unlock(&rtr_info->matches->rtr_match_mutex); cursor->btr_cur.page_cur.rec = rec.r_rec; cursor->btr_cur.page_cur.block = &rtr_info->matches->block; @@ -494,7 +494,7 @@ rtr_pcur_move_to_next( return(true); } - mutex_exit(&rtr_info->matches->rtr_match_mutex); + mysql_mutex_unlock(&rtr_info->matches->rtr_match_mutex); /* Fetch the next page */ return(rtr_pcur_getnext_from_path(tuple, mode, &cursor->btr_cur, @@ -920,20 +920,21 @@ rtr_create_rtr_info( rtr_info->matches->bufp = page_align(rtr_info->matches->rec_buf + UNIV_PAGE_SIZE_MAX + 1); - mutex_create(LATCH_ID_RTR_MATCH_MUTEX, - &rtr_info->matches->rtr_match_mutex); + mysql_mutex_init(rtr_match_mutex_key, + &rtr_info->matches->rtr_match_mutex, + nullptr); rtr_info->matches->block.lock.init(); } rtr_info->path = UT_NEW_NOKEY(rtr_node_path_t()); rtr_info->parent_path = UT_NEW_NOKEY(rtr_node_path_t()); rtr_info->need_prdt_lock = need_prdt; - mutex_create(LATCH_ID_RTR_PATH_MUTEX, - &rtr_info->rtr_path_mutex); + mysql_mutex_init(rtr_path_mutex_key, &rtr_info->rtr_path_mutex, + nullptr); - mutex_enter(&index->rtr_track->rtr_active_mutex); + mysql_mutex_lock(&index->rtr_track->rtr_active_mutex); index->rtr_track->rtr_active.push_front(rtr_info); - mutex_exit(&index->rtr_track->rtr_active_mutex); + mysql_mutex_unlock(&index->rtr_track->rtr_active_mutex); return(rtr_info); } @@ -972,8 +973,8 @@ rtr_init_rtr_info( rtr_info->parent_path = NULL; rtr_info->matches = NULL; - mutex_create(LATCH_ID_RTR_PATH_MUTEX, - &rtr_info->rtr_path_mutex); + mysql_mutex_init(rtr_path_mutex_key, &rtr_info->rtr_path_mutex, + nullptr); memset(rtr_info->tree_blocks, 0x0, sizeof(rtr_info->tree_blocks)); @@ -1004,9 +1005,9 @@ rtr_init_rtr_info( rtr_info->cursor = cursor; rtr_info->index = index; - mutex_enter(&index->rtr_track->rtr_active_mutex); + mysql_mutex_lock(&index->rtr_track->rtr_active_mutex); index->rtr_track->rtr_active.push_front(rtr_info); - mutex_exit(&index->rtr_track->rtr_active_mutex); + mysql_mutex_unlock(&index->rtr_track->rtr_active_mutex); } /**************************************************************//** @@ -1027,7 +1028,7 @@ rtr_clean_rtr_info( index = rtr_info->index; if (index) { - mutex_enter(&index->rtr_track->rtr_active_mutex); + mysql_mutex_lock(&index->rtr_track->rtr_active_mutex); } while (rtr_info->parent_path && !rtr_info->parent_path->empty()) { @@ -1058,7 +1059,7 @@ rtr_clean_rtr_info( if (index) { index->rtr_track->rtr_active.remove(rtr_info); - mutex_exit(&index->rtr_track->rtr_active_mutex); + mysql_mutex_unlock(&index->rtr_track->rtr_active_mutex); } if (free_all) { @@ -1069,7 +1070,8 @@ rtr_clean_rtr_info( rtr_info->matches->block.lock.free(); - mutex_destroy(&rtr_info->matches->rtr_match_mutex); + mysql_mutex_destroy( + &rtr_info->matches->rtr_match_mutex); } if (rtr_info->heap) { @@ -1077,7 +1079,7 @@ rtr_clean_rtr_info( } if (initialized) { - mutex_destroy(&rtr_info->rtr_path_mutex); + mysql_mutex_destroy(&rtr_info->rtr_path_mutex); } if (rtr_info->allocated) { @@ -1164,24 +1166,24 @@ rtr_check_discard_page( { const ulint pageno = block->page.id().page_no(); - mutex_enter(&index->rtr_track->rtr_active_mutex); + mysql_mutex_lock(&index->rtr_track->rtr_active_mutex); for (const auto& rtr_info : index->rtr_track->rtr_active) { if (cursor && rtr_info == cursor->rtr_info) { continue; } - mutex_enter(&rtr_info->rtr_path_mutex); + mysql_mutex_lock(&rtr_info->rtr_path_mutex); for (const node_visit_t& node : *rtr_info->path) { if (node.page_no == pageno) { rtr_rebuild_path(rtr_info, pageno); break; } } - mutex_exit(&rtr_info->rtr_path_mutex); + mysql_mutex_unlock(&rtr_info->rtr_path_mutex); if (rtr_info->matches) { - mutex_enter(&rtr_info->matches->rtr_match_mutex); + mysql_mutex_lock(&rtr_info->matches->rtr_match_mutex); if ((&rtr_info->matches->block)->page.id().page_no() == pageno) { @@ -1192,16 +1194,16 @@ rtr_check_discard_page( rtr_info->matches->valid = false; } - mutex_exit(&rtr_info->matches->rtr_match_mutex); + mysql_mutex_unlock(&rtr_info->matches->rtr_match_mutex); } } - mutex_exit(&index->rtr_track->rtr_active_mutex); + mysql_mutex_unlock(&index->rtr_track->rtr_active_mutex); - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); lock_prdt_page_free_from_discard(block, &lock_sys.prdt_hash); lock_prdt_page_free_from_discard(block, &lock_sys.prdt_page_hash); - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); } /** Structure acts as functor to get the optimistic access of the page. diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index e38cccf0f34..c4083f8aeb9 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -115,7 +115,6 @@ this program; if not, write to the Free Software Foundation, Inc., #include "trx0trx.h" #include "fil0pagecompress.h" #include "ut0mem.h" -#include "ut0mutex.h" #include "row0ext.h" #include <limits> @@ -146,7 +145,6 @@ void close_thread_tables(THD* thd); #include "ha_innodb.h" #include "i_s.h" -#include "sync0sync.h" #include <string> #include <sstream> @@ -208,7 +206,7 @@ static char* innodb_version_str = (char*) INNODB_VERSION_STR; extern uint srv_fil_crypt_rotate_key_age; extern uint srv_n_fil_crypt_iops; -#ifdef UNIV_DEBUG +#if defined SAFE_MUTEX && defined UNIV_DEBUG my_bool innodb_evict_tables_on_commit_debug; #endif @@ -509,6 +507,46 @@ static PSI_cond_info all_innodb_conds[] = { }; # ifdef UNIV_PFS_MUTEX +mysql_pfs_key_t buf_pool_mutex_key; +mysql_pfs_key_t dict_foreign_err_mutex_key; +mysql_pfs_key_t dict_sys_mutex_key; +mysql_pfs_key_t fil_system_mutex_key; +mysql_pfs_key_t flush_list_mutex_key; +mysql_pfs_key_t fts_cache_mutex_key; +mysql_pfs_key_t fts_cache_init_mutex_key; +mysql_pfs_key_t fts_delete_mutex_key; +mysql_pfs_key_t fts_doc_id_mutex_key; +mysql_pfs_key_t fts_pll_tokenize_mutex_key; +mysql_pfs_key_t ibuf_bitmap_mutex_key; +mysql_pfs_key_t ibuf_mutex_key; +mysql_pfs_key_t ibuf_pessimistic_insert_mutex_key; +mysql_pfs_key_t log_sys_mutex_key; +mysql_pfs_key_t log_cmdq_mutex_key; +mysql_pfs_key_t log_flush_order_mutex_key; +mysql_pfs_key_t recalc_pool_mutex_key; +mysql_pfs_key_t purge_sys_pq_mutex_key; +mysql_pfs_key_t recv_sys_mutex_key; +mysql_pfs_key_t redo_rseg_mutex_key; +mysql_pfs_key_t noredo_rseg_mutex_key; +mysql_pfs_key_t page_zip_stat_per_index_mutex_key; +mysql_pfs_key_t rtr_active_mutex_key; +mysql_pfs_key_t rtr_match_mutex_key; +mysql_pfs_key_t rtr_path_mutex_key; +mysql_pfs_key_t srv_innodb_monitor_mutex_key; +mysql_pfs_key_t srv_misc_tmpfile_mutex_key; +mysql_pfs_key_t srv_monitor_file_mutex_key; +mysql_pfs_key_t buf_dblwr_mutex_key; +mysql_pfs_key_t trx_pool_mutex_key; +mysql_pfs_key_t trx_pool_manager_mutex_key; +mysql_pfs_key_t lock_mutex_key; +mysql_pfs_key_t lock_wait_mutex_key; +mysql_pfs_key_t trx_sys_mutex_key; +mysql_pfs_key_t srv_threads_mutex_key; +mysql_pfs_key_t thread_mutex_key; +mysql_pfs_key_t row_drop_list_mutex_key; +mysql_pfs_key_t rw_trx_hash_element_mutex_key; +mysql_pfs_key_t read_view_mutex_key; + /* all_innodb_mutexes array contains mutexes that are performance schema instrumented if "UNIV_PFS_MUTEX" is defined */ @@ -551,6 +589,13 @@ static PSI_mutex_info all_innodb_mutexes[] = { # endif /* UNIV_PFS_MUTEX */ # ifdef UNIV_PFS_RWLOCK +mysql_pfs_key_t dict_operation_lock_key; +mysql_pfs_key_t index_tree_rw_lock_key; +mysql_pfs_key_t index_online_log_key; +mysql_pfs_key_t fil_space_latch_key; +mysql_pfs_key_t trx_i_s_cache_lock_key; +mysql_pfs_key_t trx_purge_latch_key; + /* all_innodb_rwlocks array contains rwlocks that are performance schema instrumented if "UNIV_PFS_RWLOCK" is defined */ @@ -1517,8 +1562,6 @@ const char* thd_innodb_tmpdir( THD* thd) { - ut_ad(!sync_check_iterate(sync_check())); - const char* tmp_dir = THDVAR(thd, tmpdir); if (tmp_dir != NULL && *tmp_dir == '\0') { @@ -2697,9 +2740,7 @@ read view to it if there is no read view yet. Why a deadlock of threads is not possible: the query cache calls this function at the start of a SELECT processing. Then the calling thread cannot be holding any InnoDB semaphores. The calling thread is holding the -query cache mutex, and this function will reserve the InnoDB trx_sys.mutex. -Thus, the 'rank' in sync0mutex.h of the MySQL query cache mutex is above -the InnoDB trx_sys.mutex. +query cache mutex, and this function will reserve the trx_sys.mutex. @return TRUE if permitted, FALSE if not; note that the value FALSE does not mean we should invalidate the query cache: invalidation is called explicitly */ @@ -2771,9 +2812,8 @@ innobase_invalidate_query_cache( NOTE that in Windows this is always in LOWER CASE! */ { - /* Note that the sync0mutex.h rank of the query cache mutex is just - above the InnoDB trx_sys_t->lock. The caller of this function must - not have latches of a lower rank. */ + /* Note that the query cache mutex is just above the trx_sys.mutex. + The caller of this function must not have latches of a lower rank. */ #ifdef HAVE_QUERY_CACHE char qcache_key_name[2 * (NAME_LEN + 1)]; @@ -4419,7 +4459,7 @@ static void innobase_kill_query(handlerton*, THD *thd, enum thd_kill_levels) Also, BF thread should own trx mutex for the victim. */ DBUG_VOID_RETURN; #endif /* WITH_WSREP */ - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); trx_sys.trx_list.freeze(); trx->mutex.wr_lock(); /* It is possible that innobase_close_connection() is concurrently @@ -4440,7 +4480,7 @@ static void innobase_kill_query(handlerton*, THD *thd, enum thd_kill_levels) if (!cancel); else if (lock_t *lock= trx->lock.wait_lock) lock_cancel_waiting_and_release(lock); - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); trx->mutex.wr_unlock(); } @@ -5075,12 +5115,12 @@ innobase_build_v_templ( ut_ad(n_v_col > 0); if (!locked) { - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); } if (s_templ->vtempl) { if (!locked) { - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); } DBUG_VOID_RETURN; } @@ -5186,7 +5226,7 @@ innobase_build_v_templ( } if (!locked) { - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); } s_templ->db_name = table->s->db.str; @@ -5485,7 +5525,7 @@ ha_innobase::open(const char* name, int, uint) key_used_on_scan = m_primary_key; if (ib_table->n_v_cols) { - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); if (ib_table->vc_templ == NULL) { ib_table->vc_templ = UT_NEW_NOKEY(dict_vcol_templ_t()); innobase_build_v_templ( @@ -5493,7 +5533,7 @@ ha_innobase::open(const char* name, int, uint) true); } - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); } if (!check_index_consistency(table, ib_table)) { @@ -9405,7 +9445,7 @@ wsrep_append_foreign_key( foreign->referenced_table : foreign->foreign_table)) { WSREP_DEBUG("pulling %s table into cache", (referenced) ? "referenced" : "foreign"); - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); if (referenced) { foreign->referenced_table = @@ -9435,7 +9475,7 @@ wsrep_append_foreign_key( TRUE, FALSE); } } - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); } if ( !((referenced) ? @@ -12572,9 +12612,9 @@ create_table_info_t::create_table_update_dict() DBUG_RETURN(-1); } - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); fts_optimize_add_table(innobase_table); - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); } if (const Field* ai = m_form->found_next_number_field) { @@ -12841,12 +12881,12 @@ ha_innobase::discard_or_import_tablespace( btr_cur_instant_init(). */ table_id_t id = m_prebuilt->table->id; ut_ad(id); - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); dict_table_close(m_prebuilt->table, TRUE, FALSE); dict_sys.remove(m_prebuilt->table); m_prebuilt->table = dict_table_open_on_id(id, TRUE, DICT_TABLE_OP_NORMAL); - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); if (!m_prebuilt->table) { err = DB_TABLE_NOT_FOUND; } else { @@ -13931,7 +13971,7 @@ ha_innobase::info_low( DEBUG_SYNC_C("ha_innobase_info_low"); - ut_ad(!mutex_own(&dict_sys.mutex)); + dict_sys.assert_not_locked(); /* If we are forcing recovery at a high level, we will suppress statistics calculation on tables, because that may crash the @@ -13991,7 +14031,7 @@ ha_innobase::info_low( ulint stat_clustered_index_size; ulint stat_sum_of_other_index_sizes; - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); ut_a(ib_table->stat_initialized); @@ -14003,7 +14043,7 @@ ha_innobase::info_low( stat_sum_of_other_index_sizes = ib_table->stat_sum_of_other_index_sizes; - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); /* The MySQL optimizer seems to assume in a left join that n_rows @@ -14120,8 +14160,8 @@ ha_innobase::info_low( } struct Locking { - Locking() { mutex_enter(&dict_sys.mutex); } - ~Locking() { mutex_exit(&dict_sys.mutex); } + Locking() { dict_sys.mutex_lock(); } + ~Locking() { dict_sys.mutex_unlock(); } } locking; ut_a(ib_table->stat_initialized); @@ -14838,7 +14878,7 @@ get_foreign_key_info( dict_table_t* ref_table; - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); ref_table = dict_table_open_on_name( foreign->referenced_table_name_lookup, TRUE, FALSE, DICT_ERR_IGNORE_NONE); @@ -14893,7 +14933,7 @@ ha_innobase::get_foreign_key_list( m_prebuilt->trx->op_info = "getting list of foreign keys"; - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); for (dict_foreign_set::iterator it = m_prebuilt->table->foreign_set.begin(); @@ -14910,7 +14950,7 @@ ha_innobase::get_foreign_key_list( } } - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); m_prebuilt->trx->op_info = ""; @@ -14931,7 +14971,7 @@ ha_innobase::get_parent_foreign_key_list( m_prebuilt->trx->op_info = "getting list of referencing foreign keys"; - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); for (dict_foreign_set::iterator it = m_prebuilt->table->referenced_set.begin(); @@ -14948,7 +14988,7 @@ ha_innobase::get_parent_foreign_key_list( } } - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); m_prebuilt->trx->op_info = ""; @@ -15543,7 +15583,7 @@ innodb_show_status( char* str; size_t flen; - mutex_enter(&srv_monitor_file_mutex); + mysql_mutex_lock(&srv_monitor_file_mutex); rewind(srv_monitor_file); srv_printf_innodb_monitor(srv_monitor_file, FALSE, @@ -15570,7 +15610,7 @@ innodb_show_status( if (!(str = (char*) my_malloc(PSI_INSTRUMENT_ME, usable_len + 1, MYF(0)))) { - mutex_exit(&srv_monitor_file_mutex); + mysql_mutex_unlock(&srv_monitor_file_mutex); DBUG_RETURN(1); } @@ -15598,7 +15638,7 @@ innodb_show_status( flen = fread(str, 1, MAX_STATUS_SIZE - 1, srv_monitor_file); } - mutex_exit(&srv_monitor_file_mutex); + mysql_mutex_unlock(&srv_monitor_file_mutex); ret_val= stat_print( thd, innobase_hton_name, @@ -15610,215 +15650,6 @@ innodb_show_status( DBUG_RETURN(ret_val); } -/** Callback for collecting mutex statistics */ -struct ShowStatus { - - /** For tracking the mutex metrics */ - struct Value { - - /** Constructor - @param[in] name Name of the mutex - @param[in] spins Number of spins - @param[in] os_waits OS waits so far - @param[in] calls Number of calls to enter() */ - Value(const char* name, - ulint spins, - uint64_t waits, - uint64_t calls) - : - m_name(name), - m_spins(spins), - m_waits(waits), - m_calls(calls) - { - /* No op */ - } - - /** Mutex name */ - std::string m_name; - - /** Spins so far */ - ulint m_spins; - - /** Waits so far */ - uint64_t m_waits; - - /** Number of calls so far */ - uint64_t m_calls; - }; - - /** Order by m_waits, in descending order. */ - struct OrderByWaits: public std::binary_function<Value, Value, bool> - { - /** @return true if rhs < lhs */ - bool operator()( - const Value& lhs, - const Value& rhs) const - UNIV_NOTHROW - { - return(rhs.m_waits < lhs.m_waits); - } - }; - - typedef std::vector<Value, ut_allocator<Value> > Values; - - /** Collect the individual latch counts */ - struct GetCount { - typedef latch_meta_t::CounterType::Count Count; - - /** Constructor - @param[in] name Latch name - @param[in,out] values Put the values here */ - GetCount( - const char* name, - Values* values) - UNIV_NOTHROW - : - m_name(name), - m_values(values) - { - /* No op */ - } - - /** Collect the latch metrics. Ignore entries where the - spins and waits are zero. - @param[in] count The latch metrics */ - void operator()(Count* count) const UNIV_NOTHROW - { - if (count->m_spins > 0 || count->m_waits > 0) { - - m_values->push_back(Value( - m_name, - count->m_spins, - count->m_waits, - count->m_calls)); - } - } - - /** The latch name */ - const char* m_name; - - /** For collecting the active mutex stats. */ - Values* m_values; - }; - - /** Constructor */ - ShowStatus() { } - - /** Callback for collecting the stats - @param[in] latch_meta Latch meta data - @return always returns true */ - bool operator()(latch_meta_t& latch_meta) - UNIV_NOTHROW - { - latch_meta.get_counter()->iterate( - GetCount(latch_meta.get_name(), &m_values)); - - return(true); - } - - /** Implements the SHOW MUTEX STATUS command, for mutexes. - The table structure is like so: Engine | Mutex Name | Status - We store the metrics in the "Status" column as: - - spins=N,waits=N,calls=N" - - The user has to parse the dataunfortunately - @param[in,out] thd the MySQL query thread of the caller - @param[in,out] stat_print function for printing statistics - @return true on success. */ - bool to_string( - THD* thd, - stat_print_fn* stat_print) - UNIV_NOTHROW; - - /** For collecting the active mutex stats. */ - Values m_values; -}; - -/** Implements the SHOW MUTEX STATUS command, for mutexes. -The table structure is like so: Engine | Mutex Name | Status -We store the metrics in the "Status" column as: - - spins=N,waits=N,calls=N" - -The user has to parse the dataunfortunately -@param[in,out] thd the MySQL query thread of the caller -@param[in,out] stat_print function for printing statistics -@return true on success. */ -bool -ShowStatus::to_string( - THD* thd, - stat_print_fn* stat_print) - UNIV_NOTHROW -{ - uint hton_name_len = (uint) strlen(innobase_hton_name); - - std::sort(m_values.begin(), m_values.end(), OrderByWaits()); - - Values::iterator end = m_values.end(); - - for (Values::iterator it = m_values.begin(); it != end; ++it) { - - int name_len; - char name_buf[IO_SIZE]; - - name_len = snprintf( - name_buf, sizeof(name_buf), "%s", it->m_name.c_str()); - - int status_len; - char status_buf[IO_SIZE]; - - status_len = snprintf( - status_buf, sizeof(status_buf), - "spins=%lu,waits=%lu,calls=%llu", - static_cast<ulong>(it->m_spins), - static_cast<long>(it->m_waits), - (ulonglong) it->m_calls); - - if (stat_print(thd, innobase_hton_name, - hton_name_len, - name_buf, static_cast<uint>(name_len), - status_buf, static_cast<uint>(status_len))) { - - return(false); - } - } - - return(true); -} - -/** Implements the SHOW MUTEX STATUS command, for mutexes. -@param[in,out] hton the innodb handlerton -@param[in,out] thd the MySQL query thread of the caller -@param[in,out] stat_print function for printing statistics -@return 0 on success. */ -static -int -innodb_show_mutex_status( - handlerton* -#ifdef DBUG_ASSERT_EXISTS - hton -#endif - , - THD* thd, - stat_print_fn* stat_print) -{ - DBUG_ENTER("innodb_show_mutex_status"); - - ShowStatus collector; - - DBUG_ASSERT(hton == innodb_hton_ptr); - - mutex_monitor.iterate(collector); - - if (!collector.to_string(thd, stat_print)) { - DBUG_RETURN(1); - } - - DBUG_RETURN(0); -} - /************************************************************************//** Return 0 on success and non-zero on failure. Note: the bool return type seems to be abused here, should be an int. */ @@ -15840,8 +15671,6 @@ innobase_show_status( return(innodb_show_status(hton, thd, stat_print) != 0); case HA_ENGINE_MUTEX: - return(innodb_show_mutex_status(hton, thd, stat_print) != 0); - case HA_ENGINE_LOGS: /* Not handled */ break; @@ -17128,11 +16957,6 @@ innodb_monitor_set_option( srv_mon_process_existing_counter( monitor_id, MONITOR_TURN_ON); } - - if (MONITOR_IS_ON(MONITOR_LATCHES)) { - - mutex_monitor.enable(); - } break; case MONITOR_TURN_OFF: @@ -17143,25 +16967,14 @@ innodb_monitor_set_option( MONITOR_OFF(monitor_id); MONITOR_SET_OFF(monitor_id); - - if (!MONITOR_IS_ON(MONITOR_LATCHES)) { - - mutex_monitor.disable(); - } break; case MONITOR_RESET_VALUE: srv_mon_reset(monitor_id); - - if (monitor_id == (MONITOR_LATCHES)) { - - mutex_monitor.reset(); - } break; case MONITOR_RESET_ALL_VALUE: srv_mon_reset_all(monitor_id); - mutex_monitor.reset(); break; default: @@ -18174,7 +17987,7 @@ int wsrep_innobase_kill_one_trx(THD *bf_thd, trx_t *victim_trx, bool signal) { ut_ad(bf_thd); ut_ad(victim_trx); - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); DBUG_ENTER("wsrep_innobase_kill_one_trx"); @@ -18276,11 +18089,11 @@ wsrep_abort_transaction( wsrep_thd_transaction_state_str(victim_thd)); if (victim_trx) { - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); victim_trx->mutex.wr_lock(); int rcode= wsrep_innobase_kill_one_trx(bf_thd, victim_trx, signal); - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); victim_trx->mutex.wr_unlock(); DBUG_RETURN(rcode); } else { @@ -19180,10 +18993,12 @@ static MYSQL_SYSVAR_BOOL(trx_purge_view_update_only_debug, " but the each purges were not done yet.", NULL, NULL, FALSE); +# ifdef SAFE_MUTEX static MYSQL_SYSVAR_BOOL(evict_tables_on_commit_debug, innodb_evict_tables_on_commit_debug, PLUGIN_VAR_OPCMDARG, "On transaction commit, try to evict tables from the data dictionary cache.", NULL, NULL, FALSE); +# endif /* SAFE_MUTEX */ static MYSQL_SYSVAR_UINT(data_file_size_debug, srv_sys_space_size_debug, @@ -19211,11 +19026,6 @@ static MYSQL_SYSVAR_BOOL(page_cleaner_disabled_debug, "Disable page cleaner", NULL, NULL, FALSE); -static MYSQL_SYSVAR_BOOL(sync_debug, srv_sync_debug, - PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, - "Enable the sync debug checks", - NULL, NULL, FALSE); - static MYSQL_SYSVAR_BOOL(dict_stats_disabled_debug, innodb_dict_stats_disabled_debug, PLUGIN_VAR_OPCMDARG, @@ -19471,7 +19281,9 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(trx_rseg_n_slots_debug), MYSQL_SYSVAR(limit_optimistic_insert_debug), MYSQL_SYSVAR(trx_purge_view_update_only_debug), +# ifdef SAFE_MUTEX MYSQL_SYSVAR(evict_tables_on_commit_debug), +# endif /* SAFE_MUTEX */ MYSQL_SYSVAR(data_file_size_debug), MYSQL_SYSVAR(fil_make_page_dirty_debug), MYSQL_SYSVAR(saved_page_number_debug), @@ -19479,7 +19291,6 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(page_cleaner_disabled_debug), MYSQL_SYSVAR(dict_stats_disabled_debug), MYSQL_SYSVAR(master_thread_disabled_debug), - MYSQL_SYSVAR(sync_debug), #endif /* UNIV_DEBUG */ MYSQL_SYSVAR(force_primary_key), MYSQL_SYSVAR(fatal_semaphore_wait_threshold), @@ -19698,9 +19509,9 @@ TABLE* innobase_init_vc_templ(dict_table_t* table) DBUG_RETURN(NULL); } - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); innobase_build_v_templ(mysql_table, table, table->vc_templ, NULL, true); - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); DBUG_RETURN(mysql_table); } @@ -20764,13 +20575,13 @@ ib_foreign_warn(trx_t* trx, /*!< in: trx */ vsprintf(buf, format, args); va_end(args); - mutex_enter(&dict_foreign_err_mutex); + mysql_mutex_lock(&dict_foreign_err_mutex); rewind(ef); ut_print_timestamp(ef); fprintf(ef, " Error in foreign key constraint of table %s:\n", table_name); fputs(buf, ef); - mutex_exit(&dict_foreign_err_mutex); + mysql_mutex_unlock(&dict_foreign_err_mutex); if (trx && trx->mysql_thd) { THD* thd = (THD*)trx->mysql_thd; diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 9c106bdb6bf..8dceb3a21f5 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -486,7 +486,7 @@ inline bool dict_table_t::instant_column(const dict_table_t& table, DBUG_ASSERT(table.n_cols + table.n_dropped() >= n_cols + n_dropped()); DBUG_ASSERT(!table.persistent_autoinc || persistent_autoinc == table.persistent_autoinc); - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); { const char* end = table.col_names; @@ -2592,7 +2592,7 @@ innobase_init_foreign( ulint referenced_num_field) /*!< in: number of referenced columns */ { - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); if (constraint_name) { ulint db_len; @@ -2996,7 +2996,7 @@ innobase_get_foreign_key_info( add_fk[num_fk] = dict_mem_foreign_create(); - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); referenced_table_name = dict_get_referenced_table( table->name.m_name, @@ -3012,7 +3012,7 @@ innobase_get_foreign_key_info( referenced_table = NULL;); if (!referenced_table && trx->check_foreigns) { - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); my_error(ER_FK_CANNOT_OPEN_PARENT, MYF(0), fk_key->ref_table.str); @@ -3045,7 +3045,7 @@ innobase_get_foreign_key_info( /* Check whether there exist such index in the the index create clause */ if (!referenced_index) { - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); my_error(ER_FK_NO_INDEX_PARENT, MYF(0), fk_key->name.str ? fk_key->name.str : "", @@ -3060,7 +3060,7 @@ innobase_get_foreign_key_info( } else { /* Not possible to add a foreign key without a referenced column */ - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); my_error(ER_CANNOT_ADD_FOREIGN, MYF(0), fk_key->ref_table.str); goto err_exit; @@ -3072,7 +3072,7 @@ innobase_get_foreign_key_info( num_col, referenced_table_name, referenced_table, referenced_index, referenced_column_names, referenced_num_col)) { - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); my_error( ER_DUP_CONSTRAINT_NAME, MYF(0), @@ -3080,7 +3080,7 @@ innobase_get_foreign_key_info( goto err_exit; } - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); correct_option = innobase_set_foreign_key_option( add_fk[num_fk], fk_key); @@ -4024,7 +4024,7 @@ online_retry_drop_indexes_low( dict_table_t* table, /*!< in/out: table */ trx_t* trx) /*!< in/out: transaction */ { - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH); ut_ad(trx_get_dict_operation(trx) == TRX_DICT_OP_INDEX); @@ -4061,9 +4061,9 @@ online_retry_drop_indexes( trx->free(); } - ut_d(mutex_enter(&dict_sys.mutex)); + ut_d(dict_sys.mutex_lock()); ut_d(dict_table_check_for_dup_indexes(table, CHECK_ALL_COMPLETE)); - ut_d(mutex_exit(&dict_sys.mutex)); + ut_d(dict_sys.mutex_unlock()); ut_ad(!table->drop_aborted); } @@ -4138,7 +4138,7 @@ innobase_check_foreigns_low( bool drop) { dict_foreign_t* foreign; - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); /* Check if any FOREIGN KEY constraints are defined on this column. */ @@ -6753,7 +6753,7 @@ new_clustered_failed: table. The new_table must be in the data dictionary cache, because we are still holding the dict_sys.mutex. */ - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); temp_table = dict_table_open_on_name( ctx->new_table->name.m_name, TRUE, FALSE, DICT_ERR_IGNORE_NONE); @@ -7078,10 +7078,10 @@ error_handling: case DB_SUCCESS: ut_a(!dict_locked); - ut_d(mutex_enter(&dict_sys.mutex)); + ut_d(dict_sys.mutex_lock()); ut_d(dict_table_check_for_dup_indexes( user_table, CHECK_PARTIAL_OK)); - ut_d(mutex_exit(&dict_sys.mutex)); + ut_d(dict_sys.mutex_unlock()); DBUG_RETURN(false); case DB_TABLESPACE_EXISTS: my_error(ER_TABLESPACE_EXISTS, MYF(0), "(unknown)"); @@ -7505,10 +7505,10 @@ ha_innobase::prepare_inplace_alter_table( } #endif /* UNIV_DEBUG */ - ut_d(mutex_enter(&dict_sys.mutex)); + ut_d(dict_sys.mutex_lock()); ut_d(dict_table_check_for_dup_indexes( m_prebuilt->table, CHECK_ABORTED_OK)); - ut_d(mutex_exit(&dict_sys.mutex)); + ut_d(dict_sys.mutex_unlock()); if (!(ha_alter_info->handler_flags & ~INNOBASE_INPLACE_IGNORE)) { /* Nothing to do */ @@ -8312,7 +8312,6 @@ ha_innobase::inplace_alter_table( bool rebuild_templ = false; DBUG_ENTER("inplace_alter_table"); DBUG_ASSERT(!srv_read_only_mode); - ut_ad(!sync_check_iterate(sync_check())); DEBUG_SYNC(m_user_thd, "innodb_inplace_alter_table_enter"); @@ -8459,10 +8458,10 @@ oom: KEY* dup_key; all_done: case DB_SUCCESS: - ut_d(mutex_enter(&dict_sys.mutex)); + ut_d(dict_sys.mutex_lock()); ut_d(dict_table_check_for_dup_indexes( m_prebuilt->table, CHECK_PARTIAL_OK)); - ut_d(mutex_exit(&dict_sys.mutex)); + ut_d(dict_sys.mutex_unlock()); /* prebuilt->table->n_ref_count can be anything here, given that we hold at most a shared lock on the table. */ goto ok_exit; @@ -8631,7 +8630,7 @@ operation. static ulint innobase_get_uncommitted_fts_indexes(const dict_table_t* table) { - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); dict_index_t* index = dict_table_get_first_index(table); ulint n_uncommitted_fts = 0; @@ -9598,7 +9597,7 @@ innobase_update_foreign_cache( DBUG_ENTER("innobase_update_foreign_cache"); - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); user_table = ctx->old_table; @@ -10294,7 +10293,7 @@ commit_cache_norebuild( if (fil_space_t* space = ctx->new_table->space) { bool update = !(space->flags & FSP_FLAGS_MASK_PAGE_COMPRESSION); - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); space->flags &= ~FSP_FLAGS_MASK_MEM_COMPRESSION_LEVEL; space->flags |= ctx->page_compression_level << FSP_FLAGS_MEM_COMPRESSION_LEVEL; @@ -10306,7 +10305,7 @@ commit_cache_norebuild( |= innodb_compression_algorithm << FSP_FLAGS_FCRC32_POS_COMPRESSED_ALGO; } - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); if (update) { /* Maybe we should introduce an undo diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc index 6314bdc940d..ca0333a70ef 100644 --- a/storage/innobase/handler/i_s.cc +++ b/storage/innobase/handler/i_s.cc @@ -1335,11 +1335,11 @@ i_s_cmp_per_index_fill_low( /* Create a snapshot of the stats so we do not bump into lock order violations with dict_sys.mutex below. */ - mutex_enter(&page_zip_stat_per_index_mutex); + mysql_mutex_lock(&page_zip_stat_per_index_mutex); page_zip_stat_per_index_t snap (page_zip_stat_per_index); - mutex_exit(&page_zip_stat_per_index_mutex); + mysql_mutex_unlock(&page_zip_stat_per_index_mutex); - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); page_zip_stat_per_index_t::iterator iter; ulint i; @@ -1397,13 +1397,13 @@ i_s_cmp_per_index_fill_low( contents of INFORMATION_SCHEMA.innodb_cmp_per_index being inconsistent, but it is an acceptable compromise. */ if (i == 1000) { - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); i = 0; - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); } } - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); if (reset) { page_zip_reset_stat_per_index(); @@ -2973,9 +2973,7 @@ i_s_fts_index_table_fill_selected( } } - mutex_enter(&dict_sys.mutex); - que_graph_free(graph); - mutex_exit(&dict_sys.mutex); + fts_que_graph_free(graph); trx->free(); @@ -3996,7 +3994,7 @@ i_s_innodb_buffer_page_fill( if (page_info->page_type == I_S_PAGE_TYPE_INDEX) { bool ret = false; - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); const dict_index_t* index = dict_index_get_if_in_cache_low( @@ -4021,7 +4019,7 @@ i_s_innodb_buffer_page_fill( system_charset_info); } - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); OK(ret); @@ -4500,7 +4498,7 @@ i_s_innodb_buf_page_lru_fill( if (page_info->page_type == I_S_PAGE_TYPE_INDEX) { bool ret = false; - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); const dict_index_t* index = dict_index_get_if_in_cache_low( @@ -4525,7 +4523,7 @@ i_s_innodb_buf_page_lru_fill( system_charset_info); } - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); OK(ret); @@ -4846,7 +4844,7 @@ i_s_sys_tables_fill_table( } heap = mem_heap_create(1000); - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); mtr_start(&mtr); rec = dict_startscan_system(&pcur, &mtr, SYS_TABLES); @@ -4860,7 +4858,7 @@ i_s_sys_tables_fill_table( err_msg = dict_process_sys_tables_rec_and_mtr_commit( heap, rec, &table_rec, false, &mtr); - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); if (!err_msg) { i_s_dict_fill_sys_tables(thd, table_rec, @@ -4878,13 +4876,13 @@ i_s_sys_tables_fill_table( mem_heap_empty(heap); /* Get the next record */ - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); mtr_start(&mtr); rec = dict_getnext_system(&pcur, &mtr); } mtr_commit(&mtr); - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); mem_heap_free(heap); DBUG_RETURN(0); @@ -5025,8 +5023,8 @@ i_s_dict_fill_sys_tablestats( { struct Locking { - Locking() { mutex_enter(&dict_sys.mutex); } - ~Locking() { mutex_exit(&dict_sys.mutex); } + Locking() { dict_sys.mutex_lock(); } + ~Locking() { dict_sys.mutex_unlock(); } } locking; OK(fields[SYS_TABLESTATS_INIT]->store(table->stat_initialized, @@ -5093,7 +5091,7 @@ i_s_sys_tables_fill_table_stats( heap = mem_heap_create(1000); dict_sys.freeze(); - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); mtr_start(&mtr); rec = dict_startscan_system(&pcur, &mtr, SYS_TABLES); @@ -5108,7 +5106,7 @@ i_s_sys_tables_fill_table_stats( heap, rec, &table_rec, true, &mtr); ulint ref_count = table_rec ? table_rec->get_ref_count() : 0; - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); DBUG_EXECUTE_IF("test_sys_tablestats", { if (strcmp("test/t1", table_rec->name.m_name) == 0 ) { @@ -5131,14 +5129,14 @@ i_s_sys_tables_fill_table_stats( /* Get the next record */ dict_sys.freeze(); - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); mtr_start(&mtr); rec = dict_getnext_system(&pcur, &mtr); } mtr_commit(&mtr); - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); dict_sys.unfreeze(); mem_heap_free(heap); @@ -5333,7 +5331,7 @@ i_s_sys_indexes_fill_table( } heap = mem_heap_create(1000); - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); mtr_start(&mtr); /* Start scan the SYS_INDEXES table */ @@ -5355,7 +5353,7 @@ i_s_sys_indexes_fill_table( space_id = space_id == 4 ? mach_read_from_4(field) : ULINT_UNDEFINED; mtr_commit(&mtr); - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); if (!err_msg) { if (int err = i_s_dict_fill_sys_indexes( @@ -5373,13 +5371,13 @@ i_s_sys_indexes_fill_table( mem_heap_empty(heap); /* Get the next record */ - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); mtr_start(&mtr); rec = dict_getnext_system(&pcur, &mtr); } mtr_commit(&mtr); - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); mem_heap_free(heap); DBUG_RETURN(0); @@ -5552,7 +5550,7 @@ i_s_sys_columns_fill_table( } heap = mem_heap_create(1000); - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); mtr_start(&mtr); rec = dict_startscan_system(&pcur, &mtr, SYS_COLUMNS); @@ -5570,7 +5568,7 @@ i_s_sys_columns_fill_table( &nth_v_col); mtr_commit(&mtr); - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); if (!err_msg) { i_s_dict_fill_sys_columns(thd, table_id, col_name, @@ -5585,13 +5583,13 @@ i_s_sys_columns_fill_table( mem_heap_empty(heap); /* Get the next record */ - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); mtr_start(&mtr); rec = dict_getnext_system(&pcur, &mtr); } mtr_commit(&mtr); - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); mem_heap_free(heap); DBUG_RETURN(0); @@ -5745,7 +5743,7 @@ i_s_sys_virtual_fill_table( DBUG_RETURN(0); } - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); mtr_start(&mtr); rec = dict_startscan_system(&pcur, &mtr, SYS_VIRTUAL); @@ -5761,7 +5759,7 @@ i_s_sys_virtual_fill_table( &base_pos); mtr_commit(&mtr); - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); if (!err_msg) { i_s_dict_fill_sys_virtual(thd, table_id, pos, base_pos, @@ -5773,13 +5771,13 @@ i_s_sys_virtual_fill_table( } /* Get the next record */ - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); mtr_start(&mtr); rec = dict_getnext_system(&pcur, &mtr); } mtr_commit(&mtr); - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); DBUG_RETURN(0); } @@ -5931,7 +5929,7 @@ i_s_sys_fields_fill_table( } heap = mem_heap_create(1000); - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); mtr_start(&mtr); /* will save last index id so that we know whether we move to @@ -5952,7 +5950,7 @@ i_s_sys_fields_fill_table( &pos, &index_id, last_id); mtr_commit(&mtr); - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); if (!err_msg) { i_s_dict_fill_sys_fields(thd, index_id, &field_rec, @@ -5967,13 +5965,13 @@ i_s_sys_fields_fill_table( mem_heap_empty(heap); /* Get the next record */ - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); mtr_start(&mtr); rec = dict_getnext_system(&pcur, &mtr); } mtr_commit(&mtr); - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); mem_heap_free(heap); DBUG_RETURN(0); @@ -6135,7 +6133,7 @@ i_s_sys_foreign_fill_table( } heap = mem_heap_create(1000); - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); mtr_start(&mtr); rec = dict_startscan_system(&pcur, &mtr, SYS_FOREIGN); @@ -6149,7 +6147,7 @@ i_s_sys_foreign_fill_table( err_msg = dict_process_sys_foreign_rec(heap, rec, &foreign_rec); mtr_commit(&mtr); - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); if (!err_msg) { i_s_dict_fill_sys_foreign(thd, &foreign_rec, @@ -6164,12 +6162,12 @@ i_s_sys_foreign_fill_table( /* Get the next record */ mtr_start(&mtr); - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); rec = dict_getnext_system(&pcur, &mtr); } mtr_commit(&mtr); - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); mem_heap_free(heap); DBUG_RETURN(0); @@ -6327,7 +6325,7 @@ i_s_sys_foreign_cols_fill_table( } heap = mem_heap_create(1000); - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); mtr_start(&mtr); rec = dict_startscan_system(&pcur, &mtr, SYS_FOREIGN_COLS); @@ -6344,7 +6342,7 @@ i_s_sys_foreign_cols_fill_table( heap, rec, &name, &for_col_name, &ref_col_name, &pos); mtr_commit(&mtr); - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); if (!err_msg) { i_s_dict_fill_sys_foreign_cols( @@ -6359,13 +6357,13 @@ i_s_sys_foreign_cols_fill_table( mem_heap_empty(heap); /* Get the next record */ - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); mtr_start(&mtr); rec = dict_getnext_system(&pcur, &mtr); } mtr_commit(&mtr); - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); mem_heap_free(heap); DBUG_RETURN(0); @@ -6552,7 +6550,7 @@ static int i_s_sys_tablespaces_fill_table(THD *thd, TABLE_LIST *tables, Item*) int err= 0; - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); fil_system.freeze_space_list++; for (fil_space_t *space= UT_LIST_GET_FIRST(fil_system.space_list); @@ -6562,9 +6560,9 @@ static int i_s_sys_tablespaces_fill_table(THD *thd, TABLE_LIST *tables, Item*) space->chain.start) { space->reacquire(); - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); err= i_s_sys_tablespaces_fill(thd, *space, tables->table); - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); space->release(); if (err) break; @@ -6572,7 +6570,7 @@ static int i_s_sys_tablespaces_fill_table(THD *thd, TABLE_LIST *tables, Item*) } fil_system.freeze_space_list--; - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); DBUG_RETURN(err); } @@ -6772,7 +6770,7 @@ i_s_tablespaces_encryption_fill_table( } int err = 0; - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); fil_system.freeze_space_list++; for (fil_space_t* space = UT_LIST_GET_FIRST(fil_system.space_list); @@ -6780,10 +6778,10 @@ i_s_tablespaces_encryption_fill_table( if (space->purpose == FIL_TYPE_TABLESPACE && !space->is_stopping()) { space->reacquire(); - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); err = i_s_dict_fill_tablespaces_encryption( thd, space, tables->table); - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); space->release(); if (err) { break; @@ -6792,7 +6790,7 @@ i_s_tablespaces_encryption_fill_table( } fil_system.freeze_space_list--; - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); DBUG_RETURN(err); } /*******************************************************************//** diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc index a7f623a21ff..93e40aa732a 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.cc +++ b/storage/innobase/ibuf/ibuf0ibuf.cc @@ -25,7 +25,6 @@ Created 7/19/1997 Heikki Tuuri *******************************************************/ #include "ibuf0ibuf.h" -#include "sync0sync.h" #include "btr0sea.h" /** Number of bits describing a single page */ @@ -234,14 +233,15 @@ type, counter, and some flags. */ format or later */ -/** The mutex used to block pessimistic inserts to ibuf trees */ -static ib_mutex_t ibuf_pessimistic_insert_mutex; - -/** The mutex protecting the insert buffer structs */ -static ib_mutex_t ibuf_mutex; - -/** The mutex protecting the insert buffer bitmaps */ -static ib_mutex_t ibuf_bitmap_mutex; +#ifndef SAFE_MUTEX +static +#endif /* SAFE_MUTEX */ +/** The mutex protecting the insert buffer */ +mysql_mutex_t ibuf_mutex, + /** The mutex covering pessimistic inserts into the change buffer */ + ibuf_pessimistic_insert_mutex, + /** mutex covering all change buffer bitmap pages */ + ibuf_bitmap_mutex; /** The area in pages from which contract looks for page numbers for merge */ const ulint IBUF_MERGE_AREA = 8; @@ -332,7 +332,7 @@ static buf_block_t *ibuf_tree_root_get(mtr_t *mtr) buf_block_t* block; ut_ad(ibuf_inside(mtr)); - ut_ad(mutex_own(&ibuf_mutex)); + mysql_mutex_assert_owner(&ibuf_mutex); mtr_sx_lock_index(ibuf.index, mtr); @@ -358,11 +358,9 @@ ibuf_close(void) return; } - mutex_free(&ibuf_pessimistic_insert_mutex); - - mutex_free(&ibuf_mutex); - - mutex_free(&ibuf_bitmap_mutex); + mysql_mutex_destroy(&ibuf_pessimistic_insert_mutex); + mysql_mutex_destroy(&ibuf_mutex); + mysql_mutex_destroy(&ibuf_bitmap_mutex); dict_table_t* ibuf_table = ibuf.index->table; ibuf.index->lock.free(); @@ -380,7 +378,7 @@ ibuf_size_update( /*=============*/ const page_t* root) /*!< in: ibuf tree root */ { - ut_ad(mutex_own(&ibuf_mutex)); + mysql_mutex_assert_owner(&ibuf_mutex); ibuf.free_list_len = flst_get_len(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST); @@ -425,14 +423,12 @@ ibuf_init_at_db_start(void) ibuf.max_size = ((buf_pool_get_curr_size() >> srv_page_size_shift) * CHANGE_BUFFER_DEFAULT_SIZE) / 100; - mutex_create(LATCH_ID_IBUF, &ibuf_mutex); - - mutex_create(LATCH_ID_IBUF_BITMAP, &ibuf_bitmap_mutex); - - mutex_create(LATCH_ID_IBUF_PESSIMISTIC_INSERT, - &ibuf_pessimistic_insert_mutex); + mysql_mutex_init(ibuf_mutex_key, &ibuf_mutex, nullptr); + mysql_mutex_init(ibuf_bitmap_mutex_key, &ibuf_bitmap_mutex, nullptr); + mysql_mutex_init(ibuf_pessimistic_insert_mutex_key, + &ibuf_pessimistic_insert_mutex, nullptr); - mutex_enter(&ibuf_mutex); + mysql_mutex_lock(&ibuf_mutex); fseg_n_reserved_pages(*header_page, IBUF_HEADER + IBUF_TREE_SEG_HEADER @@ -453,7 +449,7 @@ ibuf_init_at_db_start(void) } ibuf_size_update(root); - mutex_exit(&ibuf_mutex); + mysql_mutex_unlock(&ibuf_mutex); ibuf.empty = page_is_empty(root); mtr.commit(); @@ -503,9 +499,9 @@ ibuf_max_size_update( { ulint new_size = ((buf_pool_get_curr_size() >> srv_page_size_shift) * new_val) / 100; - mutex_enter(&ibuf_mutex); + mysql_mutex_lock(&ibuf_mutex); ibuf.max_size = new_size; - mutex_exit(&ibuf_mutex); + mysql_mutex_unlock(&ibuf_mutex); } # ifdef UNIV_DEBUG @@ -876,7 +872,7 @@ ibuf_update_free_bits_for_two_pages_low( the bitmap mutex to prevent a deadlock with a similar operation performed by another OS thread. */ - mutex_enter(&ibuf_bitmap_mutex); + mysql_mutex_lock(&ibuf_bitmap_mutex); state = ibuf_index_page_calc_free(block1); @@ -886,7 +882,7 @@ ibuf_update_free_bits_for_two_pages_low( ibuf_set_free_bits_low(block2, state, mtr); - mutex_exit(&ibuf_bitmap_mutex); + mysql_mutex_unlock(&ibuf_bitmap_mutex); } /** Returns TRUE if the page is one of the fixed address ibuf pages. @@ -1753,7 +1749,7 @@ dare to start a pessimistic insert to the insert buffer. @return whether enough free pages in list */ static inline bool ibuf_data_enough_free_for_insert() { - ut_ad(mutex_own(&ibuf_mutex)); + mysql_mutex_assert_owner(&ibuf_mutex); /* We want a big margin of free pages, because a B-tree can sometimes grow in size also if records are deleted from it, as the node pointers @@ -1773,7 +1769,7 @@ ibool ibuf_data_too_much_free(void) /*=========================*/ { - ut_ad(mutex_own(&ibuf_mutex)); + mysql_mutex_assert_owner(&ibuf_mutex); return(ibuf.free_list_len >= 3 + (ibuf.size / 2) + 3 * ibuf.height); } @@ -1814,7 +1810,7 @@ static bool ibuf_add_free_page() ut_ad(block->lock.not_recursive()); ibuf_enter(&mtr); - mutex_enter(&ibuf_mutex); + mysql_mutex_lock(&ibuf_mutex); mtr.write<2>(*block, block->frame + FIL_PAGE_TYPE, FIL_PAGE_IBUF_FREE_LIST); @@ -1834,7 +1830,7 @@ static bool ibuf_add_free_page() const page_id_t page_id(block->page.id()); buf_block_t* bitmap_page = ibuf_bitmap_get_map_page(page_id, 0, &mtr); - mutex_exit(&ibuf_mutex); + mysql_mutex_unlock(&ibuf_mutex); ibuf_bitmap_page_set_bits<IBUF_BITMAP_IBUF>(bitmap_page, page_id, srv_page_size, true, @@ -1867,13 +1863,13 @@ ibuf_remove_free_page(void) /* Prevent pessimistic inserts to insert buffer trees for a while */ ibuf_enter(&mtr); - mutex_enter(&ibuf_pessimistic_insert_mutex); - mutex_enter(&ibuf_mutex); + mysql_mutex_lock(&ibuf_pessimistic_insert_mutex); + mysql_mutex_lock(&ibuf_mutex); if (!ibuf_data_too_much_free()) { - mutex_exit(&ibuf_mutex); - mutex_exit(&ibuf_pessimistic_insert_mutex); + mysql_mutex_unlock(&ibuf_mutex); + mysql_mutex_unlock(&ibuf_pessimistic_insert_mutex); ibuf_mtr_commit(&mtr); @@ -1884,7 +1880,7 @@ ibuf_remove_free_page(void) buf_block_t* root = ibuf_tree_root_get(&mtr2); - mutex_exit(&ibuf_mutex); + mysql_mutex_unlock(&ibuf_mutex); uint32_t page_no = flst_get_last(PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST + root->frame).page; @@ -1910,7 +1906,7 @@ ibuf_remove_free_page(void) ibuf_enter(&mtr); - mutex_enter(&ibuf_mutex); + mysql_mutex_lock(&ibuf_mutex); root = ibuf_tree_root_get(&mtr); @@ -1924,7 +1920,7 @@ ibuf_remove_free_page(void) flst_remove(root, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, block, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, &mtr); - mutex_exit(&ibuf_pessimistic_insert_mutex); + mysql_mutex_unlock(&ibuf_pessimistic_insert_mutex); ibuf.seg_size--; ibuf.free_list_len--; @@ -1934,7 +1930,7 @@ ibuf_remove_free_page(void) buf_block_t* bitmap_page = ibuf_bitmap_get_map_page(page_id, 0, &mtr); - mutex_exit(&ibuf_mutex); + mysql_mutex_unlock(&ibuf_mutex); ibuf_bitmap_page_set_bits<IBUF_BITMAP_IBUF>( bitmap_page, page_id, srv_page_size, false, &mtr); @@ -1959,9 +1955,9 @@ ibuf_free_excess_pages(void) ibool too_much_free; - mutex_enter(&ibuf_mutex); + mysql_mutex_lock(&ibuf_mutex); too_much_free = ibuf_data_too_much_free(); - mutex_exit(&ibuf_mutex); + mysql_mutex_unlock(&ibuf_mutex); if (!too_much_free) { return; @@ -3199,16 +3195,16 @@ ibuf_insert_low( if (BTR_LATCH_MODE_WITHOUT_INTENTION(mode) == BTR_MODIFY_TREE) { for (;;) { - mutex_enter(&ibuf_pessimistic_insert_mutex); - mutex_enter(&ibuf_mutex); + mysql_mutex_lock(&ibuf_pessimistic_insert_mutex); + mysql_mutex_lock(&ibuf_mutex); if (UNIV_LIKELY(ibuf_data_enough_free_for_insert())) { break; } - mutex_exit(&ibuf_mutex); - mutex_exit(&ibuf_pessimistic_insert_mutex); + mysql_mutex_unlock(&ibuf_mutex); + mysql_mutex_unlock(&ibuf_pessimistic_insert_mutex); if (!ibuf_add_free_page()) { @@ -3256,8 +3252,8 @@ ibuf_insert_low( fail_exit: if (BTR_LATCH_MODE_WITHOUT_INTENTION(mode) == BTR_MODIFY_TREE) { - mutex_exit(&ibuf_mutex); - mutex_exit(&ibuf_pessimistic_insert_mutex); + mysql_mutex_unlock(&ibuf_mutex); + mysql_mutex_unlock(&ibuf_pessimistic_insert_mutex); } err = DB_STRONG_FAIL; @@ -3284,9 +3280,9 @@ commit_exit: ibuf_mtr_commit(&bitmap_mtr); goto fail_exit; } else { - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); const auto lock_exists = lock_sys.get_first(page_id); - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); if (lock_exists) { goto commit_exit; } @@ -3390,9 +3386,9 @@ commit_exit: &dummy_big_rec, 0, thr, &mtr); } - mutex_exit(&ibuf_pessimistic_insert_mutex); + mysql_mutex_unlock(&ibuf_pessimistic_insert_mutex); ibuf_size_update(root); - mutex_exit(&ibuf_mutex); + mysql_mutex_unlock(&ibuf_mutex); ibuf.empty = page_is_empty(root); block = btr_cur_get_block(cursor); @@ -4054,13 +4050,13 @@ bool ibuf_delete_rec(const page_id_t page_id, btr_pcur_t* pcur, ibuf_btr_pcur_commit_specify_mtr(pcur, mtr); ibuf_mtr_start(mtr); - mutex_enter(&ibuf_mutex); + mysql_mutex_lock(&ibuf_mutex); if (!ibuf_restore_pos(page_id, search_tuple, BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE, pcur, mtr)) { - mutex_exit(&ibuf_mutex); + mysql_mutex_unlock(&ibuf_mutex); ut_ad(mtr->has_committed()); goto func_exit; } @@ -4072,7 +4068,7 @@ bool ibuf_delete_rec(const page_id_t page_id, btr_pcur_t* pcur, ut_a(err == DB_SUCCESS); ibuf_size_update(root); - mutex_exit(&ibuf_mutex); + mysql_mutex_unlock(&ibuf_mutex); ibuf.empty = page_is_empty(root); ibuf_btr_pcur_commit_specify_mtr(pcur, mtr); @@ -4494,11 +4490,11 @@ ibuf_is_empty(void) ibuf_mtr_start(&mtr); - ut_d(mutex_enter(&ibuf_mutex)); + ut_d(mysql_mutex_lock(&ibuf_mutex)); const buf_block_t* root = ibuf_tree_root_get(&mtr); bool is_empty = page_is_empty(root->frame); ut_a(is_empty == ibuf.empty); - ut_d(mutex_exit(&ibuf_mutex)); + ut_d(mysql_mutex_unlock(&ibuf_mutex)); ibuf_mtr_commit(&mtr); return(is_empty); @@ -4511,7 +4507,7 @@ ibuf_print( /*=======*/ FILE* file) /*!< in: file where to print */ { - mutex_enter(&ibuf_mutex); + mysql_mutex_lock(&ibuf_mutex); fprintf(file, "Ibuf: size " ULINTPF ", free list len " ULINTPF "," @@ -4527,7 +4523,7 @@ ibuf_print( fputs("discarded operations:\n ", file); ibuf_print_ops(ibuf.n_discarded_ops, file); - mutex_exit(&ibuf_mutex); + mysql_mutex_unlock(&ibuf_mutex); } /** Check the insert buffer bitmaps on IMPORT TABLESPACE. @@ -4550,7 +4546,7 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space) mtr_t mtr; - mutex_enter(&ibuf_mutex); + mysql_mutex_lock(&ibuf_mutex); /* The two bitmap pages (allocation bitmap and ibuf bitmap) repeat every page_size pages. For example if page_size is 16 KiB, then the @@ -4560,7 +4556,7 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space) for (uint32_t page_no = 0; page_no < size; page_no += physical_size) { if (trx_is_interrupted(trx)) { - mutex_exit(&ibuf_mutex); + mysql_mutex_unlock(&ibuf_mutex); return(DB_INTERRUPTED); } @@ -4573,7 +4569,7 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space) buf_block_t* bitmap_page = ibuf_bitmap_get_map_page( page_id_t(space->id, page_no), zip_size, &mtr); if (!bitmap_page) { - mutex_exit(&ibuf_mutex); + mysql_mutex_unlock(&ibuf_mutex); mtr.commit(); return DB_CORRUPTION; } @@ -4610,7 +4606,7 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space) bitmap_page->frame, cur_page_id, zip_size, IBUF_BITMAP_IBUF, &mtr)) { - mutex_exit(&ibuf_mutex); + mysql_mutex_unlock(&ibuf_mutex); ibuf_exit(&mtr); mtr_commit(&mtr); @@ -4648,7 +4644,7 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space) mtr_commit(&mtr); } - mutex_exit(&ibuf_mutex); + mysql_mutex_unlock(&ibuf_mutex); return(DB_SUCCESS); } 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 diff --git a/storage/innobase/innodb.cmake b/storage/innobase/innodb.cmake index 83232a4d66c..5c7784091bd 100644 --- a/storage/innobase/innodb.cmake +++ b/storage/innobase/innodb.cmake @@ -137,14 +137,6 @@ IF(HAVE_C99_INITIALIZERS) ADD_DEFINITIONS(-DHAVE_C99_INITIALIZERS) ENDIF() -SET(MUTEXTYPE "sys" CACHE STRING "Mutex type: sys or futex") - -IF(MUTEXTYPE MATCHES "futex" AND DEFINED HAVE_IB_LINUX_FUTEX) - ADD_DEFINITIONS(-DMUTEX_FUTEX) -ELSE() - ADD_DEFINITIONS(-DMUTEX_SYS) -ENDIF() - OPTION(WITH_INNODB_DISALLOW_WRITES "InnoDB freeze writes patch from Google" ${WITH_WSREP}) IF (WITH_INNODB_DISALLOW_WRITES) ADD_DEFINITIONS(-DWITH_INNODB_DISALLOW_WRITES) diff --git a/storage/innobase/lock/lock0iter.cc b/storage/innobase/lock/lock0iter.cc index ad057731804..d082aef07c9 100644 --- a/storage/innobase/lock/lock0iter.cc +++ b/storage/innobase/lock/lock0iter.cc @@ -49,7 +49,7 @@ lock_queue_iterator_reset( ulint bit_no) /*!< in: record number in the heap */ { - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); iter->current_lock = lock; @@ -84,7 +84,7 @@ lock_queue_iterator_get_prev( { const lock_t* prev_lock; - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); switch (lock_get_type_low(iter->current_lock)) { case LOCK_REC: diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index b96f150a3d0..1c78f963e02 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -42,7 +42,7 @@ Created 5/7/1996 Heikki Tuuri #include "row0mysql.h" #include "row0vers.h" #include "pars0pars.h" -#include "sync0sync.h" +#include "srv0mon.h" #include <set> @@ -304,6 +304,12 @@ static bool lock_rec_validate_page(const buf_block_t *block, bool latched) /* The lock system */ lock_sys_t lock_sys; +/** Diagnostic message for exceeding the mutex_lock_wait() timeout */ +const char lock_sys_t::fatal_msg[]= + "innodb_fatal_semaphore_wait_threshold was exceeded for lock_sys.mutex. " + "Please refer to " + "https://mariadb.com/kb/en/how-to-produce-a-full-stack-trace-for-mysqld/"; + /** We store info on the latest deadlock error to this buffer. InnoDB Monitor will then fetch it and print */ static bool lock_deadlock_found = false; @@ -470,6 +476,41 @@ void lock_sys_t::create(ulint n_cells) timeout_timer_active = false; } +void lock_sys_t::mutex_lock_wait() +{ + ulonglong now= my_hrtime_coarse().val, old= 0; + if (mutex_wait_start.compare_exchange_strong + (old, now, std::memory_order_relaxed, std::memory_order_relaxed)) + { + mysql_mutex_lock(&mutex); + mutex_wait_start.store(0, std::memory_order_relaxed); + return; + } + + ut_ad(old); + /* We could have old > now due to our use of my_hrtime_coarse(). */ + ulong waited= old <= now ? static_cast<ulong>((now - old) / 1000000) : 0; + const ulong threshold= srv_fatal_semaphore_wait_threshold; + + if (waited >= threshold) + ib::fatal() << fatal_msg; + + if (waited > threshold / 4) + ib::warn() << "A long wait (" << waited + << " seconds) was observed for lock_sys.mutex"; + mysql_mutex_lock(&mutex); +} + +#ifdef HAVE_PSI_MUTEX_INTERFACE +/** Try to acquire lock_sys.mutex */ +int lock_sys_t::mutex_trylock() { return mysql_mutex_trylock(&mutex); } +/** Acquire lock_sys.mutex */ +void lock_sys_t::mutex_lock() { if (mutex_trylock()) mutex_lock_wait(); } +/** Release lock_sys.mutex */ +void lock_sys_t::mutex_unlock() { mysql_mutex_unlock(&mutex); } +#endif + + /** Calculates the fold value of a lock: used in migrating the hash table. @param[in] lock record lock object @return folded value */ @@ -488,7 +529,7 @@ void lock_sys_t::resize(ulint n_cells) { ut_ad(this == &lock_sys); - mysql_mutex_lock(&mutex); + mutex_lock(); hash_table_t old_hash(rec_hash); rec_hash.create(n_cells); @@ -507,7 +548,7 @@ void lock_sys_t::resize(ulint n_cells) HASH_MIGRATE(&old_hash, &prdt_page_hash, lock_t, hash, lock_rec_lock_fold); old_hash.free(); - mysql_mutex_unlock(&mutex); + mutex_unlock(); } @@ -873,7 +914,7 @@ lock_rec_get_prev( lock_t* lock; lock_t* found_lock = NULL; - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); ut_ad(lock_get_type_low(in_lock) == LOCK_REC); for (lock = lock_sys.get_first(*lock_hash_get(in_lock->type_mode), @@ -910,7 +951,7 @@ lock_rec_has_expl( { lock_t* lock; - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); ut_ad((precise_mode & LOCK_MODE_MASK) == LOCK_S || (precise_mode & LOCK_MODE_MASK) == LOCK_X); ut_ad(!(precise_mode & LOCK_INSERT_INTENTION)); @@ -959,7 +1000,7 @@ lock_rec_other_has_expl_req( are taken into account */ { - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); ut_ad(mode == LOCK_X || mode == LOCK_S); /* Only GAP lock can be on SUPREMUM, and we are not looking for @@ -994,7 +1035,7 @@ wsrep_kill_victim( const trx_t * const trx, const lock_t *lock) { - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); /* quit for native mysql */ if (!trx->is_wsrep()) return; @@ -1069,7 +1110,7 @@ lock_rec_other_has_conflicting( { lock_t* lock; - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); bool is_supremum = (heap_no == PAGE_HEAP_NO_SUPREMUM); @@ -1115,7 +1156,7 @@ lock_sec_rec_some_has_impl( trx_id_t max_trx_id; const page_t* page = page_align(rec); - mysql_mutex_assert_not_owner(&lock_sys.mutex); + lock_sys.mutex_assert_unlocked(); ut_ad(!dict_index_is_clust(index)); ut_ad(page_rec_is_user_rec(rec)); ut_ad(rec_offs_validate(rec, index, offsets)); @@ -1156,7 +1197,7 @@ lock_number_of_rows_locked( /*=======================*/ const trx_lock_t* trx_lock) /*!< in: transaction locks */ { - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); return(trx_lock->n_rec_locks); } @@ -1172,7 +1213,7 @@ lock_number_of_tables_locked( const lock_t* lock; ulint n_tables = 0; - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); for (lock = UT_LIST_GET_FIRST(trx_lock->trx_locks); lock != NULL; @@ -1247,7 +1288,7 @@ lock_rec_create_low( ulint n_bits; ulint n_bytes; - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); ut_ad(dict_index_is_clust(index) || !dict_index_is_online_ddl(index)); #ifdef UNIV_DEBUG @@ -1431,7 +1472,7 @@ lock_rec_enqueue_waiting( que_thr_t* thr, lock_prdt_t* prdt) { - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); ut_ad(!srv_read_only_mode); ut_ad(dict_index_is_clust(index) || !dict_index_is_online_ddl(index)); @@ -1520,7 +1561,7 @@ lock_rec_find_similar_on_page( lock_t* lock, /*!< in: lock_sys.get_first() */ const trx_t* trx) /*!< in: transaction */ { - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); for (/* No op */; lock != NULL; @@ -1561,7 +1602,7 @@ lock_rec_add_to_queue( /*!< in: TRUE if caller owns the transaction mutex */ { - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); ut_ad(index->is_primary() || dict_index_get_online_status(index) != ONLINE_INDEX_CREATION); #ifdef UNIV_DEBUG @@ -1690,7 +1731,7 @@ lock_rec_lock( ut_ad(dict_index_is_clust(index) || !dict_index_is_online_ddl(index)); DBUG_EXECUTE_IF("innodb_report_deadlock", return DB_DEADLOCK;); - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); ut_ad((LOCK_MODE_MASK & mode) != LOCK_S || lock_table_has(trx, index->table, LOCK_IS)); ut_ad((LOCK_MODE_MASK & mode) != LOCK_X || @@ -1764,7 +1805,7 @@ lock_rec_lock( err= DB_SUCCESS_LOCKED_REC; } - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); MONITOR_ATOMIC_INC(MONITOR_NUM_RECLOCK_REQ); return err; } @@ -1784,7 +1825,7 @@ lock_rec_has_to_wait_in_queue( ulint bit_offset; ut_ad(wait_lock); - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); ut_ad(lock_get_wait(wait_lock)); ut_ad(lock_get_type_low(wait_lock) == LOCK_REC); @@ -1813,7 +1854,7 @@ lock_rec_has_to_wait_in_queue( after lock_reset_lock_and_trx_wait() has been called. */ static void lock_grant_after_reset(lock_t* lock) { - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); if (lock_get_mode(lock) == LOCK_AUTO_INC) { dict_table_t* table = lock->un_member.tab_lock.table; @@ -1867,7 +1908,7 @@ lock_rec_cancel( /*============*/ lock_t* lock) /*!< in: waiting record lock request */ { - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); ut_ad(lock_get_type_low(lock) == LOCK_REC); /* Reset the bit (there can be only one set bit) in the lock bitmap */ @@ -1895,7 +1936,7 @@ static void lock_rec_dequeue_from_page(lock_t* in_lock) { hash_table_t* lock_hash; - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); ut_ad(lock_get_type_low(in_lock) == LOCK_REC); /* We may or may not be holding in_lock->trx->mutex here. */ @@ -1948,7 +1989,7 @@ lock_rec_discard( { trx_lock_t* trx_lock; - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); ut_ad(lock_get_type_low(in_lock) == LOCK_REC); trx_lock = &in_lock->trx->lock; @@ -2014,7 +2055,7 @@ lock_rec_reset_and_release_wait_low( { lock_t* lock; - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); for (lock = lock_rec_get_first(hash, block, heap_no); lock != NULL; @@ -2070,7 +2111,7 @@ lock_rec_inherit_to_gap( { lock_t* lock; - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); /* At READ UNCOMMITTED or READ COMMITTED isolation level, we do not want locks set @@ -2112,7 +2153,7 @@ lock_rec_inherit_to_gap_if_gap_lock( { lock_t* lock; - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); for (lock = lock_rec_get_first(&lock_sys.rec_hash, block, heap_no); lock != NULL; @@ -2129,7 +2170,7 @@ lock_rec_inherit_to_gap_if_gap_lock( } } - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); } /*************************************************************//** @@ -2153,7 +2194,7 @@ lock_rec_move_low( { lock_t* lock; - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); /* If the lock is predicate lock, it resides on INFIMUM record */ ut_ad(lock_rec_get_first( @@ -2259,13 +2300,13 @@ lock_move_reorganize_page( mem_heap_t* heap = NULL; ulint comp; - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); /* FIXME: This needs to deal with predicate lock too */ lock = lock_sys.get_first(block->page.id()); if (lock == NULL) { - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); return; } @@ -2361,7 +2402,7 @@ lock_move_reorganize_page( ut_ad(lock_rec_find_set_bit(lock) == ULINT_UNDEFINED); } - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); mem_heap_free(heap); @@ -2390,7 +2431,7 @@ lock_move_rec_list_end( ut_ad(buf_block_get_frame(block) == page_align(rec)); ut_ad(comp == page_is_comp(buf_block_get_frame(new_block))); - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); /* Note: when we move locks from record to record, waiting locks and possible granted gap type locks behind them are enqueued in @@ -2478,7 +2519,7 @@ lock_move_rec_list_end( } } - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); #ifdef UNIV_DEBUG_LOCK_VALIDATE if (fil_space_t* space = fil_space_t::get(page_id.space())) { @@ -2516,7 +2557,7 @@ lock_move_rec_list_start( ut_ad(comp == page_rec_is_comp(old_end)); ut_ad(!page_rec_is_metadata(rec)); - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); for (lock = lock_sys.get_first(block->page.id()); lock; @@ -2596,7 +2637,7 @@ lock_move_rec_list_start( #endif /* UNIV_DEBUG */ } - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); #ifdef UNIV_DEBUG_LOCK_VALIDATE ut_ad(lock_rec_validate_page(block)); @@ -2629,7 +2670,7 @@ lock_rtr_move_rec_list( ut_ad(new_block->frame == page_align(rec_move[0].new_rec)); ut_ad(comp == page_rec_is_comp(rec_move[0].new_rec)); - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); for (lock = lock_sys.get_first(block->page.id()); lock; @@ -2680,7 +2721,7 @@ lock_rtr_move_rec_list( } } - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); #ifdef UNIV_DEBUG_LOCK_VALIDATE ut_ad(lock_rec_validate_page(block)); @@ -2696,7 +2737,7 @@ lock_update_split_right( { ulint heap_no = lock_get_min_heap_no(right_block); - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); /* Move the locks on the supremum of the left page to the supremum of the right page */ @@ -2710,7 +2751,7 @@ lock_update_split_right( lock_rec_inherit_to_gap(left_block, right_block, PAGE_HEAP_NO_SUPREMUM, heap_no); - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); } /*************************************************************//** @@ -2730,7 +2771,7 @@ lock_update_merge_right( { ut_ad(!page_rec_is_metadata(orig_succ)); - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); /* Inherit the locks from the supremum of the left page to the original successor of infimum on the right page, to which the left @@ -2752,7 +2793,7 @@ lock_update_merge_right( lock_rec_free_all_from_discard_page(left_block); - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); } /*************************************************************//** @@ -2768,14 +2809,14 @@ lock_update_root_raise( const buf_block_t* block, /*!< in: index page to which copied */ const buf_block_t* root) /*!< in: root page */ { - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); /* Move the locks on the supremum of the root to the supremum of block */ lock_rec_move(block, root, PAGE_HEAP_NO_SUPREMUM, PAGE_HEAP_NO_SUPREMUM); - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); } /*************************************************************//** @@ -2789,7 +2830,7 @@ lock_update_copy_and_discard( const buf_block_t* block) /*!< in: index page; NOT the root! */ { - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); /* Move the locks on the supremum of the old page to the supremum of new_page */ @@ -2798,7 +2839,7 @@ lock_update_copy_and_discard( PAGE_HEAP_NO_SUPREMUM, PAGE_HEAP_NO_SUPREMUM); lock_rec_free_all_from_discard_page(block); - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); } /*************************************************************//** @@ -2811,7 +2852,7 @@ lock_update_split_left( { ulint heap_no = lock_get_min_heap_no(right_block); - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); /* Inherit the locks to the supremum of the left page from the successor of the infimum on the right page */ @@ -2819,7 +2860,7 @@ lock_update_split_left( lock_rec_inherit_to_gap(left_block, right_block, PAGE_HEAP_NO_SUPREMUM, heap_no); - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); } /*************************************************************//** @@ -2839,7 +2880,7 @@ lock_update_merge_left( ut_ad(left_block->frame == page_align(orig_pred)); - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); left_next_rec = page_rec_get_next_const(orig_pred); @@ -2871,7 +2912,7 @@ lock_update_merge_left( lock_rec_free_all_from_discard_page(right_block); - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); } /*************************************************************//** @@ -2891,13 +2932,13 @@ lock_rec_reset_and_inherit_gap_locks( ulint heap_no) /*!< in: heap_no of the donating record */ { - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); lock_rec_reset_and_release_wait(heir_block, heir_heap_no); lock_rec_inherit_to_gap(heir_block, block, heir_heap_no, heap_no); - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); } /*************************************************************//** @@ -2917,7 +2958,7 @@ lock_update_discard( ulint heap_no; const page_id_t page_id(block->page.id()); - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); if (lock_sys.get_first(page_id)) { ut_ad(!lock_sys.get_first_prdt(page_id)); @@ -2964,7 +3005,7 @@ lock_update_discard( page_id, &lock_sys.prdt_page_hash); } - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); } /*************************************************************//** @@ -3025,7 +3066,7 @@ lock_update_delete( FALSE)); } - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); /* Let the next record inherit the locks from rec, in gap mode */ @@ -3035,7 +3076,7 @@ lock_update_delete( lock_rec_reset_and_release_wait(block, heap_no); - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); } /*********************************************************************//** @@ -3059,11 +3100,11 @@ lock_rec_store_on_page_infimum( ut_ad(block->frame == page_align(rec)); - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); lock_rec_move(block, block, PAGE_HEAP_NO_INFIMUM, heap_no); - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); } /*********************************************************************//** @@ -3083,11 +3124,11 @@ lock_rec_restore_from_page_infimum( { ulint heap_no = page_rec_get_heap_no(rec); - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); lock_rec_move(block, donator, heap_no, PAGE_HEAP_NO_INFIMUM); - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); } /*========================= TABLE LOCKS ==============================*/ @@ -3121,7 +3162,7 @@ lock_table_create( lock_t* lock; ut_ad(table && trx); - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); check_trx_state(trx); @@ -3219,7 +3260,7 @@ lock_table_pop_autoinc_locks( /*=========================*/ trx_t* trx) /*!< in/out: transaction that owns the AUTOINC locks */ { - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); ut_ad(!ib_vector_is_empty(trx->autoinc_locks)); /* Skip any gaps, gaps are NULL lock entries in the @@ -3247,7 +3288,7 @@ lock_table_remove_autoinc_lock( lock_t* autoinc_lock; lint i = ib_vector_size(trx->autoinc_locks) - 1; - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); ut_ad(lock_get_mode(lock) == LOCK_AUTO_INC); ut_ad(lock_get_type_low(lock) & LOCK_TABLE); ut_ad(!ib_vector_is_empty(trx->autoinc_locks)); @@ -3299,7 +3340,7 @@ lock_table_remove_low( trx_t* trx; dict_table_t* table; - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); trx = lock->trx; table = lock->un_member.tab_lock.table; @@ -3362,7 +3403,7 @@ lock_table_enqueue_waiting( trx_t* trx; lock_t* lock; - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); ut_ad(!srv_read_only_mode); trx = thr_get_trx(thr); @@ -3442,7 +3483,7 @@ lock_table_other_has_incompatible( { lock_t* lock; - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); for (lock = UT_LIST_GET_LAST(table->locks); lock != NULL; @@ -3528,7 +3569,7 @@ lock_table( trx_set_rw_mode(trx); } - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); DBUG_EXECUTE_IF("fatal-semaphore-timeout", { os_thread_sleep(3600000000LL); }); @@ -3559,7 +3600,7 @@ lock_table( err = DB_SUCCESS; } - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); trx->mutex.wr_unlock(); @@ -3582,7 +3623,7 @@ lock_table_ix_resurrect( auto mutex= &trx->mutex; - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); /* We have to check if the new lock is compatible with any locks other transactions have in the table lock queue. */ @@ -3592,7 +3633,7 @@ lock_table_ix_resurrect( mutex->wr_lock(); lock_table_create(table, LOCK_IX, trx); - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); mutex->wr_unlock(); } @@ -3608,7 +3649,7 @@ lock_table_has_to_wait_in_queue( const dict_table_t* table; const lock_t* lock; - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); ut_ad(lock_get_wait(wait_lock)); table = wait_lock->un_member.tab_lock.table; @@ -3638,7 +3679,7 @@ lock_table_dequeue( behind will get their lock requests granted, if they are now qualified to it */ { - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); ut_a(lock_get_type_low(in_lock) == LOCK_TABLE); lock_t* lock = UT_LIST_GET_NEXT(un_member.tab_lock.locks, in_lock); @@ -3744,7 +3785,7 @@ lock_rec_unlock( heap_no = page_rec_get_heap_no(rec); - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); first_lock = lock_rec_get_first(&lock_sys.rec_hash, block, heap_no); @@ -3758,7 +3799,7 @@ lock_rec_unlock( } } - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); { ib::error err; @@ -3796,7 +3837,7 @@ released: } } - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); } #ifdef UNIV_DEBUG @@ -3847,7 +3888,7 @@ void lock_release(trx_t* trx) ulint count = 0; trx_id_t max_trx_id = trx_sys.get_max_trx_id(); - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); for (lock_t* lock = UT_LIST_GET_LAST(trx->lock.trx_locks); lock != NULL; @@ -3880,9 +3921,9 @@ void lock_release(trx_t* trx) /* Release the mutex for a while, so that we do not monopolize it */ - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); count = 0; } @@ -3890,7 +3931,7 @@ void lock_release(trx_t* trx) ++count; } - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); } /* True if a lock mode is S or X */ @@ -3908,7 +3949,7 @@ lock_trx_table_locks_remove( { trx_t* trx = lock_to_remove->trx; - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); /* It is safe to read this because we are holding the lock mutex */ const bool have_mutex = trx->lock.cancel; @@ -3948,7 +3989,7 @@ static void lock_table_print(FILE* file, const lock_t* lock) { - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); ut_a(lock_get_type_low(lock) == LOCK_TABLE); fputs("TABLE LOCK table ", file); @@ -3986,7 +4027,7 @@ lock_table_print(FILE* file, const lock_t* lock) @param[in,out] mtr mini-transaction for accessing the record */ static void lock_rec_print(FILE* file, const lock_t* lock, mtr_t& mtr) { - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); ut_a(lock_get_type_low(lock) == LOCK_REC); const page_id_t page_id(lock->un_member.rec_lock.page_id); @@ -4083,7 +4124,7 @@ static ulint lock_get_n_rec_locks() ulint n_locks = 0; ulint i; - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); for (i = 0; i < lock_sys.rec_hash.n_cells; i++) { const lock_t* lock; @@ -4116,8 +4157,8 @@ lock_print_info_summary( otherwise return immediately if fail to obtain the mutex. */ if (!nowait) { - mysql_mutex_lock(&lock_sys.mutex); - } else if (mysql_mutex_trylock(&lock_sys.mutex)) { + lock_sys.mutex_lock(); + } else if (lock_sys.mutex_trylock()) { fputs("FAIL TO OBTAIN LOCK MUTEX," " SKIP LOCK INFO PRINTING\n", file); return(FALSE); @@ -4257,12 +4298,12 @@ lock_print_info_all_transactions( /*=============================*/ FILE* file) /*!< in/out: file where to print */ { - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); fprintf(file, "LIST OF TRANSACTIONS FOR EACH SESSION:\n"); trx_sys.trx_list.for_each(lock_print_info(file, time(nullptr))); - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); ut_ad(lock_validate()); } @@ -4315,7 +4356,7 @@ lock_table_queue_validate( { const lock_t* lock; - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); for (lock = UT_LIST_GET_FIRST(table->locks); lock != NULL; @@ -4373,10 +4414,10 @@ lock_rec_queue_validate( heap_no = page_rec_get_heap_no(rec); if (!locked_lock_trx_sys) { - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); } - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); if (!page_rec_is_user_rec(rec)) { @@ -4398,14 +4439,14 @@ lock_rec_queue_validate( func_exit: if (!locked_lock_trx_sys) { - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); } return true; } ut_ad(page_rec_is_leaf(rec)); - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); const trx_id_t impl_trx_id = index && index->is_primary() ? lock_clust_rec_some_has_impl(rec, index, offsets) @@ -4536,7 +4577,7 @@ static bool lock_rec_validate_page(const buf_block_t *block, bool latched) rec_offs* offsets = offsets_; rec_offs_init(offsets_); - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); loop: lock = lock_sys.get_first(block->page.id()); @@ -4593,7 +4634,7 @@ loop: goto loop; function_exit: - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); if (heap != NULL) { mem_heap_free(heap); @@ -4613,7 +4654,7 @@ lock_rec_validate( page_id_t* limit) /*!< in/out: upper limit of (space, page_no) */ { - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); for (const lock_t* lock = static_cast<const lock_t*>( HASH_GET_FIRST(&lock_sys.rec_hash, start)); @@ -4680,8 +4721,8 @@ static void lock_rec_block_validate(const page_id_t page_id) static my_bool lock_validate_table_locks(rw_trx_hash_element_t *element, void*) { - mysql_mutex_assert_owner(&lock_sys.mutex); - mutex_enter(&element->mutex); + lock_sys.mutex_assert_locked(); + mysql_mutex_lock(&element->mutex); if (element->trx) { check_trx_state(element->trx); @@ -4693,7 +4734,7 @@ static my_bool lock_validate_table_locks(rw_trx_hash_element_t *element, void*) lock_table_queue_validate(lock->un_member.tab_lock.table); } } - mutex_exit(&element->mutex); + mysql_mutex_unlock(&element->mutex); return 0; } @@ -4708,7 +4749,7 @@ lock_validate() { std::set<page_id_t> pages; - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); /* Validate table locks */ trx_sys.rw_trx_hash.iterate(lock_validate_table_locks); @@ -4729,7 +4770,7 @@ lock_validate() } } - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); for (page_id_t page_id : pages) { lock_rec_block_validate(page_id); @@ -4785,7 +4826,7 @@ lock_rec_insert_check_and_lock( ulint heap_no = page_rec_get_heap_no(next_rec); ut_ad(!rec_is_metadata(next_rec, *index)); - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); /* Because this code is invoked for a running transaction by the thread that is serving the transaction, it is not necessary to hold trx->mutex here. */ @@ -4800,7 +4841,7 @@ lock_rec_insert_check_and_lock( if (lock == NULL) { /* We optimize CPU time usage in the simplest case */ - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); if (inherit_in && !dict_index_is_clust(index)) { /* Update the page max trx id field */ @@ -4853,7 +4894,7 @@ lock_rec_insert_check_and_lock( err = DB_SUCCESS; } - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); switch (err) { case DB_SUCCESS_LOCKED_REC: @@ -4914,7 +4955,7 @@ lock_rec_convert_impl_to_expl_for_trx( ut_ad(!rec_is_metadata(rec, *index)); DEBUG_SYNC_C("before_lock_rec_convert_impl_to_expl_for_trx"); - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); trx->mutex.wr_lock(); ut_ad(!trx_state_eq(trx, TRX_STATE_NOT_STARTED)); @@ -4925,7 +4966,7 @@ lock_rec_convert_impl_to_expl_for_trx( block, heap_no, index, trx, true); } - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); trx->mutex.wr_unlock(); trx->release_reference(); @@ -4946,7 +4987,7 @@ static my_bool lock_rec_other_trx_holds_expl_callback( rw_trx_hash_element_t *element, lock_rec_other_trx_holds_expl_arg *arg) { - mutex_enter(&element->mutex); + mysql_mutex_lock(&element->mutex); if (element->trx) { element->trx->mutex.wr_lock(); @@ -4961,7 +5002,7 @@ static my_bool lock_rec_other_trx_holds_expl_callback( ut_ad(!expl_lock || expl_lock->trx == arg->impl_trx); element->trx->mutex.wr_unlock(); } - mutex_exit(&element->mutex); + mysql_mutex_unlock(&element->mutex); return 0; } @@ -4987,21 +5028,21 @@ static void lock_rec_other_trx_holds_expl(trx_t *caller_trx, trx_t *trx, if (trx) { ut_ad(!page_rec_is_metadata(rec)); - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); ut_ad(trx->is_referenced()); const trx_state_t state{trx->state}; ut_ad(state != TRX_STATE_NOT_STARTED); if (state == TRX_STATE_COMMITTED_IN_MEMORY) { - /* The transaction was committed before our mysql_mutex_lock(&lock_sys.mutex). */ - mysql_mutex_unlock(&lock_sys.mutex); + /* The transaction was committed before our lock_sys.mutex_lock(). */ + lock_sys.mutex_unlock(); return; } lock_rec_other_trx_holds_expl_arg arg= { page_rec_get_heap_no(rec), block, trx }; trx_sys.rw_trx_hash.iterate(caller_trx, lock_rec_other_trx_holds_expl_callback, &arg); - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); } } #endif /* UNIV_DEBUG */ @@ -5035,7 +5076,7 @@ lock_rec_convert_impl_to_expl( { trx_t* trx; - mysql_mutex_assert_not_owner(&lock_sys.mutex); + lock_sys.mutex_assert_unlocked(); ut_ad(page_rec_is_user_rec(rec)); ut_ad(rec_offs_validate(rec, index, offsets)); ut_ad(!page_rec_is_comp(rec) == !rec_offs_comp(offsets)); @@ -5419,7 +5460,7 @@ lock_release_autoinc_last_lock( ulint last; lock_t* lock; - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); ut_a(!ib_vector_is_empty(autoinc_locks)); /* The lock to be release must be the last lock acquired. */ @@ -5461,7 +5502,7 @@ lock_release_autoinc_locks( /*=======================*/ trx_t* trx) /*!< in/out: transaction */ { - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); /* If this is invoked for a running transaction by the thread that is serving the transaction, then it is not necessary to hold trx->mutex here. */ @@ -5591,7 +5632,7 @@ lock_cancel_waiting_and_release( { que_thr_t* thr; - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); lock->trx->lock.cancel = true; @@ -5635,7 +5676,7 @@ lock_unlock_table_autoinc( /*======================*/ trx_t* trx) /*!< in/out: transaction */ { - mysql_mutex_assert_not_owner(&lock_sys.mutex); + lock_sys.mutex_assert_unlocked(); ut_ad(!trx->lock.wait_lock); /* This can be invoked on NOT_STARTED, ACTIVE, PREPARED, @@ -5649,17 +5690,17 @@ lock_unlock_table_autoinc( necessary to hold trx->mutex here. */ if (lock_trx_holds_autoinc_locks(trx)) { - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); lock_release_autoinc_locks(trx); - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); } } static inline dberr_t lock_trx_handle_wait_low(trx_t* trx) { - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); if (trx->lock.was_chosen_as_deadlock_victim) { return DB_DEADLOCK; @@ -5689,10 +5730,10 @@ lock_trx_handle_wait( return lock_trx_handle_wait_low(trx); } #endif /* WITH_WSREP */ - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); trx->mutex.wr_lock(); dberr_t err = lock_trx_handle_wait_low(trx); - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); trx->mutex.wr_unlock(); return err; } @@ -5707,11 +5748,11 @@ lock_table_get_n_locks( { ulint n_table_locks; - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); n_table_locks = UT_LIST_GET_LEN(table->locks); - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); return(n_table_locks); } @@ -5727,8 +5768,8 @@ lock_table_get_n_locks( static my_bool lock_table_locks_lookup(rw_trx_hash_element_t *element, const dict_table_t *table) { - mysql_mutex_assert_owner(&lock_sys.mutex); - mutex_enter(&element->mutex); + lock_sys.mutex_assert_locked(); + mysql_mutex_lock(&element->mutex); if (element->trx) { element->trx->mutex.wr_lock(); @@ -5752,7 +5793,7 @@ static my_bool lock_table_locks_lookup(rw_trx_hash_element_t *element, } element->trx->mutex.wr_unlock(); } - mutex_exit(&element->mutex); + mysql_mutex_unlock(&element->mutex); return 0; } #endif /* UNIV_DEBUG */ @@ -5770,7 +5811,7 @@ lock_table_has_locks( ibool has_locks; ut_ad(table != NULL); - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); has_locks = UT_LIST_GET_LEN(table->locks) > 0 || table->n_rec_locks > 0; @@ -5780,7 +5821,7 @@ lock_table_has_locks( } #endif /* UNIV_DEBUG */ - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); return(has_locks); } @@ -5819,7 +5860,7 @@ lock_trx_has_sys_table_locks( const lock_t* strongest_lock = 0; lock_mode strongest = LOCK_NONE; - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); const lock_list::const_iterator end = trx->lock.table_locks.end(); lock_list::const_iterator it = trx->lock.table_locks.begin(); @@ -5840,7 +5881,7 @@ lock_trx_has_sys_table_locks( } if (strongest == LOCK_NONE) { - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); return(NULL); } @@ -5865,7 +5906,7 @@ lock_trx_has_sys_table_locks( } } - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); return(strongest_lock); } @@ -5885,12 +5926,12 @@ lock_trx_has_expl_x_lock( { ut_ad(heap_no > PAGE_HEAP_NO_SUPREMUM); - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); ut_ad(lock_table_has(trx, table, LOCK_IX)); ut_ad(lock_table_has(trx, table, LOCK_X) || lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, block, heap_no, trx)); - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); return(true); } #endif /* UNIV_DEBUG */ @@ -5901,7 +5942,7 @@ is enabled. */ void DeadlockChecker::start_print() { - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); rewind(lock_latest_err_file); ut_print_timestamp(lock_latest_err_file); @@ -5930,7 +5971,7 @@ DeadlockChecker::print(const char* msg) void DeadlockChecker::print(const trx_t* trx, ulint max_query_len) { - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); ulint n_rec_locks = lock_number_of_rows_locked(&trx->lock); ulint n_trx_locks = UT_LIST_GET_LEN(trx->lock.trx_locks); @@ -5950,7 +5991,7 @@ DeadlockChecker::print(const trx_t* trx, ulint max_query_len) void DeadlockChecker::print(const lock_t* lock) { - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); if (lock_get_type_low(lock) == LOCK_REC) { mtr_t mtr; @@ -5979,7 +6020,7 @@ Note: "next" here means PREV for table locks. const lock_t* DeadlockChecker::get_next_lock(const lock_t* lock, ulint heap_no) const { - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); do { if (lock_get_type_low(lock) == LOCK_REC) { @@ -6019,7 +6060,7 @@ due to the way the record lock has is implemented. const lock_t* DeadlockChecker::get_first_lock(ulint* heap_no) const { - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); const lock_t* lock = m_wait_lock; @@ -6068,7 +6109,7 @@ transaction info. void DeadlockChecker::notify(const lock_t* lock) const { - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); start_print(); @@ -6105,7 +6146,7 @@ DeadlockChecker::notify(const lock_t* lock) const const trx_t* DeadlockChecker::select_victim() const { - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); ut_ad(m_start->lock.wait_lock != 0); ut_ad(m_wait_lock->trx != m_start); @@ -6135,7 +6176,7 @@ have been granted its lock by the deadlock checks. const trx_t* DeadlockChecker::search() { - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); ut_ad(m_start != NULL); ut_ad(m_wait_lock != NULL); @@ -6245,7 +6286,7 @@ DeadlockChecker::search() void DeadlockChecker::rollback_print(const trx_t* trx, const lock_t* lock) { - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); /* If the lock search exceeds the max step or the max depth, the current trx will be @@ -6268,7 +6309,7 @@ DeadlockChecker::rollback_print(const trx_t* trx, const lock_t* lock) void DeadlockChecker::trx_rollback() { - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); trx_t* trx = m_wait_lock->trx; @@ -6302,7 +6343,7 @@ or there is no deadlock (any more) */ const trx_t* DeadlockChecker::check_and_resolve(const lock_t* lock, trx_t* trx) { - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); check_trx_state(trx); ut_ad(!srv_read_only_mode); @@ -6397,7 +6438,7 @@ lock_update_split_and_merge( ut_ad(page_is_leaf(right_block->frame)); ut_ad(page_align(orig_pred) == left_block->frame); - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); left_next_rec = page_rec_get_next_const(orig_pred); ut_ad(!page_rec_is_metadata(left_next_rec)); @@ -6420,5 +6461,5 @@ lock_update_split_and_merge( PAGE_HEAP_NO_SUPREMUM, lock_get_min_heap_no(right_block)); - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); } diff --git a/storage/innobase/lock/lock0prdt.cc b/storage/innobase/lock/lock0prdt.cc index 2be58aef7a4..1ba05aa01b0 100644 --- a/storage/innobase/lock/lock0prdt.cc +++ b/storage/innobase/lock/lock0prdt.cc @@ -237,7 +237,7 @@ lock_prdt_has_lock( { lock_t* lock; - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); ut_ad((precise_mode & LOCK_MODE_MASK) == LOCK_S || (precise_mode & LOCK_MODE_MASK) == LOCK_X); ut_ad(!(precise_mode & LOCK_INSERT_INTENTION)); @@ -295,7 +295,7 @@ lock_prdt_other_has_conflicting( the new lock will be on */ const trx_t* trx) /*!< in: our transaction */ { - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); for (lock_t* lock = lock_rec_get_first( lock_hash_get(mode), block, PRDT_HEAPNO); @@ -392,7 +392,7 @@ lock_prdt_find_on_page( { lock_t* lock; - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); for (lock = lock_sys.get_first(*lock_hash_get(type_mode), block->page.id()); @@ -437,7 +437,7 @@ lock_prdt_add_to_queue( /*!< in: TRUE if caller owns the transaction mutex */ { - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); ut_ad(!dict_index_is_clust(index) && !dict_index_is_online_ddl(index)); ut_ad(type_mode & (LOCK_PREDICATE | LOCK_PRDT_PAGE)); @@ -531,7 +531,7 @@ lock_prdt_insert_check_and_lock( trx_t* trx = thr_get_trx(thr); - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); /* Because this code is invoked for a running transaction by the thread that is serving the transaction, it is not necessary @@ -545,7 +545,7 @@ lock_prdt_insert_check_and_lock( lock = lock_rec_get_first(&lock_sys.prdt_hash, block, PRDT_HEAPNO); if (lock == NULL) { - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); /* Update the page max trx id field */ page_update_max_trx_id(block, buf_block_get_page_zip(block), @@ -591,7 +591,7 @@ lock_prdt_insert_check_and_lock( err = DB_SUCCESS; } - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); switch (err) { case DB_SUCCESS_LOCKED_REC: @@ -622,7 +622,7 @@ lock_prdt_update_parent( lock_prdt_t* right_prdt, /*!< in: MBR on the new page */ const page_id_t page_id) /*!< in: parent page */ { - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); /* Get all locks in parent */ for (lock_t *lock = lock_sys.get_first_prdt(page_id); @@ -660,7 +660,7 @@ lock_prdt_update_parent( } } - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); } /**************************************************************//** @@ -728,7 +728,7 @@ lock_prdt_update_split( lock_prdt_t* new_prdt, /*!< in: MBR on the new page */ const page_id_t page_id) /*!< in: page number */ { - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); lock_prdt_update_split_low(new_block, prdt, new_prdt, page_id, LOCK_PREDICATE); @@ -736,7 +736,7 @@ lock_prdt_update_split( lock_prdt_update_split_low(new_block, NULL, NULL, page_id, LOCK_PRDT_PAGE); - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); } /*********************************************************************//** @@ -801,7 +801,7 @@ lock_prdt_lock( index record, and this would not have been possible if another active transaction had modified this secondary index record. */ - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); const unsigned prdt_mode = type_mode | mode; lock_t* lock = lock_sys.get_first(hash, block->page.id()); @@ -867,7 +867,7 @@ lock_prdt_lock( } } - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); if (status == LOCK_REC_SUCCESS_CREATED && type_mode == LOCK_PREDICATE) { /* Append the predicate in the lock record */ @@ -897,7 +897,7 @@ lock_place_prdt_page_lock( index record, and this would not have been possible if another active transaction had modified this secondary index record. */ - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); const lock_t* lock = lock_sys.get_first_prdt_page(page_id); const ulint mode = LOCK_S | LOCK_PRDT_PAGE; @@ -927,7 +927,7 @@ lock_place_prdt_page_lock( #endif /* PRDT_DIAG */ } - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); return(DB_SUCCESS); } @@ -940,11 +940,11 @@ bool lock_test_prdt_page_lock(const trx_t *trx, const page_id_t page_id) { lock_t* lock; - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); lock = lock_sys.get_first_prdt_page(page_id); - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); return(!lock || trx == lock->trx); } @@ -960,7 +960,7 @@ lock_prdt_rec_move( const buf_block_t* donator) /*!< in: buffer block containing the donating record */ { - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); for (lock_t *lock = lock_rec_get_first(&lock_sys.prdt_hash, donator, PRDT_HEAPNO); @@ -978,7 +978,7 @@ lock_prdt_rec_move( lock_prdt, FALSE); } - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); } /** Removes predicate lock objects set on an index page which is discarded. @@ -992,7 +992,7 @@ lock_prdt_page_free_from_discard( lock_t* lock; lock_t* next_lock; - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); lock = lock_sys.get_first(*lock_hash, block->page.id()); diff --git a/storage/innobase/lock/lock0wait.cc b/storage/innobase/lock/lock0wait.cc index 1949d499ac6..5c5caef9df8 100644 --- a/storage/innobase/lock/lock0wait.cc +++ b/storage/innobase/lock/lock0wait.cc @@ -92,13 +92,13 @@ lock_wait_table_release_slot( trx_t::mutex. To reduce contention on the lock mutex when reserving the slot we avoid acquiring the lock mutex. */ - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); slot->thr->slot = NULL; slot->thr = NULL; slot->in_use = FALSE; - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); /* Scan backwards and adjust the last free slot pointer. */ for (slot = lock_sys.last_slot; @@ -190,15 +190,15 @@ wsrep_is_BF_lock_timeout( ib::info() << "WSREP: BF lock wait long for trx:" << ib::hex(trx->id) << " query: " << wsrep_thd_query(trx->mysql_thd); if (!locked) { - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); } - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); trx_print_latched(stderr, trx, 3000); if (!locked) { - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); } srv_print_innodb_monitor = TRUE; @@ -284,12 +284,12 @@ lock_wait_suspend_thread( current thread which owns the transaction. Only acquire the mutex if the wait_lock is still active. */ if (const lock_t* wait_lock = trx->lock.wait_lock) { - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); wait_lock = trx->lock.wait_lock; if (wait_lock) { lock_type = lock_get_type_low(wait_lock); } - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); } ulint had_dict_lock = trx->dict_operation_lock_mode; @@ -325,11 +325,9 @@ lock_wait_suspend_thread( thd_wait_begin(trx->mysql_thd, THD_WAIT_TABLE_LOCK); } - mysql_mutex_lock(&lock_sys.mutex); - while (trx->lock.wait_lock) { - mysql_cond_wait(&slot->cond, &lock_sys.mutex); - } - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_lock(); + lock_sys.wait_lock(&trx->lock.wait_lock, &slot->cond); + lock_sys.mutex_unlock(); thd_wait_end(trx->mysql_thd); @@ -403,7 +401,7 @@ lock_wait_release_thread_if_suspended( que_thr_t* thr) /*!< in: query thread associated with the user OS thread */ { - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); /* We own both the lock mutex and the trx_t::mutex but not the lock wait mutex. This is OK because other threads will see the state @@ -451,7 +449,7 @@ lock_wait_check_and_cancel( possible that the lock has already been granted: in that case do nothing */ - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); if (trx->lock.wait_lock != NULL) { ut_a(trx->lock.que_state == TRX_QUE_LOCK_WAIT); @@ -467,7 +465,7 @@ lock_wait_check_and_cancel( #endif /* WITH_WSREP */ } - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); } } diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index 92ec2d2e18d..44eaecb7a29 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -50,7 +50,6 @@ Created 12/9/1995 Heikki Tuuri #include "trx0trx.h" #include "trx0roll.h" #include "srv0mon.h" -#include "sync0sync.h" #include "buf0dump.h" #include "log0sync.h" diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index ea7629b8695..c4495d4f1e4 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -54,7 +54,6 @@ Created 9/20/1997 Heikki Tuuri #include "buf0rea.h" #include "srv0srv.h" #include "srv0start.h" -#include "sync0sync.h" #include "fil0pagecompress.h" /** Read-ahead area in applying log records to file pages */ diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index 98e4733fbc5..a42006bf97e 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -42,6 +42,7 @@ Created 10/21/1995 Heikki Tuuri # include <sys/stat.h> #endif +#include "srv0mon.h" #include "srv0srv.h" #include "srv0start.h" #include "fil0fil.h" @@ -4477,7 +4478,7 @@ void fil_node_t::find_metadata(os_file_t file @return whether the page was found valid */ bool fil_node_t::read_page0() { - ut_ad(mutex_own(&fil_system.mutex)); + mysql_mutex_assert_owner(&fil_system.mutex); const unsigned psize = space->physical_size(); #ifndef _WIN32 struct stat statbuf; diff --git a/storage/innobase/page/page0zip.cc b/storage/innobase/page/page0zip.cc index 12c8731ed3d..b25f034d0ae 100644 --- a/storage/innobase/page/page0zip.cc +++ b/storage/innobase/page/page0zip.cc @@ -1358,9 +1358,9 @@ page_zip_compress( #endif /* PAGE_ZIP_COMPRESS_DBG */ page_zip_stat[page_zip->ssize - 1].compressed++; if (cmp_per_index_enabled) { - mutex_enter(&page_zip_stat_per_index_mutex); + mysql_mutex_lock(&page_zip_stat_per_index_mutex); page_zip_stat_per_index[ind_id].compressed++; - mutex_exit(&page_zip_stat_per_index_mutex); + mysql_mutex_unlock(&page_zip_stat_per_index_mutex); } if (UNIV_UNLIKELY(n_dense * PAGE_ZIP_DIR_SLOT_SIZE @@ -1538,10 +1538,10 @@ err_exit: page_zip_stat[page_zip->ssize - 1].compressed_usec += time_diff; if (cmp_per_index_enabled) { - mutex_enter(&page_zip_stat_per_index_mutex); + mysql_mutex_lock(&page_zip_stat_per_index_mutex); page_zip_stat_per_index[ind_id].compressed_usec += time_diff; - mutex_exit(&page_zip_stat_per_index_mutex); + mysql_mutex_unlock(&page_zip_stat_per_index_mutex); } return false; } @@ -1605,10 +1605,10 @@ err_exit: page_zip_stat[page_zip->ssize - 1].compressed_ok++; page_zip_stat[page_zip->ssize - 1].compressed_usec += time_diff; if (cmp_per_index_enabled) { - mutex_enter(&page_zip_stat_per_index_mutex); + mysql_mutex_lock(&page_zip_stat_per_index_mutex); page_zip_stat_per_index[ind_id].compressed_ok++; page_zip_stat_per_index[ind_id].compressed_usec += time_diff; - mutex_exit(&page_zip_stat_per_index_mutex); + mysql_mutex_unlock(&page_zip_stat_per_index_mutex); } if (page_is_leaf(page)) { @@ -3244,10 +3244,10 @@ page_zip_decompress( index_id_t index_id = btr_page_get_index_id(page); if (srv_cmp_per_index_enabled) { - mutex_enter(&page_zip_stat_per_index_mutex); + mysql_mutex_lock(&page_zip_stat_per_index_mutex); page_zip_stat_per_index[index_id].decompressed++; page_zip_stat_per_index[index_id].decompressed_usec += time_diff; - mutex_exit(&page_zip_stat_per_index_mutex); + mysql_mutex_unlock(&page_zip_stat_per_index_mutex); } /* Update the stat counter for LRU policy. */ diff --git a/storage/innobase/pars/pars0pars.cc b/storage/innobase/pars/pars0pars.cc index 2f3791aeb5e..dce987a8280 100644 --- a/storage/innobase/pars/pars0pars.cc +++ b/storage/innobase/pars/pars0pars.cc @@ -1987,7 +1987,7 @@ pars_sql( heap = mem_heap_create(16000); /* Currently, the parser is not reentrant: */ - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); pars_sym_tab_global = sym_tab_create(heap); diff --git a/storage/innobase/pars/pars0sym.cc b/storage/innobase/pars/pars0sym.cc index 5e4c0e0f6e0..b65021a375a 100644 --- a/storage/innobase/pars/pars0sym.cc +++ b/storage/innobase/pars/pars0sym.cc @@ -67,7 +67,7 @@ sym_tab_free_private( sym_node_t* sym; func_node_t* func; - ut_ad(mutex_own(&dict_sys.mutex)); + dict_sys.assert_locked(); for (sym = UT_LIST_GET_FIRST(sym_tab->sym_list); sym != NULL; diff --git a/storage/innobase/que/que0que.cc b/storage/innobase/que/que0que.cc index d5645d78a05..a4de6d3bf9d 100644 --- a/storage/innobase/que/que0que.cc +++ b/storage/innobase/que/que0que.cc @@ -182,7 +182,7 @@ que_thr_end_lock_wait( { que_thr_t* thr; - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); thr = trx->lock.wait_thr; @@ -1085,13 +1085,13 @@ que_eval_sql( ut_a(trx->error_state == DB_SUCCESS); if (reserve_dict_mutex) { - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); } graph = pars_sql(info, sql); if (reserve_dict_mutex) { - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); } graph->trx = trx; @@ -1104,13 +1104,13 @@ que_eval_sql( que_run_threads(thr); if (reserve_dict_mutex) { - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); } que_graph_free(graph); if (reserve_dict_mutex) { - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); } DBUG_RETURN(trx->error_state); diff --git a/storage/innobase/read/read0read.cc b/storage/innobase/read/read0read.cc index 92504546130..be37a9f9e5f 100644 --- a/storage/innobase/read/read0read.cc +++ b/storage/innobase/read/read0read.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2018, 2019, MariaDB Corporation. +Copyright (c) 2018, 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 @@ -226,10 +226,10 @@ void ReadView::open(trx_t *trx) m_open.store(true, std::memory_order_relaxed); else { - mutex_enter(&m_mutex); + mysql_mutex_lock(&m_mutex); snapshot(trx); m_open.store(true, std::memory_order_relaxed); - mutex_exit(&m_mutex); + mysql_mutex_unlock(&m_mutex); } } } diff --git a/storage/innobase/row/row0ftsort.cc b/storage/innobase/row/row0ftsort.cc index fa0cd841499..026c587f015 100644 --- a/storage/innobase/row/row0ftsort.cc +++ b/storage/innobase/row/row0ftsort.cc @@ -31,7 +31,6 @@ Created 10/13/2010 Jimmy Yang #include "btr0cur.h" #include "fts0plugin.h" #include "log0crypt.h" -#include "sync0sync.h" /** Read the next record to buffer N. @param N index into array of merge info structure */ diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index b5886b797f1..04f56ba8613 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -1411,7 +1411,7 @@ row_import::set_root_by_heuristic() UNIV_NOTHROW " the tablespace has " << m_n_indexes << " indexes"; } - dict_mutex_enter_for_mysql(); + dict_sys.mutex_lock(); ulint i = 0; dberr_t err = DB_SUCCESS; @@ -1452,7 +1452,7 @@ row_import::set_root_by_heuristic() UNIV_NOTHROW } } - dict_mutex_exit_for_mysql(); + dict_sys.mutex_unlock(); return(err); } diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index 22e15e41096..9835e6b0afe 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -671,7 +671,7 @@ row_ins_set_detailed( { ut_ad(!srv_read_only_mode); - mutex_enter(&srv_misc_tmpfile_mutex); + mysql_mutex_lock(&srv_misc_tmpfile_mutex); rewind(srv_misc_tmpfile); if (os_file_set_eof(srv_misc_tmpfile)) { @@ -685,7 +685,7 @@ row_ins_set_detailed( trx_set_detailed_error(trx, "temp file operation failed"); } - mutex_exit(&srv_misc_tmpfile_mutex); + mysql_mutex_unlock(&srv_misc_tmpfile_mutex); } /*********************************************************************//** @@ -704,13 +704,13 @@ row_ins_foreign_trx_print( ut_ad(!srv_read_only_mode); - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); n_rec_locks = lock_number_of_rows_locked(&trx->lock); n_trx_locks = UT_LIST_GET_LEN(trx->lock.trx_locks); heap_size = mem_heap_get_size(trx->lock.lock_heap); - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); - mutex_enter(&dict_foreign_err_mutex); + mysql_mutex_lock(&dict_foreign_err_mutex); rewind(dict_foreign_err_file); ut_print_timestamp(dict_foreign_err_file); fputs(" Transaction:\n", dict_foreign_err_file); @@ -718,7 +718,7 @@ row_ins_foreign_trx_print( trx_print_low(dict_foreign_err_file, trx, 600, n_rec_locks, n_trx_locks, heap_size); - ut_ad(mutex_own(&dict_foreign_err_mutex)); + mysql_mutex_assert_owner(&dict_foreign_err_mutex); } /*********************************************************************//** @@ -776,7 +776,7 @@ row_ins_foreign_report_err( } putc('\n', ef); - mutex_exit(&dict_foreign_err_mutex); + mysql_mutex_unlock(&dict_foreign_err_mutex); } /*********************************************************************//** @@ -842,7 +842,7 @@ row_ins_foreign_report_add_err( } putc('\n', ef); - mutex_exit(&dict_foreign_err_mutex); + mysql_mutex_unlock(&dict_foreign_err_mutex); } /*********************************************************************//** @@ -1598,7 +1598,7 @@ row_ins_check_foreign_constraint( err = DB_ROW_IS_REFERENCED; } - mutex_exit(&dict_foreign_err_mutex); + mysql_mutex_unlock(&dict_foreign_err_mutex); goto exit_func; } @@ -3009,9 +3009,9 @@ row_ins_sec_index_entry_low( if (!index->is_committed()) { ut_ad(!thr_get_trx(thr) ->dict_operation_lock_mode); - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); dict_set_corrupted_index_cache_only(index); - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); /* Do not return any error to the caller. The duplicate will be reported by ALTER TABLE or CREATE UNIQUE INDEX. diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc index 62678ac8f00..e4f7be83940 100644 --- a/storage/innobase/row/row0log.cc +++ b/storage/innobase/row/row0log.cc @@ -172,7 +172,7 @@ directly. When also head.bytes == tail.bytes, both counts will be reset to 0 and the file will be truncated. */ struct row_log_t { pfs_os_file_t fd; /*!< file descriptor */ - ib_mutex_t mutex; /*!< mutex protecting error, + mysql_mutex_t mutex; /*!< mutex protecting error, max_trx and tail */ page_no_map* blobs; /*!< map of page numbers of off-page columns that have been freed during table-rebuilding @@ -363,7 +363,7 @@ row_log_online_op( + (trx_id ? DATA_TRX_ID_LEN : 0); log = index->online_log; - mutex_enter(&log->mutex); + mysql_mutex_lock(&log->mutex); if (trx_id > log->max_trx) { log->max_trx = trx_id; @@ -471,7 +471,7 @@ write_failed: MEM_UNDEFINED(log->tail.buf, sizeof log->tail.buf); err_exit: - mutex_exit(&log->mutex); + mysql_mutex_unlock(&log->mutex); } /******************************************************//** @@ -499,13 +499,13 @@ row_log_table_open( ulint size, /*!< in: size of log record */ ulint* avail) /*!< out: available size for log record */ { - mutex_enter(&log->mutex); + mysql_mutex_lock(&log->mutex); MEM_UNDEFINED(log->tail.buf, sizeof log->tail.buf); if (log->error != DB_SUCCESS) { err_exit: - mutex_exit(&log->mutex); + mysql_mutex_unlock(&log->mutex); return(NULL); } @@ -541,7 +541,7 @@ row_log_table_close_func( { row_log_t* log = index->online_log; - ut_ad(mutex_own(&log->mutex)); + mysql_mutex_assert_owner(&log->mutex); if (size >= avail) { const os_offset_t byte_offset @@ -605,7 +605,7 @@ write_failed: log->tail.total += size; MEM_UNDEFINED(log->tail.buf, sizeof log->tail.buf); err_exit: - mutex_exit(&log->mutex); + mysql_mutex_unlock(&log->mutex); onlineddl_rowlog_rows++; /* 10000 means 100.00%, 4525 means 45.25% */ @@ -1272,7 +1272,7 @@ row_log_table_get_pk( return(NULL); } - mutex_enter(&log->mutex); + mysql_mutex_lock(&log->mutex); /* log->error is protected by log->mutex. */ if (log->error == DB_SUCCESS) { @@ -1411,7 +1411,7 @@ err_exit: } func_exit: - mutex_exit(&log->mutex); + mysql_mutex_unlock(&log->mutex); return(tuple); } @@ -3187,7 +3187,7 @@ row_log_allocate( } log->fd = OS_FILE_CLOSED; - mutex_create(LATCH_ID_INDEX_ONLINE_LOG, &log->mutex); + mysql_mutex_init(index_online_log_key, &log->mutex, nullptr); log->blobs = NULL; log->table = table; @@ -3270,7 +3270,7 @@ row_log_free( my_large_free(log->crypt_tail, log->crypt_tail_size); } - mutex_free(&log->mutex); + mysql_mutex_destroy(&log->mutex); ut_free(log); } @@ -3284,9 +3284,11 @@ row_log_get_max_trx( dict_index_t* index) /*!< in: index, must be locked */ { ut_ad(dict_index_get_online_status(index) == ONLINE_INDEX_CREATION); +#ifdef SAFE_MUTEX ut_ad(index->lock.have_x() || (index->lock.have_s() - && mutex_own(&index->online_log->mutex))); + && mysql_mutex_is_owner(&index->online_log->mutex))); +#endif return(index->online_log->max_trx); } diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index d1c8fddb26e..3c9331d9909 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -51,6 +51,7 @@ Completed by Sunny Bains and Marko Makela #endif /* BTR_CUR_ADAPT */ #include "ut0stage.h" #include "fil0crypt.h" +#include "srv0mon.h" /* Ignore posix_fadvise() on those platforms where it does not exist */ #if defined _WIN32 @@ -3602,7 +3603,6 @@ row_merge_insert_index_tuples( } ut_ad(dtuple_validate(dtuple)); - ut_ad(!sync_check_iterate(sync_check())); error = btr_bulk->insert(dtuple); if (error != DB_SUCCESS) { diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index fb17db9ff82..5de60e2c862 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -61,8 +61,7 @@ Created 9/17/2000 Heikki Tuuri #include "trx0rec.h" #include "trx0roll.h" #include "trx0undo.h" -#include "srv0start.h" -#include "row0ext.h" +#include "srv0mon.h" #include "srv0start.h" #include <algorithm> @@ -94,7 +93,7 @@ more. Protected by row_drop_list_mutex. */ static UT_LIST_BASE_NODE_T(row_mysql_drop_t) row_mysql_drop_list; /** Mutex protecting the background table drop list. */ -static ib_mutex_t row_drop_list_mutex; +static mysql_mutex_t row_drop_list_mutex; /** Flag: has row_mysql_drop_list been initialized? */ static bool row_mysql_drop_list_inited; @@ -125,9 +124,9 @@ row_wait_for_background_drop_list_empty() { bool empty = false; while (!empty) { - mutex_enter(&row_drop_list_mutex); + mysql_mutex_lock(&row_drop_list_mutex); empty = (UT_LIST_GET_LEN(row_mysql_drop_list) == 0); - mutex_exit(&row_drop_list_mutex); + mysql_mutex_unlock(&row_drop_list_mutex); os_thread_sleep(100000); } } @@ -2259,12 +2258,14 @@ 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 */ { ut_ad(trx->dict_operation_lock_mode == 0); - dict_sys.lock(file, line); + dict_sys.lock(SRW_LOCK_ARGS(file, line)); trx->dict_operation_lock_mode = RW_X_LATCH; } @@ -2560,7 +2561,7 @@ row_drop_tables_for_mysql_in_background(void) ulint n_tables; ulint n_tables_dropped = 0; loop: - mutex_enter(&row_drop_list_mutex); + mysql_mutex_lock(&row_drop_list_mutex); ut_a(row_mysql_drop_list_inited); next: @@ -2568,7 +2569,7 @@ next: n_tables = UT_LIST_GET_LEN(row_mysql_drop_list); - mutex_exit(&row_drop_list_mutex); + mysql_mutex_unlock(&row_drop_list_mutex); if (drop == NULL) { /* All tables dropped */ @@ -2584,7 +2585,7 @@ next: if (!table) { n_tables_dropped++; - mutex_enter(&row_drop_list_mutex); + mysql_mutex_lock(&row_drop_list_mutex); UT_LIST_REMOVE(row_mysql_drop_list, drop); MONITOR_DEC(MONITOR_BACKGROUND_DROP_TABLE); ut_free(drop); @@ -2599,7 +2600,7 @@ next: skip: dict_table_close(table, FALSE, FALSE); - mutex_enter(&row_drop_list_mutex); + mysql_mutex_lock(&row_drop_list_mutex); UT_LIST_REMOVE(row_mysql_drop_list, drop); if (!skip) { UT_LIST_ADD_LAST(row_mysql_drop_list, drop); @@ -2610,9 +2611,9 @@ skip: } if (!srv_fast_shutdown && !trx_sys.any_active_transactions()) { - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); skip = UT_LIST_GET_LEN(table->locks) != 0; - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); if (skip) { /* We cannot drop tables that are locked by XA PREPARE transactions. */ @@ -2647,13 +2648,13 @@ row_get_background_drop_list_len_low(void) { ulint len; - mutex_enter(&row_drop_list_mutex); + mysql_mutex_lock(&row_drop_list_mutex); ut_a(row_mysql_drop_list_inited); len = UT_LIST_GET_LEN(row_mysql_drop_list); - mutex_exit(&row_drop_list_mutex); + mysql_mutex_unlock(&row_drop_list_mutex); return(len); } @@ -2743,7 +2744,7 @@ row_add_table_to_background_drop_list(table_id_t table_id) row_mysql_drop_t* drop; bool added = true; - mutex_enter(&row_drop_list_mutex); + mysql_mutex_lock(&row_drop_list_mutex); ut_a(row_mysql_drop_list_inited); @@ -2765,7 +2766,7 @@ row_add_table_to_background_drop_list(table_id_t table_id) MONITOR_INC(MONITOR_BACKGROUND_DROP_TABLE); func_exit: - mutex_exit(&row_drop_list_mutex); + mysql_mutex_unlock(&row_drop_list_mutex); return added; } @@ -2881,7 +2882,7 @@ row_discard_tablespace_foreign_key_checks( /* We only allow discarding a referenced table if FOREIGN_KEY_CHECKS is set to 0 */ - mutex_enter(&dict_foreign_err_mutex); + mysql_mutex_lock(&dict_foreign_err_mutex); rewind(ef); @@ -2894,7 +2895,7 @@ row_discard_tablespace_foreign_key_checks( ut_print_name(ef, trx, foreign->foreign_table_name); putc('\n', ef); - mutex_exit(&dict_foreign_err_mutex); + mysql_mutex_unlock(&dict_foreign_err_mutex); return(DB_CANNOT_DROP_CONSTRAINT); } @@ -3416,7 +3417,7 @@ row_drop_table_for_mysql( err = DB_CANNOT_DROP_CONSTRAINT; - mutex_enter(&dict_foreign_err_mutex); + mysql_mutex_lock(&dict_foreign_err_mutex); rewind(ef); ut_print_timestamp(ef); @@ -3427,7 +3428,7 @@ row_drop_table_for_mysql( ut_print_name(ef, trx, foreign->foreign_table_name); putc('\n', ef); - mutex_exit(&dict_foreign_err_mutex); + mysql_mutex_unlock(&dict_foreign_err_mutex); goto funct_exit; } @@ -3938,9 +3939,9 @@ loop: dict_table_close(table, TRUE, FALSE); /* The dict_table_t object must not be accessed before - dict_table_open() or after dict_table_close(). But this is OK - if we are holding, the dict_sys.mutex. */ - ut_ad(mutex_own(&dict_sys.mutex)); + dict_table_open() or after dict_table_close() while + not holding dict_sys.mutex. */ + dict_sys.assert_locked(); /* Disable statistics on the found table. */ if (!dict_stats_stop_bg(table)) { @@ -4737,19 +4738,12 @@ not_ok: goto loop; } -/*********************************************************************//** -Initialize this module */ -void -row_mysql_init(void) -/*================*/ +/** Initialize this module */ +void row_mysql_init() { - mutex_create(LATCH_ID_ROW_DROP_LIST, &row_drop_list_mutex); - - UT_LIST_INIT( - row_mysql_drop_list, - &row_mysql_drop_t::row_mysql_drop_list); - - row_mysql_drop_list_inited = true; + mysql_mutex_init(row_drop_list_mutex_key, &row_drop_list_mutex, nullptr); + UT_LIST_INIT(row_mysql_drop_list, &row_mysql_drop_t::row_mysql_drop_list); + row_mysql_drop_list_inited= true; } void row_mysql_close() @@ -4759,7 +4753,7 @@ void row_mysql_close() if (row_mysql_drop_list_inited) { row_mysql_drop_list_inited= false; - mutex_free(&row_drop_list_mutex); + mysql_mutex_destroy(&row_drop_list_mutex); while (row_mysql_drop_t *drop= UT_LIST_GET_FIRST(row_mysql_drop_list)) { diff --git a/storage/innobase/row/row0quiesce.cc b/storage/innobase/row/row0quiesce.cc index 2bc996091b0..54e5ca3c134 100644 --- a/storage/innobase/row/row0quiesce.cc +++ b/storage/innobase/row/row0quiesce.cc @@ -486,7 +486,7 @@ row_quiesce_table_has_fts_index( { bool exists = false; - dict_mutex_enter_for_mysql(); + dict_sys.mutex_lock(); for (const dict_index_t* index = UT_LIST_GET_FIRST(table->indexes); index != 0; @@ -498,7 +498,7 @@ row_quiesce_table_has_fts_index( } } - dict_mutex_exit_for_mysql(); + dict_sys.mutex_unlock(); return(exists); } diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc index 89085a17bca..419a2e628aa 100644 --- a/storage/innobase/row/row0sel.cc +++ b/storage/innobase/row/row0sel.cc @@ -1098,13 +1098,13 @@ re_scan: thr->lock_state = QUE_THR_LOCK_NOLOCK; mtr->start(); - mutex_enter(&match->rtr_match_mutex); + mysql_mutex_lock(&match->rtr_match_mutex); if (!match->valid && match->matched_recs->empty()) { - mutex_exit(&match->rtr_match_mutex); + mysql_mutex_unlock(&match->rtr_match_mutex); err = DB_RECORD_NOT_FOUND; goto func_end; } - mutex_exit(&match->rtr_match_mutex); + mysql_mutex_unlock(&match->rtr_match_mutex); /* MDEV-14059 FIXME: why re-latch the block? pcur is already positioned on it! */ @@ -2164,7 +2164,6 @@ stop_for_a_while: btr_pcur_store_position(&(plan->pcur), &mtr); mtr.commit(); - ut_ad(!sync_check_iterate(sync_check())); err = DB_SUCCESS; goto func_exit; @@ -2181,7 +2180,6 @@ commit_mtr_for_a_while: mtr.commit(); mtr_has_extra_clust_latch = FALSE; - ut_ad(!sync_check_iterate(dict_sync_check())); goto table_loop; @@ -2196,8 +2194,6 @@ lock_wait_or_error: mtr.commit(); func_exit: - ut_ad(!sync_check_iterate(dict_sync_check())); - if (heap != NULL) { mem_heap_free(heap); } @@ -3292,16 +3288,16 @@ Row_sel_get_clust_rec_for_mysql::operator()( || rec != btr_pcur_get_rec(prebuilt->pcur))) { #ifdef UNIV_DEBUG rtr_info_t* rtr_info = btr_cur->rtr_info; - mutex_enter(&rtr_info->matches->rtr_match_mutex); + mysql_mutex_lock(&rtr_info->matches->rtr_match_mutex); /* The page could be deallocated (by rollback etc.) */ if (!rtr_info->matches->valid) { - mutex_exit(&rtr_info->matches->rtr_match_mutex); + mysql_mutex_unlock(&rtr_info->matches->rtr_match_mutex); clust_rec = NULL; err = DB_SUCCESS; goto func_exit; } - mutex_exit(&rtr_info->matches->rtr_match_mutex); + mysql_mutex_unlock(&rtr_info->matches->rtr_match_mutex); if (rec_get_deleted_flag(rec, dict_table_is_comp(sec_index->table)) @@ -4263,8 +4259,6 @@ row_search_mvcc( DBUG_RETURN(DB_END_OF_INDEX); } - ut_ad(!sync_check_iterate(sync_check())); - if (!prebuilt->table->space) { DBUG_RETURN(DB_TABLESPACE_DELETED); } else if (!prebuilt->table->is_readable()) { @@ -4496,7 +4490,6 @@ aborted: /* NOTE that we do NOT store the cursor position */ trx->op_info = ""; - ut_ad(!sync_check_iterate(sync_check())); ut_ad(!did_semi_consistent_read); if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); @@ -5786,8 +5779,6 @@ func_exit: } } - ut_ad(!sync_check_iterate(sync_check())); - DEBUG_SYNC_C("innodb_row_search_for_mysql_exit"); DBUG_RETURN(err); diff --git a/storage/innobase/row/row0uins.cc b/storage/innobase/row/row0uins.cc index 0ce136c5906..492c2f35e62 100644 --- a/storage/innobase/row/row0uins.cc +++ b/storage/innobase/row/row0uins.cc @@ -367,9 +367,9 @@ static bool row_undo_ins_parse_undo_rec(undo_node_t* node, bool dict_locked) node->table = dict_table_open_on_id(table_id, dict_locked, DICT_TABLE_OP_NORMAL); } else if (!dict_locked) { - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); node->table = dict_sys.get_temporary_table(table_id); - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); } else { node->table = dict_sys.get_temporary_table(table_id); } @@ -563,11 +563,11 @@ row_undo_ins( if (node->table->id == DICT_INDEXES_ID) { ut_ad(!node->table->is_temporary()); if (!dict_locked) { - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); } err = row_undo_ins_remove_clust_rec(node); if (!dict_locked) { - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); } } else { err = row_undo_ins_remove_clust_rec(node); diff --git a/storage/innobase/row/row0umod.cc b/storage/innobase/row/row0umod.cc index f81916db6e8..462563de540 100644 --- a/storage/innobase/row/row0umod.cc +++ b/storage/innobase/row/row0umod.cc @@ -912,9 +912,9 @@ row_undo_mod_sec_flag_corrupted( on the data dictionary during normal rollback, we can only mark the index corrupted in the data dictionary cache. TODO: fix this somehow.*/ - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); dict_set_corrupted_index_cache_only(index); - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); break; default: ut_ad(0); @@ -1230,9 +1230,9 @@ static bool row_undo_mod_parse_undo_rec(undo_node_t* node, bool dict_locked) node->table = dict_table_open_on_id(table_id, dict_locked, DICT_TABLE_OP_NORMAL); } else if (!dict_locked) { - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); node->table = dict_sys.get_temporary_table(table_id); - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); } else { node->table = dict_sys.get_temporary_table(table_id); } diff --git a/storage/innobase/row/row0vers.cc b/storage/innobase/row/row0vers.cc index 893522105fd..b0523fa141d 100644 --- a/storage/innobase/row/row0vers.cc +++ b/storage/innobase/row/row0vers.cc @@ -395,7 +395,7 @@ row_vers_impl_x_locked( const rec_t* clust_rec; dict_index_t* clust_index; - mysql_mutex_assert_not_owner(&lock_sys.mutex); + lock_sys.mutex_assert_unlocked(); mtr_start(&mtr); diff --git a/storage/innobase/srv/srv0mon.cc b/storage/innobase/srv/srv0mon.cc index d9c169ab7b8..55024a810ba 100644 --- a/storage/innobase/srv/srv0mon.cc +++ b/storage/innobase/srv/srv0mon.cc @@ -1267,16 +1267,6 @@ static monitor_info_t innodb_counter_info[] = MONITOR_NONE, MONITOR_DEFAULT_START, MONITOR_ICP_MATCH}, - /* ========== Mutex monitoring on/off ========== */ - {"latch_status", "Latch counters", - "Collect latch counters to display via SHOW ENGING INNODB MUTEX", - MONITOR_MODULE, - MONITOR_DEFAULT_START, MONITOR_MODULE_LATCHES}, - - {"latch", "sync", "Latch monitoring control", - MONITOR_HIDDEN, - MONITOR_DEFAULT_START, MONITOR_LATCHES}, - /* ========== To turn on/off reset all counters ========== */ {"all", "All Counters", "Turn on/off and reset all counters", MONITOR_MODULE, diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index bb9b62dcde1..6a5e400015f 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -62,7 +62,6 @@ Created 10/8/1995 Heikki Tuuri #include "srv0mon.h" #include "srv0srv.h" #include "srv0start.h" -#include "sync0sync.h" #include "trx0i_s.h" #include "trx0purge.h" #include "ut0crc32.h" @@ -396,20 +395,18 @@ const char* srv_io_thread_function[SRV_MAX_N_IO_THREADS]; static time_t srv_last_monitor_time; -static ib_mutex_t srv_innodb_monitor_mutex; +static mysql_mutex_t srv_innodb_monitor_mutex; /** Mutex protecting page_zip_stat_per_index */ -ib_mutex_t page_zip_stat_per_index_mutex; +mysql_mutex_t page_zip_stat_per_index_mutex; -/* Mutex for locking srv_monitor_file. Not created if srv_read_only_mode */ -ib_mutex_t srv_monitor_file_mutex; +/** Mutex for locking srv_monitor_file */ +mysql_mutex_t srv_monitor_file_mutex; /** Temporary file for innodb monitor output */ FILE* srv_monitor_file; -/** Mutex for locking srv_misc_tmpfile. Not 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. */ -ib_mutex_t srv_misc_tmpfile_mutex; +/** Mutex for locking srv_misc_tmpfile */ +mysql_mutex_t srv_misc_tmpfile_mutex; /** Temporary file for miscellanous diagnostic output */ FILE* srv_misc_tmpfile; @@ -524,7 +521,7 @@ in a traditional Unix implementation. */ /** The server system struct */ struct srv_sys_t{ - ib_mutex_t tasks_mutex; /*!< variable protecting the + mysql_mutex_t tasks_mutex; /*!< variable protecting the tasks queue */ UT_LIST_BASE_NODE_T(que_thr_t) tasks; /*!< task queue */ @@ -655,13 +652,6 @@ static void thread_pool_thread_end() } -#ifndef DBUG_OFF -static void dbug_after_task_callback() -{ - ut_ad(!sync_check_iterate(sync_check())); -} -#endif - void srv_thread_pool_init() { DBUG_ASSERT(!srv_thread_pool); @@ -673,9 +663,6 @@ void srv_thread_pool_init() #endif srv_thread_pool->set_thread_callbacks(thread_pool_thread_init, thread_pool_thread_end); -#ifndef DBUG_OFF - tpool::set_after_task_callback(dbug_after_task_callback); -#endif } @@ -691,26 +678,16 @@ static bool need_srv_free; /** Initialize the server. */ static void srv_init() { - mutex_create(LATCH_ID_SRV_INNODB_MONITOR, &srv_innodb_monitor_mutex); - - if (!srv_read_only_mode) { - mutex_create(LATCH_ID_SRV_SYS_TASKS, &srv_sys.tasks_mutex); - - UT_LIST_INIT(srv_sys.tasks, &que_thr_t::queue); - } + mysql_mutex_init(srv_innodb_monitor_mutex_key, + &srv_innodb_monitor_mutex, nullptr); + mysql_mutex_init(srv_threads_mutex_key, &srv_sys.tasks_mutex, nullptr); + UT_LIST_INIT(srv_sys.tasks, &que_thr_t::queue); need_srv_free = true; ut_d(mysql_cond_init(0, &srv_master_thread_disabled_cond, nullptr)); - /* page_zip_stat_per_index_mutex is acquired from: - 1. page_zip_compress() - 2. page_zip_decompress() - 3. i_s_cmp_per_index_fill_low() (where SYNC_DICT is acquired) - 4. innodb_cmp_per_index_update(), no other latches - since we do not acquire any other latches while holding this mutex, - it can have very low level. We pick SYNC_ANY_LATCH for it. */ - mutex_create(LATCH_ID_PAGE_ZIP_STAT_PER_INDEX, - &page_zip_stat_per_index_mutex); + mysql_mutex_init(page_zip_stat_per_index_mutex_key, + &page_zip_stat_per_index_mutex, nullptr); /* Initialize some INFORMATION SCHEMA internal structures */ trx_i_s_cache_init(trx_i_s_cache); @@ -727,12 +704,9 @@ srv_free(void) return; } - mutex_free(&srv_innodb_monitor_mutex); - mutex_free(&page_zip_stat_per_index_mutex); - - if (!srv_read_only_mode) { - mutex_free(&srv_sys.tasks_mutex); - } + mysql_mutex_destroy(&srv_innodb_monitor_mutex); + mysql_mutex_destroy(&page_zip_stat_per_index_mutex); + mysql_mutex_destroy(&srv_sys.tasks_mutex); ut_d(mysql_cond_destroy(&srv_master_thread_disabled_cond)); @@ -747,7 +721,6 @@ srv_boot(void) /*==========*/ { srv_thread_pool_init(); - sync_check_init(); trx_pool_init(); row_mysql_init(); srv_init(); @@ -757,12 +730,12 @@ srv_boot(void) Refreshes the values used to calculate per-second averages. */ static void srv_refresh_innodb_monitor_stats(time_t current_time) { - mutex_enter(&srv_innodb_monitor_mutex); + mysql_mutex_lock(&srv_innodb_monitor_mutex); if (difftime(current_time, srv_last_monitor_time) < 60) { /* We referesh InnoDB Monitor values so that averages are printed from at most 60 last seconds */ - mutex_exit(&srv_innodb_monitor_mutex); + mysql_mutex_unlock(&srv_innodb_monitor_mutex); return; } @@ -789,7 +762,7 @@ static void srv_refresh_innodb_monitor_stats(time_t current_time) srv_n_system_rows_deleted_old = srv_stats.n_system_rows_deleted; srv_n_system_rows_read_old = srv_stats.n_system_rows_read; - mutex_exit(&srv_innodb_monitor_mutex); + mysql_mutex_unlock(&srv_innodb_monitor_mutex); } /******************************************************************//** @@ -811,7 +784,7 @@ srv_printf_innodb_monitor( time_t current_time; ibool ret; - mutex_enter(&srv_innodb_monitor_mutex); + mysql_mutex_lock(&srv_innodb_monitor_mutex); current_time = time(NULL); @@ -845,11 +818,11 @@ srv_printf_innodb_monitor( /* End of intentionally blank section */ /* Conceptually, srv_innodb_monitor_mutex has a very high latching - order level in sync0sync.h, while dict_foreign_err_mutex has a very - low level 135. Therefore we can reserve the latter mutex here without + order level, while dict_foreign_err_mutex has a very low level. + Therefore we can reserve the latter mutex here without a danger of a deadlock of threads. */ - mutex_enter(&dict_foreign_err_mutex); + mysql_mutex_lock(&dict_foreign_err_mutex); if (!srv_read_only_mode && ftell(dict_foreign_err_file) != 0L) { fputs("------------------------\n" @@ -858,7 +831,7 @@ srv_printf_innodb_monitor( ut_copy_file(file, dict_foreign_err_file); } - mutex_exit(&dict_foreign_err_mutex); + mysql_mutex_unlock(&dict_foreign_err_mutex); /* Only if lock_print_info_summary proceeds correctly, before we call the lock_print_info_all_transactions @@ -1024,7 +997,7 @@ srv_printf_innodb_monitor( fputs("----------------------------\n" "END OF INNODB MONITOR OUTPUT\n" "============================\n", file); - mutex_exit(&srv_innodb_monitor_mutex); + mysql_mutex_unlock(&srv_innodb_monitor_mutex); fflush(file); return(ret); @@ -1060,7 +1033,7 @@ srv_export_innodb_status(void) export_vars.innodb_mem_dictionary = dict_sys.rough_size(); - mutex_enter(&srv_innodb_monitor_mutex); + mysql_mutex_lock(&srv_innodb_monitor_mutex); export_vars.innodb_data_pending_reads = ulint(MONITOR_VALUE(MONITOR_OS_PENDING_READS)); @@ -1265,7 +1238,7 @@ srv_export_innodb_status(void) srv_stats.key_rotation_list_length; } - mutex_exit(&srv_innodb_monitor_mutex); + mysql_mutex_unlock(&srv_innodb_monitor_mutex); mysql_mutex_lock(&log_sys.mutex); export_vars.innodb_lsn_current = log_sys.get_lsn(); @@ -1329,7 +1302,7 @@ static void srv_monitor() mutexes in read-only-mode */ if (!srv_read_only_mode && srv_innodb_status) { - mutex_enter(&srv_monitor_file_mutex); + mysql_mutex_lock(&srv_monitor_file_mutex); rewind(srv_monitor_file); if (!srv_printf_innodb_monitor(srv_monitor_file, MUTEX_NOWAIT(monitor_state.mutex_skipped), @@ -1340,7 +1313,7 @@ static void srv_monitor() } os_file_set_eof(srv_monitor_file); - mutex_exit(&srv_monitor_file_mutex); + mysql_mutex_unlock(&srv_monitor_file_mutex); } } @@ -1373,6 +1346,37 @@ void srv_monitor_task(void*) eviction policy. */ buf_LRU_stat_update(); + const ulonglong now = my_hrtime_coarse().val; + const ulong threshold = srv_fatal_semaphore_wait_threshold; + + if (ulonglong start = lock_sys.oldest_wait()) { + ulong waited = static_cast<ulong>((now - start) / 1000000); + if (waited >= threshold) { + ib::fatal() << lock_sys.fatal_msg; + } + + if (waited == threshold / 4 + || waited == threshold / 2 + || waited == threshold / 4 * 3) { + ib::warn() << "Long wait (" << waited + << " seconds) for lock_sys.mutex"; + } + } + + if (ulonglong start = dict_sys.oldest_wait()) { + ulong waited = static_cast<ulong>((now - start) / 1000000); + if (waited >= threshold) { + ib::fatal() << dict_sys.fatal_msg; + } + + if (waited == threshold / 4 + || waited == threshold / 2 + || waited == threshold / 4 * 3) { + ib::warn() << "Long wait (" << waited + << " seconds) for dict_sys.mutex"; + } + } + srv_monitor(); } @@ -1469,7 +1473,6 @@ void purge_sys_t::resume() } ut_ad(!srv_read_only_mode); ut_ad(srv_force_recovery < SRV_FORCE_NO_BACKGROUND); - ut_ad(!sync_check_iterate(sync_check())); purge_coordinator_task.enable(); latch.wr_lock(SRW_LOCK_CALL); int32_t paused= m_paused--; @@ -1847,18 +1850,18 @@ static bool srv_task_execute() ut_ad(!srv_read_only_mode); ut_ad(srv_force_recovery < SRV_FORCE_NO_BACKGROUND); - mutex_enter(&srv_sys.tasks_mutex); + mysql_mutex_lock(&srv_sys.tasks_mutex); if (que_thr_t* thr = UT_LIST_GET_FIRST(srv_sys.tasks)) { ut_a(que_node_get_type(thr->child) == QUE_NODE_PURGE); UT_LIST_REMOVE(srv_sys.tasks, thr); - mutex_exit(&srv_sys.tasks_mutex); + mysql_mutex_unlock(&srv_sys.tasks_mutex); que_run_threads(thr); return true; } ut_ad(UT_LIST_GET_LEN(srv_sys.tasks) == 0); - mutex_exit(&srv_sys.tasks_mutex); + mysql_mutex_unlock(&srv_sys.tasks_mutex); return false; } @@ -2095,11 +2098,11 @@ srv_que_task_enqueue_low( que_thr_t* thr) /*!< in: query thread */ { ut_ad(!srv_read_only_mode); - mutex_enter(&srv_sys.tasks_mutex); + mysql_mutex_lock(&srv_sys.tasks_mutex); UT_LIST_ADD_LAST(srv_sys.tasks, thr); - mutex_exit(&srv_sys.tasks_mutex); + mysql_mutex_unlock(&srv_sys.tasks_mutex); } #ifdef UNIV_DEBUG @@ -2110,11 +2113,11 @@ ulint srv_get_task_queue_length() ut_ad(!srv_read_only_mode); - mutex_enter(&srv_sys.tasks_mutex); + mysql_mutex_lock(&srv_sys.tasks_mutex); n_tasks = UT_LIST_GET_LEN(srv_sys.tasks); - mutex_exit(&srv_sys.tasks_mutex); + mysql_mutex_unlock(&srv_sys.tasks_mutex); return(n_tasks); } diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index b8a1a4e2cfc..16e5b827397 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -560,7 +560,7 @@ err_exit: ut_a(space); fil_node_t *file= space->add(name, fh, 0, false, true); - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); if (create) { @@ -575,7 +575,7 @@ err_exit: fil_system.n_open--; } - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); return space_id; } @@ -1076,8 +1076,6 @@ dberr_t srv_start(bool create_new_db) ib::info() << "!!!!!!!! UNIV_IBUF_DEBUG switched on !!!!!!!!!"; #endif - ib::info() << MUTEX_TYPE; - ib::info() << "Compressed tables use zlib " ZLIB_VERSION #ifdef UNIV_ZIP_DEBUG " with validation" @@ -1120,10 +1118,13 @@ dberr_t srv_start(bool create_new_db) ib::info() << my_crc32c_implementation(); if (!srv_read_only_mode) { + mysql_mutex_init(srv_monitor_file_mutex_key, + &srv_monitor_file_mutex, nullptr); + mysql_mutex_init(srv_misc_tmpfile_mutex_key, + &srv_misc_tmpfile_mutex, nullptr); + } - mutex_create(LATCH_ID_SRV_MONITOR_FILE, - &srv_monitor_file_mutex); - + if (!srv_read_only_mode) { if (srv_innodb_status) { srv_monitor_file_name = static_cast<char*>( @@ -1159,9 +1160,6 @@ dberr_t srv_start(bool create_new_db) } } - mutex_create(LATCH_ID_SRV_MISC_TMPFILE, - &srv_misc_tmpfile_mutex); - srv_misc_tmpfile = os_file_create_tmpfile(); if (!srv_misc_tmpfile && err == DB_SUCCESS) { @@ -1683,8 +1681,7 @@ file_checked: /* Note: When creating the extra rollback segments during an upgrade we violate the latching order, even if the change buffer is empty. - We make an exception in sync0sync.cc and check srv_is_being_started - for that violation. It cannot create a deadlock because we are still + It cannot create a deadlock because we are still running in single threaded mode essentially. Only the IO threads should be running at this stage. */ @@ -1906,9 +1903,7 @@ skip_monitors: needed already here as log_preflush_pool_modified_pages will flush dirty pages and that might need e.g. fil_crypt_threads_cond. */ - fil_system_enter(); fil_crypt_threads_init(); - fil_system_exit(); /* Initialize online defragmentation. */ btr_defragment_init(); @@ -2054,8 +2049,8 @@ void innodb_shutdown() trx_pool_close(); if (!srv_read_only_mode) { - mutex_free(&srv_monitor_file_mutex); - mutex_free(&srv_misc_tmpfile_mutex); + mysql_mutex_destroy(&srv_monitor_file_mutex); + mysql_mutex_destroy(&srv_misc_tmpfile_mutex); } dict_sys.close(); @@ -2068,7 +2063,6 @@ void innodb_shutdown() ut_ad(buf_pool.is_initialised() || !srv_was_started); buf_pool.close(); - sync_check_close(); if (srv_was_started && srv_print_verbose_log) { ib::info() << "Shutdown completed; log sequence number " diff --git a/storage/innobase/sync/srw_lock.cc b/storage/innobase/sync/srw_lock.cc index e1d2abc6d2b..17260ebb318 100644 --- a/storage/innobase/sync/srw_lock.cc +++ b/storage/innobase/sync/srw_lock.cc @@ -18,6 +18,7 @@ this program; if not, write to the Free Software Foundation, Inc., #include "srw_lock.h" #include "srv0srv.h" +#include "my_cpu.h" #ifdef SRW_LOCK_DUMMY void ssux_lock_low::init() diff --git a/storage/innobase/sync/sync0debug.cc b/storage/innobase/sync/sync0debug.cc deleted file mode 100644 index cdef44a6652..00000000000 --- a/storage/innobase/sync/sync0debug.cc +++ /dev/null @@ -1,1040 +0,0 @@ -/***************************************************************************** - -Copyright (c) 2014, 2016, 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 sync/sync0debug.cc -Debug checks for latches. - -Created 2012-08-21 Sunny Bains -*******************************************************/ - -#include "sync0sync.h" -#include "sync0debug.h" -#include "srv0start.h" -#include "lock0lock.h" - -#include <vector> -#include <string> -#include <algorithm> -#include <map> - -#ifdef UNIV_DEBUG - -my_bool srv_sync_debug; - -/** The latch held by a thread */ -struct Latched { - - /** Constructor */ - Latched() : m_latch(), m_level(SYNC_UNKNOWN) { } - - /** Constructor - @param[in] latch Latch instance - @param[in] level Level of latch held */ - Latched(const latch_t* latch, - latch_level_t level) - : - m_latch(latch), - m_level(level) - { - /* No op */ - } - - /** @return the latch level */ - latch_level_t get_level() const - { - return(m_level); - } - - /** Check if the rhs latch and level match - @param[in] rhs instance to compare with - @return true on match */ - bool operator==(const Latched& rhs) const - { - return(m_latch == rhs.m_latch && m_level == rhs.m_level); - } - - /** The latch instance */ - const latch_t* m_latch; - - /** The latch level. For buffer blocks we can pass a separate latch - level to check against, see buf_block_dbg_add_level() */ - latch_level_t m_level; -}; - -/** Thread specific latches. This is ordered on level in descending order. */ -typedef std::vector<Latched, ut_allocator<Latched> > Latches; - -/** The deadlock detector. */ -struct LatchDebug { - - /** Debug mutex for control structures, should not be tracked - by this module. */ - typedef OSMutex Mutex; - - /** Comparator for the ThreadMap. */ - struct os_thread_id_less - : public std::binary_function< - os_thread_id_t, - os_thread_id_t, - bool> - { - /** @return true if lhs < rhs */ - bool operator()( - const os_thread_id_t& lhs, - const os_thread_id_t& rhs) const - UNIV_NOTHROW - { - return(ulint(lhs) < ulint(rhs)); - } - }; - - /** For tracking a thread's latches. */ - typedef std::map< - os_thread_id_t, - Latches*, - os_thread_id_less, - ut_allocator<std::pair<const os_thread_id_t, Latches*> > > - ThreadMap; - - /** Constructor */ - LatchDebug() - UNIV_NOTHROW; - - /** Destructor */ - ~LatchDebug() - UNIV_NOTHROW - { - m_mutex.destroy(); - } - - /** Create a new instance if one doesn't exist else return - the existing one. - @param[in] add add an empty entry if one is not - found (default no) - @return pointer to a thread's acquired latches. */ - Latches* thread_latches(bool add = false) - UNIV_NOTHROW; - - /** Check that all the latches already owned by a thread have a lower - level than limit. - @param[in] latches the thread's existing (acquired) latches - @param[in] limit to check against - @return latched if there is one with a level <= limit . */ - const Latched* less( - const Latches* latches, - latch_level_t limit) const - UNIV_NOTHROW; - - /** Checks if the level value exists in the thread's acquired latches. - @param[in] latches the thread's existing (acquired) latches - @param[in] level to lookup - @return latch if found or 0 */ - const latch_t* find( - const Latches* Latches, - latch_level_t level) const - UNIV_NOTHROW; - - /** - Checks if the level value exists in the thread's acquired latches. - @param[in] level to lookup - @return latch if found or 0 */ - const latch_t* find(latch_level_t level) - UNIV_NOTHROW; - - /** Report error and abort. - @param[in] latches thread's existing latches - @param[in] latched The existing latch causing the - invariant to fail - @param[in] level The new level request that breaks - the order */ - void crash( - const Latches* latches, - const Latched* latched, - latch_level_t level) const - UNIV_NOTHROW; - - /** Do a basic ordering check. - @param[in] latches thread's existing latches - @param[in] requested_level Level requested by latch - @param[in] level declared ulint so that we can - do level - 1. The level of the - latch that the thread is trying - to acquire - @return true if passes, else crash with error message. */ - inline bool basic_check( - const Latches* latches, - latch_level_t requested_level, - lint level) const - UNIV_NOTHROW; - - /** Adds a latch and its level in the thread level array. Allocates - the memory for the array if called for the first time for this - OS thread. Makes the checks against other latch levels stored - in the array for this thread. - - @param[in] latch latch that the thread wants to acqire. - @param[in] level latch level to check against */ - void lock_validate( - const latch_t* latch, - latch_level_t level) - UNIV_NOTHROW - { - /* Ignore diagnostic latches, starting with '.' */ - - if (*latch->get_name() != '.') { - Latches* latches = check_order(latch, level); - - ut_a(latches->empty() - || level == SYNC_NO_ORDER_CHECK - || latches->back().get_level() - == SYNC_NO_ORDER_CHECK - || latches->back().get_level() >= level); - } - } - - /** Adds a latch and its level in the thread level array. Allocates - the memory for the array if called for the first time for this - OS thread. Makes the checks against other latch levels stored - in the array for this thread. - - @param[in] latch latch that the thread wants to acqire. - @param[in] level latch level to check against */ - void lock_granted( - const latch_t* latch, - latch_level_t level) - UNIV_NOTHROW - { - /* Ignore diagnostic latches, starting with '.' */ - - if (*latch->get_name() != '.') { - thread_latches(true)->push_back(Latched(latch, level)); - } - } - - /** Iterate over a thread's latches. - @param[in] functor The callback - @return true if the functor returns true. */ - bool for_each(const sync_check_functor_t& functor) - UNIV_NOTHROW - { - if (const Latches* latches = thread_latches()) { - Latches::const_iterator end = latches->end(); - for (Latches::const_iterator it = latches->begin(); - it != end; ++it) { - - if (functor(it->m_level)) { - return(true); - } - } - } - - return(false); - } - - /** Removes a latch from the thread level array if it is found there. - @param[in] latch The latch that was released - @return true if found in the array; it is not an error if the latch is - not found, as we presently are not able to determine the level for - every latch reservation the program does */ - void unlock(const latch_t* latch) UNIV_NOTHROW; - - /** Get the level name - @param[in] level The level ID to lookup - @return level name */ - const std::string& get_level_name(latch_level_t level) const - UNIV_NOTHROW - { - Levels::const_iterator it = m_levels.find(level); - - ut_ad(it != m_levels.end()); - - return(it->second); - } - - /** Shutdown the latch debug checking */ - static void shutdown() - UNIV_NOTHROW; - - /** @return the singleton instance */ - static LatchDebug* instance() - UNIV_NOTHROW - { - return(s_instance); - } - - /** Create the singleton instance */ - static void create_instance() - UNIV_NOTHROW - { - ut_ad(s_instance == NULL); - - s_instance = UT_NEW_NOKEY(LatchDebug()); - } - -private: - /** Disable copying */ - LatchDebug(const LatchDebug&); - LatchDebug& operator=(const LatchDebug&); - - /** Adds a latch and its level in the thread level array. Allocates - the memory for the array if called first time for this OS thread. - Makes the checks against other latch levels stored in the array - for this thread. - - @param[in] latch pointer to a mutex or an rw-lock - @param[in] level level in the latching order - @return the thread's latches */ - Latches* check_order( - const latch_t* latch, - latch_level_t level) - UNIV_NOTHROW; - - /** Print the latches acquired by a thread - @param[in] latches Latches acquired by a thread */ - void print_latches(const Latches* latches) const - UNIV_NOTHROW; - - /** Special handling for the RTR mutexes. We need to add proper - levels for them if possible. - @param[in] latch Latch to check - @return true if it is a an _RTR_ mutex */ - bool is_rtr_mutex(const latch_t* latch) const - UNIV_NOTHROW - { - return(latch->get_id() == LATCH_ID_RTR_ACTIVE_MUTEX - || latch->get_id() == LATCH_ID_RTR_PATH_MUTEX - || latch->get_id() == LATCH_ID_RTR_MATCH_MUTEX); - } - -private: - /** Comparator for the Levels . */ - struct latch_level_less - : public std::binary_function< - latch_level_t, - latch_level_t, - bool> - { - /** @return true if lhs < rhs */ - bool operator()( - const latch_level_t& lhs, - const latch_level_t& rhs) const - UNIV_NOTHROW - { - return(lhs < rhs); - } - }; - - typedef std::map< - latch_level_t, - std::string, - latch_level_less, - ut_allocator<std::pair<const latch_level_t, std::string> > > - Levels; - - /** Mutex protecting the deadlock detector data structures. */ - Mutex m_mutex; - - /** Thread specific data. Protected by m_mutex. */ - ThreadMap m_threads; - - /** Mapping from latche level to its string representation. */ - Levels m_levels; - - /** The singleton instance. Must be created in single threaded mode. */ - static LatchDebug* s_instance; - -public: - /** For checking whether this module has been initialised or not. */ - static bool s_initialized; -}; - -/** The latch order checking infra-structure */ -LatchDebug* LatchDebug::s_instance = NULL; -bool LatchDebug::s_initialized = false; - -#define LEVEL_MAP_INSERT(T) \ -do { \ - std::pair<Levels::iterator, bool> result = \ - m_levels.insert(Levels::value_type(T, #T)); \ - ut_ad(result.second); \ -} while(0) - -/** Setup the mapping from level ID to level name mapping */ -LatchDebug::LatchDebug() -{ - m_mutex.init(); - - LEVEL_MAP_INSERT(SYNC_UNKNOWN); - LEVEL_MAP_INSERT(RW_LOCK_SX); - LEVEL_MAP_INSERT(RW_LOCK_X_WAIT); - LEVEL_MAP_INSERT(RW_LOCK_S); - LEVEL_MAP_INSERT(RW_LOCK_X); - LEVEL_MAP_INSERT(RW_LOCK_NOT_LOCKED); - LEVEL_MAP_INSERT(SYNC_ANY_LATCH); - LEVEL_MAP_INSERT(SYNC_POOL); - LEVEL_MAP_INSERT(SYNC_POOL_MANAGER); - LEVEL_MAP_INSERT(SYNC_PURGE_QUEUE); - LEVEL_MAP_INSERT(SYNC_RW_TRX_HASH_ELEMENT); - LEVEL_MAP_INSERT(SYNC_READ_VIEW); - LEVEL_MAP_INSERT(SYNC_TRX_SYS); - LEVEL_MAP_INSERT(SYNC_INDEX_ONLINE_LOG); - LEVEL_MAP_INSERT(SYNC_IBUF_BITMAP_MUTEX); - LEVEL_MAP_INSERT(SYNC_IBUF_MUTEX); - LEVEL_MAP_INSERT(SYNC_NOREDO_RSEG); - LEVEL_MAP_INSERT(SYNC_REDO_RSEG); - LEVEL_MAP_INSERT(SYNC_IBUF_PESS_INSERT_MUTEX); - LEVEL_MAP_INSERT(SYNC_STATS_AUTO_RECALC); - LEVEL_MAP_INSERT(SYNC_DICT); - LEVEL_MAP_INSERT(SYNC_NO_ORDER_CHECK); - - /* Enum count starts from 0 */ - ut_ad(m_levels.size() == SYNC_LEVEL_MAX + 1); -} - -/** Print the latches acquired by a thread -@param[in] latches Latches acquired by a thread */ -void -LatchDebug::print_latches(const Latches* latches) const - UNIV_NOTHROW -{ - ib::error() << "Latches already owned by this thread: "; - - Latches::const_iterator end = latches->end(); - - for (Latches::const_iterator it = latches->begin(); - it != end; - ++it) { - - ib::error() - << sync_latch_get_name(it->m_latch->get_id()) - << " -> " - << it->m_level << " " - << "(" << get_level_name(it->m_level) << ")"; - } -} - -/** Report error and abort -@param[in] latches thread's existing latches -@param[in] latched The existing latch causing the invariant to fail -@param[in] level The new level request that breaks the order */ -void -LatchDebug::crash( - const Latches* latches, - const Latched* latched, - latch_level_t level) const - UNIV_NOTHROW -{ - const latch_t* latch = latched->m_latch; - const std::string& in_level_name = get_level_name(level); - - const std::string& latch_level_name = - get_level_name(latched->m_level); - - ib::error() - << "Thread " << os_thread_get_curr_id() - << " already owns a latch " - << sync_latch_get_name(latch->m_id) << " at level" - << " " << latched->m_level << " (" << latch_level_name - << " ), which is at a lower/same level than the" - << " requested latch: " - << level << " (" << in_level_name << "). " - << latch->to_string(); - - print_latches(latches); - - ut_error; -} - -/** Check that all the latches already owned by a thread have a lower -level than limit. -@param[in] latches the thread's existing (acquired) latches -@param[in] limit to check against -@return latched info if there is one with a level <= limit . */ -const Latched* -LatchDebug::less( - const Latches* latches, - latch_level_t limit) const - UNIV_NOTHROW -{ - Latches::const_iterator end = latches->end(); - - for (Latches::const_iterator it = latches->begin(); it != end; ++it) { - - if (it->m_level <= limit) { - return(&(*it)); - } - } - - return(NULL); -} - -/** Do a basic ordering check. -@param[in] latches thread's existing latches -@param[in] requested_level Level requested by latch -@param[in] in_level declared ulint so that we can do level - 1. - The level of the latch that the thread is - trying to acquire -@return true if passes, else crash with error message. */ -inline bool -LatchDebug::basic_check( - const Latches* latches, - latch_level_t requested_level, - lint in_level) const - UNIV_NOTHROW -{ - latch_level_t level = latch_level_t(in_level); - - ut_ad(level < SYNC_LEVEL_MAX); - - const Latched* latched = less(latches, level); - - if (latched != NULL) { - crash(latches, latched, requested_level); - return(false); - } - - return(true); -} - -/** Create a new instance if one doesn't exist else return the existing one. -@param[in] add add an empty entry if one is not found - (default no) -@return pointer to a thread's acquired latches. */ -Latches* -LatchDebug::thread_latches(bool add) - UNIV_NOTHROW -{ - m_mutex.enter(); - - os_thread_id_t thread_id = os_thread_get_curr_id(); - ThreadMap::iterator lb = m_threads.lower_bound(thread_id); - - if (lb != m_threads.end() - && !(m_threads.key_comp()(thread_id, lb->first))) { - - Latches* latches = lb->second; - - m_mutex.exit(); - - return(latches); - - } else if (!add) { - - m_mutex.exit(); - - return(NULL); - - } else { - typedef ThreadMap::value_type value_type; - - Latches* latches = UT_NEW_NOKEY(Latches()); - - ut_a(latches != NULL); - - latches->reserve(32); - - m_threads.insert(lb, value_type(thread_id, latches)); - - m_mutex.exit(); - - return(latches); - } -} - -/** Checks if the level value exists in the thread's acquired latches. -@param[in] levels the thread's existing (acquired) latches -@param[in] level to lookup -@return latch if found or 0 */ -const latch_t* -LatchDebug::find( - const Latches* latches, - latch_level_t level) const UNIV_NOTHROW -{ - Latches::const_iterator end = latches->end(); - - for (Latches::const_iterator it = latches->begin(); it != end; ++it) { - - if (it->m_level == level) { - - return(it->m_latch); - } - } - - return(0); -} - -/** Checks if the level value exists in the thread's acquired latches. -@param[in] level The level to lookup -@return latch if found or NULL */ -const latch_t* -LatchDebug::find(latch_level_t level) - UNIV_NOTHROW -{ - return(find(thread_latches(), level)); -} - -/** -Adds a latch and its level in the thread level array. Allocates the memory -for the array if called first time for this OS thread. Makes the checks -against other latch levels stored in the array for this thread. -@param[in] latch pointer to a mutex or an rw-lock -@param[in] level level in the latching order -@return the thread's latches */ -Latches* -LatchDebug::check_order( - const latch_t* latch, - latch_level_t level) - UNIV_NOTHROW -{ - Latches* latches = thread_latches(true); - - /* NOTE that there is a problem with _NODE and _LEAF levels: if the - B-tree height changes, then a leaf can change to an internal node - or the other way around. We do not know at present if this can cause - unnecessary assertion failures below. */ - - switch (level) { - case SYNC_NO_ORDER_CHECK: - break; - - case SYNC_RW_TRX_HASH_ELEMENT: - case SYNC_READ_VIEW: - case SYNC_TRX_SYS: - case SYNC_IBUF_BITMAP_MUTEX: - case SYNC_REDO_RSEG: - case SYNC_NOREDO_RSEG: - case SYNC_PURGE_QUEUE: - case SYNC_IBUF_MUTEX: - case SYNC_INDEX_ONLINE_LOG: - case SYNC_STATS_AUTO_RECALC: - case SYNC_POOL: - case SYNC_POOL_MANAGER: - basic_check(latches, level, level); - break; - - case SYNC_ANY_LATCH: - - /* Temporary workaround for LATCH_ID_RTR_*_MUTEX */ - if (is_rtr_mutex(latch)) { - - const Latched* latched = less(latches, level); - - if (latched == NULL - || (latched != NULL - && is_rtr_mutex(latched->m_latch))) { - - /* No violation */ - break; - - } - - crash(latches, latched, level); - - } else { - basic_check(latches, level, level); - } - - break; - - case SYNC_IBUF_PESS_INSERT_MUTEX: - ut_a(find(latches, SYNC_IBUF_MUTEX) == 0); - break; - - case SYNC_DICT: - basic_check(latches, level, SYNC_DICT); - break; - - case SYNC_UNKNOWN: - case RW_LOCK_X: - case RW_LOCK_X_WAIT: - case RW_LOCK_S: - case RW_LOCK_SX: - case RW_LOCK_NOT_LOCKED: - /* These levels should never be set for a latch. */ - ut_error; - break; - } - - return(latches); -} - -/** Removes a latch from the thread level array if it is found there. -@param[in] latch that was released/unlocked -@param[in] level level of the latch -@return true if found in the array; it is not an error if the latch is -not found, as we presently are not able to determine the level for -every latch reservation the program does */ -void -LatchDebug::unlock(const latch_t* latch) - UNIV_NOTHROW -{ - Latches* latches; - - if (*latch->get_name() == '.') { - - /* Ignore diagnostic latches, starting with '.' */ - - } else if ((latches = thread_latches()) != NULL) { - - Latches::reverse_iterator rend = latches->rend(); - - for (Latches::reverse_iterator it = latches->rbegin(); - it != rend; - ++it) { - - if (it->m_latch != latch) { - - continue; - } - - Latches::iterator i = it.base(); - - latches->erase(--i); - - /* If this thread doesn't own any more - latches remove from the map. - - FIXME: Perhaps use the master thread - to do purge. Or, do it from close connection. - This could be expensive. */ - - if (latches->empty()) { - - m_mutex.enter(); - - os_thread_id_t thread_id; - - thread_id = os_thread_get_curr_id(); - - m_threads.erase(thread_id); - - m_mutex.exit(); - - UT_DELETE(latches); - } - - return; - } - - ib::error() - << "Couldn't find latch " - << sync_latch_get_name(latch->get_id()); - - print_latches(latches); - - /** Must find the latch. */ - ut_error; - } -} - -/** Get the latch id from a latch name. -@param[in] name Latch name -@return latch id if found else LATCH_ID_NONE. */ -latch_id_t -sync_latch_get_id(const char* name) -{ - LatchMetaData::const_iterator end = latch_meta.end(); - - /* Linear scan should be OK, this should be extremely rare. */ - - for (LatchMetaData::const_iterator it = latch_meta.begin(); - it != end; - ++it) { - - if (*it == NULL || (*it)->get_id() == LATCH_ID_NONE) { - - continue; - - } else if (strcmp((*it)->get_name(), name) == 0) { - - return((*it)->get_id()); - } - } - - return(LATCH_ID_NONE); -} - -/** Get the latch name from a sync level -@param[in] level Latch level to lookup -@return NULL if not found. */ -const char* -sync_latch_get_name(latch_level_t level) -{ - LatchMetaData::const_iterator end = latch_meta.end(); - - /* Linear scan should be OK, this should be extremely rare. */ - - for (LatchMetaData::const_iterator it = latch_meta.begin(); - it != end; - ++it) { - - if (*it == NULL || (*it)->get_id() == LATCH_ID_NONE) { - - continue; - - } else if ((*it)->get_level() == level) { - - return((*it)->get_name()); - } - } - - return(0); -} - -/** Check if it is OK to acquire the latch. -@param[in] latch latch type */ -void -sync_check_lock_validate(const latch_t* latch) -{ - if (LatchDebug::instance() != NULL) { - LatchDebug::instance()->lock_validate( - latch, latch->get_level()); - } -} - -/** Note that the lock has been granted -@param[in] latch latch type */ -void -sync_check_lock_granted(const latch_t* latch) -{ - if (LatchDebug::instance() != NULL) { - LatchDebug::instance()->lock_granted(latch, latch->get_level()); - } -} - -/** Removes a latch from the thread level array if it is found there. -@param[in] latch The latch to unlock */ -void -sync_check_unlock(const latch_t* latch) -{ - if (LatchDebug::instance() != NULL) { - LatchDebug::instance()->unlock(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) -{ - if (LatchDebug::instance() != NULL) { - return(LatchDebug::instance()->find(level)); - } - - return(NULL); -} - -/** Iterate over the thread's latches. -@param[in,out] 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) -{ - if (LatchDebug* debug = LatchDebug::instance()) { - return(debug->for_each(functor)); - } - - return(false); -} - -/** Enable sync order checking. - -Note: We don't enforce any synchronisation checks. The caller must ensure -that no races can occur */ -static void sync_check_enable() -{ - if (!srv_sync_debug) { - - return; - } - - /* We should always call this before we create threads. */ - - LatchDebug::create_instance(); -} - -/** Shutdown the latch debug checking - -Note: We don't enforce any synchronisation checks. The caller must ensure -that no races can occur */ -void -LatchDebug::shutdown() - UNIV_NOTHROW -{ - ut_a(s_initialized); - - s_initialized = false; - - UT_DELETE(s_instance); - - LatchDebug::s_instance = NULL; -} -#endif /* UNIV_DEBUG */ - -/* Meta data for all the InnoDB latches. If the latch is not in recorded -here then it will be be considered for deadlock checks. */ -LatchMetaData latch_meta; - -/** Load the latch meta data. */ -static -void -sync_latch_meta_init() - UNIV_NOTHROW -{ - latch_meta.resize(LATCH_ID_MAX + 1); - - /* The latches should be ordered on latch_id_t. So that we can - index directly into the vector to update and fetch meta-data. */ - - LATCH_ADD_MUTEX(DICT_FOREIGN_ERR, SYNC_NO_ORDER_CHECK, - dict_foreign_err_mutex_key); - - LATCH_ADD_MUTEX(DICT_SYS, SYNC_DICT, dict_sys_mutex_key); - - LATCH_ADD_MUTEX(FIL_SYSTEM, SYNC_ANY_LATCH, fil_system_mutex_key); - - LATCH_ADD_MUTEX(IBUF_BITMAP, SYNC_IBUF_BITMAP_MUTEX, - ibuf_bitmap_mutex_key); - - LATCH_ADD_MUTEX(IBUF, SYNC_IBUF_MUTEX, ibuf_mutex_key); - - LATCH_ADD_MUTEX(IBUF_PESSIMISTIC_INSERT, SYNC_IBUF_PESS_INSERT_MUTEX, - ibuf_pessimistic_insert_mutex_key); - - LATCH_ADD_MUTEX(PURGE_SYS_PQ, SYNC_PURGE_QUEUE, - purge_sys_pq_mutex_key); - - LATCH_ADD_MUTEX(RECALC_POOL, SYNC_STATS_AUTO_RECALC, - recalc_pool_mutex_key); - - LATCH_ADD_MUTEX(REDO_RSEG, SYNC_REDO_RSEG, redo_rseg_mutex_key); - - LATCH_ADD_MUTEX(NOREDO_RSEG, SYNC_NOREDO_RSEG, noredo_rseg_mutex_key); - - LATCH_ADD_MUTEX(RTR_ACTIVE_MUTEX, SYNC_ANY_LATCH, - rtr_active_mutex_key); - - LATCH_ADD_MUTEX(RTR_MATCH_MUTEX, SYNC_ANY_LATCH, rtr_match_mutex_key); - - LATCH_ADD_MUTEX(RTR_PATH_MUTEX, SYNC_ANY_LATCH, rtr_path_mutex_key); - - LATCH_ADD_MUTEX(SRV_INNODB_MONITOR, SYNC_NO_ORDER_CHECK, - srv_innodb_monitor_mutex_key); - - LATCH_ADD_MUTEX(SRV_MISC_TMPFILE, SYNC_ANY_LATCH, - srv_misc_tmpfile_mutex_key); - - LATCH_ADD_MUTEX(SRV_MONITOR_FILE, SYNC_NO_ORDER_CHECK, - srv_monitor_file_mutex_key); - - LATCH_ADD_MUTEX(TRX_POOL, SYNC_POOL, trx_pool_mutex_key); - - LATCH_ADD_MUTEX(TRX_POOL_MANAGER, SYNC_POOL_MANAGER, - trx_pool_manager_mutex_key); - - LATCH_ADD_MUTEX(TRX_SYS, SYNC_TRX_SYS, trx_sys_mutex_key); - - LATCH_ADD_MUTEX(SRV_SYS_TASKS, SYNC_ANY_LATCH, srv_threads_mutex_key); - - LATCH_ADD_MUTEX(PAGE_ZIP_STAT_PER_INDEX, SYNC_ANY_LATCH, - page_zip_stat_per_index_mutex_key); - - LATCH_ADD_MUTEX(SYNC_ARRAY_MUTEX, SYNC_NO_ORDER_CHECK, - sync_array_mutex_key); - - LATCH_ADD_MUTEX(ROW_DROP_LIST, SYNC_NO_ORDER_CHECK, - row_drop_list_mutex_key); - - LATCH_ADD_MUTEX(INDEX_ONLINE_LOG, SYNC_INDEX_ONLINE_LOG, - index_online_log_key); - - /* JAN: TODO: Add PFS instrumentation */ - LATCH_ADD_MUTEX(DEFRAGMENT_MUTEX, SYNC_NO_ORDER_CHECK, - PFS_NOT_INSTRUMENTED); - LATCH_ADD_MUTEX(RW_TRX_HASH_ELEMENT, SYNC_RW_TRX_HASH_ELEMENT, - rw_trx_hash_element_mutex_key); - LATCH_ADD_MUTEX(READ_VIEW, SYNC_READ_VIEW, read_view_mutex_key); - - latch_id_t id = LATCH_ID_NONE; - - /* The array should be ordered on latch ID.We need to - index directly into it from the mutex policy to update - the counters and access the meta-data. */ - - for (LatchMetaData::iterator it = latch_meta.begin(); - it != latch_meta.end(); - ++it) { - - const latch_meta_t* meta = *it; - - - /* Skip blank entries */ - if (meta == NULL || meta->get_id() == LATCH_ID_NONE) { - continue; - } - - ut_a(id < meta->get_id()); - - id = meta->get_id(); - } -} - -/** Destroy the latch meta data */ -static -void -sync_latch_meta_destroy() -{ - for (LatchMetaData::iterator it = latch_meta.begin(); - it != latch_meta.end(); - ++it) { - - UT_DELETE(*it); - } - - latch_meta.clear(); -} - -/** Initializes the synchronization data structures. */ -void -sync_check_init() -{ - ut_ad(!LatchDebug::s_initialized); - ut_d(LatchDebug::s_initialized = true); - - sync_latch_meta_init(); - - ut_d(sync_check_enable()); -} - -/** Free the InnoDB synchronization data structures. */ -void -sync_check_close() -{ - ut_d(LatchDebug::shutdown()); - sync_latch_meta_destroy(); -} diff --git a/storage/innobase/sync/sync0sync.cc b/storage/innobase/sync/sync0sync.cc deleted file mode 100644 index 9c4585d1fbe..00000000000 --- a/storage/innobase/sync/sync0sync.cc +++ /dev/null @@ -1,169 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2020, MariaDB Corporation. -Copyright (c) 2008, Google 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 sync/sync0sync.cc -Mutex, the basic synchronization primitive - -Created 9/5/1995 Heikki Tuuri -*******************************************************/ - -#include "sync0sync.h" -#include "ut0mutex.h" - -#ifdef UNIV_PFS_MUTEX -mysql_pfs_key_t buf_pool_mutex_key; -mysql_pfs_key_t dict_foreign_err_mutex_key; -mysql_pfs_key_t dict_sys_mutex_key; -mysql_pfs_key_t fil_system_mutex_key; -mysql_pfs_key_t flush_list_mutex_key; -mysql_pfs_key_t fts_cache_mutex_key; -mysql_pfs_key_t fts_cache_init_mutex_key; -mysql_pfs_key_t fts_delete_mutex_key; -mysql_pfs_key_t fts_doc_id_mutex_key; -mysql_pfs_key_t fts_pll_tokenize_mutex_key; -mysql_pfs_key_t ibuf_bitmap_mutex_key; -mysql_pfs_key_t ibuf_mutex_key; -mysql_pfs_key_t ibuf_pessimistic_insert_mutex_key; -mysql_pfs_key_t log_sys_mutex_key; -mysql_pfs_key_t log_cmdq_mutex_key; -mysql_pfs_key_t log_flush_order_mutex_key; -mysql_pfs_key_t recalc_pool_mutex_key; -mysql_pfs_key_t purge_sys_pq_mutex_key; -mysql_pfs_key_t recv_sys_mutex_key; -mysql_pfs_key_t redo_rseg_mutex_key; -mysql_pfs_key_t noredo_rseg_mutex_key; -mysql_pfs_key_t page_zip_stat_per_index_mutex_key; -mysql_pfs_key_t rtr_active_mutex_key; -mysql_pfs_key_t rtr_match_mutex_key; -mysql_pfs_key_t rtr_path_mutex_key; -mysql_pfs_key_t srv_innodb_monitor_mutex_key; -mysql_pfs_key_t srv_misc_tmpfile_mutex_key; -mysql_pfs_key_t srv_monitor_file_mutex_key; -mysql_pfs_key_t buf_dblwr_mutex_key; -mysql_pfs_key_t trx_pool_mutex_key; -mysql_pfs_key_t trx_pool_manager_mutex_key; -mysql_pfs_key_t lock_mutex_key; -mysql_pfs_key_t lock_wait_mutex_key; -mysql_pfs_key_t trx_sys_mutex_key; -mysql_pfs_key_t srv_threads_mutex_key; -mysql_pfs_key_t sync_array_mutex_key; -mysql_pfs_key_t thread_mutex_key; -mysql_pfs_key_t row_drop_list_mutex_key; -mysql_pfs_key_t rw_trx_hash_element_mutex_key; -mysql_pfs_key_t read_view_mutex_key; -#endif /* UNIV_PFS_MUTEX */ -#ifdef UNIV_PFS_RWLOCK -mysql_pfs_key_t dict_operation_lock_key; -mysql_pfs_key_t index_tree_rw_lock_key; -mysql_pfs_key_t index_online_log_key; -mysql_pfs_key_t fil_space_latch_key; -mysql_pfs_key_t trx_i_s_cache_lock_key; -mysql_pfs_key_t trx_purge_latch_key; -#endif /* UNIV_PFS_RWLOCK */ - -/** For monitoring active mutexes */ -MutexMonitor mutex_monitor; - -/** Print the filename "basename" e.g., p = "/a/b/c/d/e.cc" -> p = "e.cc" -@param[in] filename Name from where to extract the basename -@return the basename */ -const char* -sync_basename(const char* filename) -{ - const char* ptr = filename + strlen(filename) - 1; - - while (ptr > filename && *ptr != '/' && *ptr != '\\') { - --ptr; - } - - ++ptr; - - return(ptr); -} - -/** 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) -{ - std::ostringstream msg; - - msg << "Mutex " << sync_latch_get_name(id) << " " - << "created " << created; - - return(msg.str()); -} - -/** Enable the mutex monitoring */ -void -MutexMonitor::enable() -{ - /** Note: We don't add any latch meta-data after startup. Therefore - there is no need to use a mutex here. */ - - LatchMetaData::iterator end = latch_meta.end(); - - for (LatchMetaData::iterator it = latch_meta.begin(); it != end; ++it) { - - if (*it != NULL) { - (*it)->get_counter()->enable(); - } - } -} - -/** Disable the mutex monitoring */ -void -MutexMonitor::disable() -{ - /** Note: We don't add any latch meta-data after startup. Therefore - there is no need to use a mutex here. */ - - LatchMetaData::iterator end = latch_meta.end(); - - for (LatchMetaData::iterator it = latch_meta.begin(); it != end; ++it) { - - if (*it != NULL) { - (*it)->get_counter()->disable(); - } - } -} - -/** Reset the mutex monitoring counters */ -void -MutexMonitor::reset() -{ - /** Note: We don't add any latch meta-data after startup. Therefore - there is no need to use a mutex here. */ - - for (auto l : latch_meta) if (l) l->get_counter()->reset(); -} diff --git a/storage/innobase/trx/trx0i_s.cc b/storage/innobase/trx/trx0i_s.cc index c35a1a0cb45..f589e4f4f54 100644 --- a/storage/innobase/trx/trx0i_s.cc +++ b/storage/innobase/trx/trx0i_s.cc @@ -41,7 +41,6 @@ Created July 17, 2007 Vasil Dimov #include "rem0rec.h" #include "row0row.h" #include "srv0srv.h" -#include "sync0sync.h" #include "trx0sys.h" #include "que0que.h" #include "trx0purge.h" @@ -423,7 +422,7 @@ fill_trx_row( { const char* s; - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); row->trx_id = trx_get_id_for_print(trx); row->trx_started = trx->start_time; @@ -1046,7 +1045,7 @@ add_trx_relevant_locks_to_cache( requested lock row, or NULL or undefined */ { - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); /* If transaction is waiting we add the wait lock and all locks from another transactions that are blocking the wait lock. */ @@ -1194,7 +1193,7 @@ static void fetch_data_into_cache_low(trx_i_s_cache_t *cache, const trx_t *trx) static void fetch_data_into_cache(trx_i_s_cache_t *cache) { - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); trx_i_s_cache_clear(cache); /* Capture the state of transactions */ @@ -1225,9 +1224,9 @@ trx_i_s_possibly_fetch_data_into_cache( /* We need to read trx_sys and record/table lock queues */ - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); fetch_data_into_cache(cache); - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); /* update cache last read time */ cache->last_read = my_interval_timer(); diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc index ccc33d19a4b..20f6d230690 100644 --- a/storage/innobase/trx/trx0purge.cc +++ b/storage/innobase/trx/trx0purge.cc @@ -79,7 +79,7 @@ Executed in the purge coordinator thread. @return whether anything is to be purged */ inline bool TrxUndoRsegsIterator::set_next() { - mutex_enter(&purge_sys.pq_mutex); + mysql_mutex_lock(&purge_sys.pq_mutex); /* Only purge consumes events from the priority queue, user threads only produce the events. */ @@ -102,15 +102,15 @@ inline bool TrxUndoRsegsIterator::set_next() } else { /* Queue is empty, reset iterator. */ purge_sys.rseg = NULL; - mutex_exit(&purge_sys.pq_mutex); + mysql_mutex_unlock(&purge_sys.pq_mutex); m_rsegs = NullElement; m_iter = m_rsegs.begin(); return false; } purge_sys.rseg = *m_iter++; - mutex_exit(&purge_sys.pq_mutex); - mutex_enter(&purge_sys.rseg->mutex); + mysql_mutex_unlock(&purge_sys.pq_mutex); + mysql_mutex_lock(&purge_sys.rseg->mutex); ut_a(purge_sys.rseg->last_page_no != FIL_NULL); ut_ad(purge_sys.rseg->last_trx_no() == m_rsegs.trx_no()); @@ -126,7 +126,7 @@ inline bool TrxUndoRsegsIterator::set_next() purge_sys.hdr_offset = purge_sys.rseg->last_offset; purge_sys.hdr_page_no = purge_sys.rseg->last_page_no; - mutex_exit(&purge_sys.rseg->mutex); + mysql_mutex_unlock(&purge_sys.rseg->mutex); return(true); } @@ -176,7 +176,7 @@ void purge_sys_t::create() hdr_page_no= 0; hdr_offset= 0; latch.SRW_LOCK_INIT(trx_purge_latch_key); - mutex_create(LATCH_ID_PURGE_SYS_PQ, &pq_mutex); + mysql_mutex_init(purge_sys_pq_mutex_key, &pq_mutex, nullptr); truncate.current= NULL; truncate.last= NULL; heap= mem_heap_create(4096); @@ -197,7 +197,7 @@ void purge_sys_t::close() trx->state= TRX_STATE_NOT_STARTED; trx->free(); latch.destroy(); - mutex_free(&pq_mutex); + mysql_mutex_destroy(&pq_mutex); mem_heap_free(heap); heap= nullptr; } @@ -358,7 +358,7 @@ trx_purge_free_segment(trx_rseg_t* rseg, fil_addr_t hdr_addr) mtr_t mtr; mtr.start(); - mutex_enter(&rseg->mutex); + mysql_mutex_lock(&rseg->mutex); buf_block_t* rseg_hdr = trx_rsegf_get(rseg->space, rseg->page_no, &mtr); buf_block_t* block = trx_undo_page_get( @@ -375,12 +375,12 @@ trx_purge_free_segment(trx_rseg_t* rseg, fil_addr_t hdr_addr) while (!fseg_free_step_not_header( TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER + block->frame, &mtr)) { - mutex_exit(&rseg->mutex); + mysql_mutex_unlock(&rseg->mutex); mtr.commit(); mtr.start(); - mutex_enter(&rseg->mutex); + mysql_mutex_lock(&rseg->mutex); rseg_hdr = trx_rsegf_get(rseg->space, rseg->page_no, &mtr); @@ -421,7 +421,7 @@ trx_purge_free_segment(trx_rseg_t* rseg, fil_addr_t hdr_addr) rseg->curr_size -= seg_size; - mutex_exit(&(rseg->mutex)); + mysql_mutex_unlock(&rseg->mutex); mtr_commit(&mtr); } @@ -442,7 +442,7 @@ trx_purge_truncate_rseg_history( mtr.start(); ut_ad(rseg.is_persistent()); - mutex_enter(&rseg.mutex); + mysql_mutex_lock(&rseg.mutex); buf_block_t* rseg_hdr = trx_rsegf_get(rseg.space, rseg.page_no, &mtr); @@ -454,7 +454,7 @@ trx_purge_truncate_rseg_history( loop: if (hdr_addr.page == FIL_NULL) { func_exit: - mutex_exit(&rseg.mutex); + mysql_mutex_unlock(&rseg.mutex); mtr.commit(); return; } @@ -487,7 +487,7 @@ func_exit: /* We can free the whole log segment */ - mutex_exit(&rseg.mutex); + mysql_mutex_unlock(&rseg.mutex); mtr.commit(); /* calls the trx_purge_remove_log_hdr() @@ -498,12 +498,12 @@ func_exit: trx_purge_remove_log_hdr(rseg_hdr, block, hdr_addr.boffset, &mtr); - mutex_exit(&rseg.mutex); + mysql_mutex_unlock(&rseg.mutex); mtr.commit(); } mtr.start(); - mutex_enter(&rseg.mutex); + mysql_mutex_lock(&rseg.mutex); rseg_hdr = trx_rsegf_get(rseg.space, rseg.page_no, &mtr); @@ -520,7 +520,7 @@ static void trx_purge_cleanse_purge_queue(const fil_space_t& space) typedef std::vector<TrxUndoRsegs> purge_elem_list_t; purge_elem_list_t purge_elem_list; - mutex_enter(&purge_sys.pq_mutex); + mysql_mutex_lock(&purge_sys.pq_mutex); /* Remove rseg instances that are in the purge queue before we start truncate of corresponding UNDO truncate. */ @@ -547,7 +547,7 @@ static void trx_purge_cleanse_purge_queue(const fil_space_t& space) } } - mutex_exit(&purge_sys.pq_mutex); + mysql_mutex_unlock(&purge_sys.pq_mutex); } /** @@ -634,11 +634,11 @@ static void trx_purge_truncate_history() if (!rseg || rseg->space != &space) { continue; } - mutex_enter(&rseg->mutex); + mysql_mutex_lock(&rseg->mutex); ut_ad(rseg->skip_allocation); if (rseg->trx_ref_count) { not_free: - mutex_exit(&rseg->mutex); + mysql_mutex_unlock(&rseg->mutex); return; } @@ -666,7 +666,7 @@ not_free: } } - mutex_exit(&rseg->mutex); + mysql_mutex_unlock(&rseg->mutex); } ib::info() << "Truncating " << file->name; @@ -704,9 +704,9 @@ not_free: mtr.set_named_space(purge_sys.truncate.current); mtr.trim_pages(page_id_t(space.id, size)); fsp_header_init(purge_sys.truncate.current, size, &mtr); - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); purge_sys.truncate.current->size = file->size = size; - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); buf_block_t* sys_header = trx_sysf_get(&mtr); @@ -782,12 +782,12 @@ not_free: /* In MDEV-8319 (10.5) we will PUNCH_HOLE the garbage (with write-ahead logging). */ - mutex_enter(&fil_system.mutex); + mysql_mutex_lock(&fil_system.mutex); ut_ad(&space == purge_sys.truncate.current); ut_ad(space.is_being_truncated); purge_sys.truncate.current->set_stopping(false); purge_sys.truncate.current->is_being_truncated = false; - mutex_exit(&fil_system.mutex); + mysql_mutex_unlock(&fil_system.mutex); if (purge_sys.rseg != NULL && purge_sys.rseg->last_page_no == FIL_NULL) { @@ -835,7 +835,7 @@ static void trx_purge_rseg_get_next_history_log( trx_id_t trx_no; mtr_t mtr; - mutex_enter(&purge_sys.rseg->mutex); + mysql_mutex_lock(&purge_sys.rseg->mutex); ut_a(purge_sys.rseg->last_page_no != FIL_NULL); @@ -868,7 +868,7 @@ static void trx_purge_rseg_get_next_history_log( purge_sys.rseg->last_page_no = FIL_NULL; } - mutex_exit(&purge_sys.rseg->mutex); + mysql_mutex_unlock(&purge_sys.rseg->mutex); mtr.commit(); if (empty) { @@ -889,7 +889,7 @@ static void trx_purge_rseg_get_next_history_log( mtr_commit(&mtr); - mutex_enter(&purge_sys.rseg->mutex); + mysql_mutex_lock(&purge_sys.rseg->mutex); purge_sys.rseg->last_page_no = prev_log_addr.page; purge_sys.rseg->last_offset = prev_log_addr.boffset; @@ -901,13 +901,13 @@ static void trx_purge_rseg_get_next_history_log( than the events that Purge produces. ie. Purge can never produce events from an empty rollback segment. */ - mutex_enter(&purge_sys.pq_mutex); + mysql_mutex_lock(&purge_sys.pq_mutex); purge_sys.purge_queue.push(*purge_sys.rseg); - mutex_exit(&purge_sys.pq_mutex); + mysql_mutex_unlock(&purge_sys.pq_mutex); - mutex_exit(&purge_sys.rseg->mutex); + mysql_mutex_unlock(&purge_sys.rseg->mutex); } /** Position the purge sys "iterator" on the undo record to use for purging. */ diff --git a/storage/innobase/trx/trx0rec.cc b/storage/innobase/trx/trx0rec.cc index 4cd67791fcf..2503a2bd3aa 100644 --- a/storage/innobase/trx/trx0rec.cc +++ b/storage/innobase/trx/trx0rec.cc @@ -2047,9 +2047,9 @@ trx_undo_report_row_operation( mtr.set_log_mode(MTR_LOG_NO_REDO); } - mutex_enter(&rseg->mutex); + mysql_mutex_lock(&rseg->mutex); trx_undo_free_last_page(undo, &mtr); - mutex_exit(&rseg->mutex); + mysql_mutex_unlock(&rseg->mutex); err = DB_UNDO_RECORD_TOO_BIG; goto err_exit; diff --git a/storage/innobase/trx/trx0roll.cc b/storage/innobase/trx/trx0roll.cc index 8bba31fb5eb..2967281382d 100644 --- a/storage/innobase/trx/trx0roll.cc +++ b/storage/innobase/trx/trx0roll.cc @@ -242,7 +242,7 @@ dberr_t trx_rollback_for_mysql(trx_t* trx) == trx->rsegs.m_redo.rseg); mtr_t mtr; mtr.start(); - mutex_enter(&trx->rsegs.m_redo.rseg->mutex); + mysql_mutex_lock(&trx->rsegs.m_redo.rseg->mutex); if (trx_undo_t* undo = trx->rsegs.m_redo.undo) { trx_undo_set_state_at_prepare(trx, undo, true, &mtr); @@ -251,7 +251,7 @@ dberr_t trx_rollback_for_mysql(trx_t* trx) trx_undo_set_state_at_prepare(trx, undo, true, &mtr); } - mutex_exit(&trx->rsegs.m_redo.rseg->mutex); + mysql_mutex_unlock(&trx->rsegs.m_redo.rseg->mutex); /* Write the redo log for the XA ROLLBACK state change to the global buffer. It is not necessary to flush the redo log. If @@ -672,7 +672,7 @@ struct trx_roll_count_callback_arg static my_bool trx_roll_count_callback(rw_trx_hash_element_t *element, trx_roll_count_callback_arg *arg) { - mutex_enter(&element->mutex); + mysql_mutex_lock(&element->mutex); if (trx_t *trx= element->trx) { if (trx->is_recovered && trx_state_eq(trx, TRX_STATE_ACTIVE)) @@ -681,7 +681,7 @@ static my_bool trx_roll_count_callback(rw_trx_hash_element_t *element, arg->n_rows+= trx->undo_no; } } - mutex_exit(&element->mutex); + mysql_mutex_unlock(&element->mutex); return 0; } @@ -719,7 +719,7 @@ void trx_roll_report_progress() static my_bool trx_rollback_recovered_callback(rw_trx_hash_element_t *element, std::vector<trx_t*> *trx_list) { - mutex_enter(&element->mutex); + mysql_mutex_lock(&element->mutex); if (trx_t *trx= element->trx) { trx->mutex.wr_lock(); @@ -727,7 +727,7 @@ static my_bool trx_rollback_recovered_callback(rw_trx_hash_element_t *element, trx_list->push_back(trx); trx->mutex.wr_unlock(); } - mutex_exit(&element->mutex); + mysql_mutex_unlock(&element->mutex); return 0; } diff --git a/storage/innobase/trx/trx0rseg.cc b/storage/innobase/trx/trx0rseg.cc index 76be716a3c0..ffa5cdcb1b3 100644 --- a/storage/innobase/trx/trx0rseg.cc +++ b/storage/innobase/trx/trx0rseg.cc @@ -361,7 +361,7 @@ trx_rseg_mem_free(trx_rseg_t* rseg) trx_undo_t* undo; trx_undo_t* next_undo; - mutex_free(&rseg->mutex); + mysql_mutex_destroy(&rseg->mutex); /* There can't be any active transactions. */ ut_a(UT_LIST_GET_LEN(rseg->undo_list) == 0); @@ -400,10 +400,10 @@ trx_rseg_mem_create(ulint id, fil_space_t* space, uint32_t page_no) rseg->last_page_no = FIL_NULL; rseg->curr_size = 1; - mutex_create(rseg->is_persistent() - ? LATCH_ID_REDO_RSEG : LATCH_ID_NOREDO_RSEG, - &rseg->mutex); - + mysql_mutex_init(rseg->is_persistent() + ? redo_rseg_mutex_key + : noredo_rseg_mutex_key, + &rseg->mutex, nullptr); UT_LIST_INIT(rseg->undo_list, &trx_undo_t::undo_list); UT_LIST_INIT(rseg->old_insert_list, &trx_undo_t::undo_list); UT_LIST_INIT(rseg->undo_cached, &trx_undo_t::undo_list); diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index 846630337f8..50a78adcf53 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -47,7 +47,6 @@ Created 3/26/1996 Heikki Tuuri #include "trx0xa.h" #include "ut0pool.h" #include "ut0vec.h" -#include "sync0sync.h" #include <set> #include <new> @@ -253,49 +252,47 @@ struct TrxFactory { }; /** The lock strategy for TrxPool */ -struct TrxPoolLock { - TrxPoolLock() { } - - /** Create the mutex */ - void create() - { - mutex_create(LATCH_ID_TRX_POOL, &m_mutex); - } +class TrxPoolLock +{ + mysql_mutex_t mutex; - /** Acquire the mutex */ - void enter() { mutex_enter(&m_mutex); } +public: + /** Create the mutex */ + void create() + { + mysql_mutex_init(trx_pool_mutex_key, &mutex, nullptr); + } - /** Release the mutex */ - void exit() { mutex_exit(&m_mutex); } + /** Acquire the mutex */ + void enter() { mysql_mutex_lock(&mutex); } - /** Free the mutex */ - void destroy() { mutex_free(&m_mutex); } + /** Release the mutex */ + void exit() { mysql_mutex_unlock(&mutex); } - /** Mutex to use */ - ib_mutex_t m_mutex; + /** Free the mutex */ + void destroy() { mysql_mutex_destroy(&mutex); } }; /** The lock strategy for the TrxPoolManager */ -struct TrxPoolManagerLock { - TrxPoolManagerLock() { } - - /** Create the mutex */ - void create() - { - mutex_create(LATCH_ID_TRX_POOL_MANAGER, &m_mutex); - } +class TrxPoolManagerLock +{ + mysql_mutex_t mutex; - /** Acquire the mutex */ - void enter() { mutex_enter(&m_mutex); } +public: + /** Create the mutex */ + void create() + { + mysql_mutex_init(trx_pool_manager_mutex_key, &mutex, nullptr); + } - /** Release the mutex */ - void exit() { mutex_exit(&m_mutex); } + /** Acquire the mutex */ + void enter() { mysql_mutex_lock(&mutex); } - /** Free the mutex */ - void destroy() { mutex_free(&m_mutex); } + /** Release the mutex */ + void exit() { mysql_mutex_unlock(&mutex); } - /** Mutex to use */ - ib_mutex_t m_mutex; + /** Free the mutex */ + void destroy() { mysql_mutex_destroy(&mutex); } }; /** Use explicit mutexes for the trx_t pool and its manager. */ @@ -614,10 +611,10 @@ trx_resurrect_table_locks( if (dict_table_t* table = dict_table_open_on_id( *i, FALSE, DICT_TABLE_OP_LOAD_TABLESPACE)) { if (!table->is_readable()) { - mutex_enter(&dict_sys.mutex); + dict_sys.mutex_lock(); dict_table_close(table, TRUE, FALSE); dict_sys.remove(table); - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); continue; } @@ -883,12 +880,12 @@ static trx_rseg_t* trx_assign_rseg_low() /* By now we have only selected the rseg but not marked it allocated. By marking it allocated we are ensuring that it will never be selected for UNDO truncate purge. */ - mutex_enter(&rseg->mutex); + mysql_mutex_lock(&rseg->mutex); if (!rseg->skip_allocation) { rseg->trx_ref_count++; allocated = true; } - mutex_exit(&rseg->mutex); + mysql_mutex_unlock(&rseg->mutex); } while (!allocated); ut_ad(rseg->trx_ref_count > 0); @@ -1021,10 +1018,10 @@ trx_serialise(trx_t* trx) { trx_rseg_t *rseg = trx->rsegs.m_redo.rseg; ut_ad(rseg); - ut_ad(mutex_own(&rseg->mutex)); + mysql_mutex_assert_owner(&rseg->mutex); if (rseg->last_page_no == FIL_NULL) { - mutex_enter(&purge_sys.pq_mutex); + mysql_mutex_lock(&purge_sys.pq_mutex); } trx_sys.assign_new_trx_no(trx); @@ -1036,7 +1033,7 @@ trx_serialise(trx_t* trx) if (rseg->last_page_no == FIL_NULL) { purge_sys.purge_queue.push(TrxUndoRsegs(trx->rw_trx_hash_element->no, *rseg)); - mutex_exit(&purge_sys.pq_mutex); + mysql_mutex_unlock(&purge_sys.pq_mutex); } } @@ -1069,9 +1066,9 @@ trx_write_serialisation_history( temp_mtr.start(); temp_mtr.set_log_mode(MTR_LOG_NO_REDO); - mutex_enter(&trx->rsegs.m_noredo.rseg->mutex); + mysql_mutex_lock(&trx->rsegs.m_noredo.rseg->mutex); trx_undo_set_state_at_finish(undo, &temp_mtr); - mutex_exit(&trx->rsegs.m_noredo.rseg->mutex); + mysql_mutex_unlock(&trx->rsegs.m_noredo.rseg->mutex); temp_mtr.commit(); } @@ -1092,7 +1089,7 @@ trx_write_serialisation_history( ut_ad(!trx->read_only); ut_ad(!undo || undo->rseg == rseg); ut_ad(!old_insert || old_insert->rseg == rseg); - mutex_enter(&rseg->mutex); + mysql_mutex_lock(&rseg->mutex); /* Assign the transaction serialisation number and add any undo log to the purge queue. */ @@ -1107,7 +1104,7 @@ trx_write_serialisation_history( trx_purge_add_undo_to_history(trx, undo, mtr); } - mutex_exit(&rseg->mutex); + mysql_mutex_unlock(&rseg->mutex); MONITOR_INC(MONITOR_TRX_COMMIT_UNDO); } @@ -1232,11 +1229,11 @@ trx_update_mod_tables_timestamp( const time_t now = time(NULL); trx_mod_tables_t::const_iterator end = trx->mod_tables.end(); -#ifdef UNIV_DEBUG +#if defined SAFE_MUTEX && defined UNIV_DEBUG const bool preserve_tables = !innodb_evict_tables_on_commit_debug || trx->is_recovered /* avoid trouble with XA recovery */ # if 1 /* if dict_stats_exec_sql() were not playing dirty tricks */ - || mutex_own(&dict_sys.mutex) + || dict_sys.mutex_is_locked() # else /* this would be more proper way to do it */ || trx->dict_operation_lock_mode || trx->dict_operation # endif @@ -1257,7 +1254,7 @@ trx_update_mod_tables_timestamp( intrusive. */ dict_table_t* table = it->first; table->update_time = now; -#ifdef UNIV_DEBUG +#if defined SAFE_MUTEX && defined UNIV_DEBUG if (preserve_tables || table->get_ref_count() || UT_LIST_GET_LEN(table->locks)) { /* do not evict when committing DDL operations @@ -1267,15 +1264,15 @@ trx_update_mod_tables_timestamp( } /* recheck while holding the mutex that blocks table->acquire() */ - mutex_enter(&dict_sys.mutex); - mysql_mutex_lock(&lock_sys.mutex); + dict_sys.mutex_lock(); + lock_sys.mutex_lock(); const bool do_evict = !table->get_ref_count() && !UT_LIST_GET_LEN(table->locks); - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); if (do_evict) { dict_sys.remove(table, true); } - mutex_exit(&dict_sys.mutex); + dict_sys.mutex_unlock(); #endif } @@ -1396,10 +1393,10 @@ inline void trx_t::commit_in_memory(const mtr_t *mtr) if (trx_rseg_t *rseg= rsegs.m_redo.rseg) { - mutex_enter(&rseg->mutex); + mysql_mutex_lock(&rseg->mutex); ut_ad(rseg->trx_ref_count > 0); --rseg->trx_ref_count; - mutex_exit(&rseg->mutex); + mysql_mutex_unlock(&rseg->mutex); if (trx_undo_t *&insert= rsegs.m_redo.old_insert) { @@ -1874,7 +1871,7 @@ trx_print_latched( ulint max_query_len) /*!< in: max query length to print, or 0 to use the default max length */ { - mysql_mutex_assert_owner(&lock_sys.mutex); + lock_sys.mutex_assert_locked(); trx_print_low(f, trx, max_query_len, lock_number_of_rows_locked(&trx->lock), @@ -1897,11 +1894,11 @@ trx_print( ulint n_trx_locks; ulint heap_size; - mysql_mutex_lock(&lock_sys.mutex); + lock_sys.mutex_lock(); n_rec_locks = lock_number_of_rows_locked(&trx->lock); n_trx_locks = UT_LIST_GET_LEN(trx->lock.trx_locks); heap_size = mem_heap_get_size(trx->lock.lock_heap); - mysql_mutex_unlock(&lock_sys.mutex); + lock_sys.mutex_unlock(); trx_print_low(f, trx, max_query_len, n_rec_locks, n_trx_locks, heap_size); @@ -1960,9 +1957,9 @@ trx_prepare_low(trx_t* trx) mtr.start(); mtr.set_log_mode(MTR_LOG_NO_REDO); - mutex_enter(&undo->rseg->mutex); + mysql_mutex_lock(&undo->rseg->mutex); trx_undo_set_state_at_prepare(trx, undo, false, &mtr); - mutex_exit(&undo->rseg->mutex); + mysql_mutex_unlock(&undo->rseg->mutex); mtr.commit(); } @@ -1984,9 +1981,9 @@ trx_prepare_low(trx_t* trx) structure define the transaction as prepared in the file-based world, at the serialization point of lsn. */ - mutex_enter(&rseg->mutex); + mysql_mutex_lock(&rseg->mutex); trx_undo_set_state_at_prepare(trx, undo, false, &mtr); - mutex_exit(&rseg->mutex); + mysql_mutex_unlock(&rseg->mutex); /* Make the XA PREPARE durable. */ mtr.commit(); @@ -2062,7 +2059,7 @@ static my_bool trx_recover_for_mysql_callback(rw_trx_hash_element_t *element, trx_recover_for_mysql_callback_arg *arg) { DBUG_ASSERT(arg->len > 0); - mutex_enter(&element->mutex); + mysql_mutex_lock(&element->mutex); if (trx_t *trx= element->trx) { /* @@ -2088,7 +2085,7 @@ static my_bool trx_recover_for_mysql_callback(rw_trx_hash_element_t *element, } } } - mutex_exit(&element->mutex); + mysql_mutex_unlock(&element->mutex); /* Do not terminate upon reaching arg->len; count all transactions */ return false; } @@ -2097,13 +2094,13 @@ static my_bool trx_recover_for_mysql_callback(rw_trx_hash_element_t *element, static my_bool trx_recover_reset_callback(rw_trx_hash_element_t *element, void*) { - mutex_enter(&element->mutex); + mysql_mutex_lock(&element->mutex); if (trx_t *trx= element->trx) { if (trx_state_eq(trx, TRX_STATE_PREPARED_RECOVERED)) trx->state= TRX_STATE_PREPARED; } - mutex_exit(&element->mutex); + mysql_mutex_unlock(&element->mutex); return false; } @@ -2152,7 +2149,7 @@ static my_bool trx_get_trx_by_xid_callback(rw_trx_hash_element_t *element, trx_get_trx_by_xid_callback_arg *arg) { my_bool found= 0; - mutex_enter(&element->mutex); + mysql_mutex_lock(&element->mutex); if (trx_t *trx= element->trx) { trx->mutex.wr_lock(); @@ -2174,7 +2171,7 @@ static my_bool trx_get_trx_by_xid_callback(rw_trx_hash_element_t *element, } trx->mutex.wr_unlock(); } - mutex_exit(&element->mutex); + mysql_mutex_unlock(&element->mutex); return found; } diff --git a/storage/innobase/trx/trx0undo.cc b/storage/innobase/trx/trx0undo.cc index cd27cd251ae..6b0103a3d52 100644 --- a/storage/innobase/trx/trx0undo.cc +++ b/storage/innobase/trx/trx0undo.cc @@ -552,7 +552,7 @@ buf_block_t* trx_undo_add_page(trx_undo_t* undo, mtr_t* mtr) a pessimistic insert in a B-tree, and we must reserve the counterpart of the tree latch, which is the rseg mutex. */ - mutex_enter(&rseg->mutex); + mysql_mutex_lock(&rseg->mutex); buf_block_t* header_block = trx_undo_page_get( page_id_t(undo->rseg->space->id, undo->hdr_page_no), mtr); @@ -584,7 +584,7 @@ buf_block_t* trx_undo_add_page(trx_undo_t* undo, mtr_t* mtr) rseg->curr_size++; func_exit: - mutex_exit(&rseg->mutex); + mysql_mutex_unlock(&rseg->mutex); return(new_block); } @@ -608,7 +608,7 @@ trx_undo_free_page( const ulint space = rseg->space->id; ut_a(hdr_page_no != page_no); - ut_ad(mutex_own(&(rseg->mutex))); + mysql_mutex_assert_owner(&rseg->mutex); buf_block_t* undo_block = trx_undo_page_get(page_id_t(space, page_no), mtr); @@ -673,7 +673,7 @@ void trx_undo_truncate_end(trx_undo_t& undo, undo_no_t limit, bool is_temp) } trx_undo_rec_t* trunc_here = NULL; - mutex_enter(&undo.rseg->mutex); + mysql_mutex_lock(&undo.rseg->mutex); buf_block_t* undo_block = trx_undo_page_get( page_id_t(undo.rseg->space->id, undo.last_page_no), &mtr); @@ -693,13 +693,13 @@ void trx_undo_truncate_end(trx_undo_t& undo, undo_no_t limit, bool is_temp) if (undo.last_page_no != undo.hdr_page_no) { trx_undo_free_last_page(&undo, &mtr); - mutex_exit(&undo.rseg->mutex); + mysql_mutex_unlock(&undo.rseg->mutex); mtr.commit(); continue; } func_exit: - mutex_exit(&undo.rseg->mutex); + mysql_mutex_unlock(&undo.rseg->mutex); if (trunc_here) { mtr.write<2>(*undo_block, @@ -732,7 +732,7 @@ trx_undo_truncate_start( trx_undo_rec_t* last_rec; mtr_t mtr; - ut_ad(mutex_own(&(rseg->mutex))); + mysql_mutex_assert_owner(&rseg->mutex); if (!limit) { return; @@ -799,7 +799,7 @@ static void trx_undo_seg_free(const trx_undo_t* undo, bool noredo) mtr.set_log_mode(MTR_LOG_NO_REDO); } - mutex_enter(&rseg->mutex); + mysql_mutex_lock(&rseg->mutex); buf_block_t* block = trx_undo_page_get( page_id_t(rseg->space->id, undo->hdr_page_no), &mtr); @@ -819,7 +819,7 @@ static void trx_undo_seg_free(const trx_undo_t* undo, bool noredo) MONITOR_DEC(MONITOR_NUM_UNDO_SLOT_USED); } - mutex_exit(&rseg->mutex); + mysql_mutex_unlock(&rseg->mutex); mtr.commit(); } while (!finished); } @@ -869,10 +869,10 @@ trx_undo_mem_create_at_db_start(trx_rseg_t *rseg, ulint id, uint32_t page_no, max_trx_id = trx_id; } - mutex_enter(&rseg->mutex); + mysql_mutex_lock(&rseg->mutex); trx_undo_t* undo = trx_undo_mem_create( rseg, id, trx_id, &xid, page_no, offset); - mutex_exit(&rseg->mutex); + mysql_mutex_unlock(&rseg->mutex); undo->dict_operation = undo_header[TRX_UNDO_DICT_TRANS]; undo->table_id = mach_read_from_8(undo_header + TRX_UNDO_TABLE_ID); @@ -946,7 +946,7 @@ trx_undo_mem_create( { trx_undo_t* undo; - ut_ad(mutex_own(&(rseg->mutex))); + mysql_mutex_assert_owner(&rseg->mutex); ut_a(id < TRX_RSEG_N_SLOTS); @@ -991,7 +991,7 @@ trx_undo_mem_init_for_reuse( const XID* xid, /*!< in: X/Open XA transaction identification*/ uint16_t offset) /*!< in: undo log header byte offset on page */ { - ut_ad(mutex_own(&((undo->rseg)->mutex))); + mysql_mutex_assert_owner(&undo->rseg->mutex); ut_a(undo->id < TRX_RSEG_N_SLOTS); @@ -1021,7 +1021,7 @@ trx_undo_create(trx_t* trx, trx_rseg_t* rseg, trx_undo_t** undo, { ulint id; - ut_ad(mutex_own(&(rseg->mutex))); + mysql_mutex_assert_owner(&rseg->mutex); buf_block_t* block = trx_undo_seg_create( rseg->space, @@ -1080,7 +1080,7 @@ buf_block_t* trx_undo_reuse_cached(trx_t* trx, trx_rseg_t* rseg, trx_undo_t** pundo, mtr_t* mtr) { - ut_ad(mutex_own(&rseg->mutex)); + mysql_mutex_assert_owner(&rseg->mutex); trx_undo_t* undo = UT_LIST_GET_FIRST(rseg->undo_cached); if (!undo) { @@ -1153,7 +1153,7 @@ trx_undo_assign(trx_t* trx, dberr_t* err, mtr_t* mtr) trx_rseg_t* rseg = trx->rsegs.m_redo.rseg; - mutex_enter(&rseg->mutex); + mysql_mutex_lock(&rseg->mutex); buf_block_t* block = trx_undo_reuse_cached( trx, rseg, &trx->rsegs.m_redo.undo, mtr); @@ -1171,7 +1171,7 @@ trx_undo_assign(trx_t* trx, dberr_t* err, mtr_t* mtr) UT_LIST_ADD_FIRST(rseg->undo_list, trx->rsegs.m_redo.undo); func_exit: - mutex_exit(&rseg->mutex); + mysql_mutex_unlock(&rseg->mutex); return block; } @@ -1209,7 +1209,7 @@ trx_undo_assign_low(trx_t* trx, trx_rseg_t* rseg, trx_undo_t** undo, *err = DB_TOO_MANY_CONCURRENT_TRXS; return NULL; ); - mutex_enter(&rseg->mutex); + mysql_mutex_lock(&rseg->mutex); buf_block_t* block = trx_undo_reuse_cached(trx, rseg, undo, mtr); @@ -1226,7 +1226,7 @@ trx_undo_assign_low(trx_t* trx, trx_rseg_t* rseg, trx_undo_t** undo, UT_LIST_ADD_FIRST(rseg->undo_list, *undo); func_exit: - mutex_exit(&rseg->mutex); + mysql_mutex_unlock(&rseg->mutex); return block; } @@ -1305,7 +1305,7 @@ trx_undo_commit_cleanup(trx_undo_t* undo, bool is_temp) ut_ad(is_temp == !rseg->is_persistent()); ut_ad(!is_temp || 0 == UT_LIST_GET_LEN(rseg->old_insert_list)); - mutex_enter(&rseg->mutex); + mysql_mutex_lock(&rseg->mutex); UT_LIST_REMOVE(is_temp ? rseg->undo_list : rseg->old_insert_list, undo); @@ -1317,9 +1317,9 @@ trx_undo_commit_cleanup(trx_undo_t* undo, bool is_temp) ut_ad(undo->state == TRX_UNDO_TO_PURGE); /* Delete first the undo log segment in the file */ - mutex_exit(&rseg->mutex); + mysql_mutex_unlock(&rseg->mutex); trx_undo_seg_free(undo, is_temp); - mutex_enter(&rseg->mutex); + mysql_mutex_lock(&rseg->mutex); ut_ad(rseg->curr_size > undo->size); rseg->curr_size -= undo->size; @@ -1327,7 +1327,7 @@ trx_undo_commit_cleanup(trx_undo_t* undo, bool is_temp) ut_free(undo); } - mutex_exit(&rseg->mutex); + mysql_mutex_unlock(&rseg->mutex); } /** At shutdown, frees the undo logs of a transaction. */ diff --git a/storage/innobase/ut/ut0mem.cc b/storage/innobase/ut/ut0mem.cc index faade827283..15d4da12a76 100644 --- a/storage/innobase/ut/ut0mem.cc +++ b/storage/innobase/ut/ut0mem.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2019, MariaDB Corporation. +Copyright (c) 2019, 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 @@ -25,6 +25,7 @@ Created 5/11/1994 Heikki Tuuri *************************************************************************/ #include "ut0mem.h" +#include "ut0new.h" /******************************************************************** Concatenate 3 strings.*/ diff --git a/storage/innobase/ut/ut0new.cc b/storage/innobase/ut/ut0new.cc index 5e00a4ca0ea..a3ce1bdf3c7 100644 --- a/storage/innobase/ut/ut0new.cc +++ b/storage/innobase/ut/ut0new.cc @@ -25,7 +25,7 @@ Created May 26, 2014 Vasil Dimov *******************************************************/ #include "univ.i" -#include <algorithm> +#include "ut0new.h" /** The total amount of memory currently allocated from the operating system with allocate_large(). */ Atomic_counter<ulint> os_total_large_mem_allocated; diff --git a/storage/innobase/ut/ut0rbt.cc b/storage/innobase/ut/ut0rbt.cc index cdd1ef06775..7ba6693cbc1 100644 --- a/storage/innobase/ut/ut0rbt.cc +++ b/storage/innobase/ut/ut0rbt.cc @@ -1,6 +1,7 @@ /***************************************************************************//** Copyright (c) 2007, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 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 @@ -24,6 +25,7 @@ Created 2007-03-20 Sunny Bains ***********************************************************************/ #include "ut0rbt.h" +#include "ut0new.h" /**********************************************************************//** Definition of a red-black tree |