diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2020-12-04 18:07:25 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2020-12-15 17:56:17 +0200 |
commit | db006a9a43b6e68c4b92d2762043fa76b313623c (patch) | |
tree | 0fb86f11c7d61fc57256a8115cb5aa6e92249737 /storage/innobase | |
parent | 38fd7b7d9170369b16ff553f01669182e70bc9b5 (diff) | |
download | mariadb-git-db006a9a43b6e68c4b92d2762043fa76b313623c.tar.gz |
MDEV-21452: Remove os_event_t, MUTEX_EVENT, TTASEventMutex, sync_array
We will default to MUTEXTYPE=sys (using OSTrackMutex) for those
ib_mutex_t that have not been replaced yet.
The view INFORMATION_SCHEMA.INNODB_SYS_SEMAPHORE_WAITS is removed.
The parameter innodb_sync_array_size is removed.
FIXME: innodb_fatal_semaphore_wait_threshold will no longer be enforced.
We should enforce it for lock_sys.mutex and dict_sys.mutex somehow!
innodb_sync_debug=ON might still cover ib_mutex_t.
Diffstat (limited to 'storage/innobase')
-rw-r--r-- | storage/innobase/CMakeLists.txt | 5 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.cc | 10 | ||||
-rw-r--r-- | storage/innobase/handler/i_s.cc | 157 | ||||
-rw-r--r-- | storage/innobase/handler/i_s.h | 44 | ||||
-rw-r--r-- | storage/innobase/include/ib0mutex.h | 163 | ||||
-rw-r--r-- | storage/innobase/include/os0event.h | 131 | ||||
-rw-r--r-- | storage/innobase/include/srv0srv.h | 3 | ||||
-rw-r--r-- | storage/innobase/include/sync0arr.h | 127 | ||||
-rw-r--r-- | storage/innobase/include/sync0arr.ic | 82 | ||||
-rw-r--r-- | storage/innobase/include/sync0types.h | 2 | ||||
-rw-r--r-- | storage/innobase/include/ut0mutex.h | 4 | ||||
-rw-r--r-- | storage/innobase/include/ut0new.h | 2 | ||||
-rw-r--r-- | storage/innobase/innodb.cmake | 6 | ||||
-rw-r--r-- | storage/innobase/os/os0event.cc | 515 | ||||
-rw-r--r-- | storage/innobase/srv/srv0srv.cc | 41 | ||||
-rw-r--r-- | storage/innobase/srv/srv0start.cc | 28 | ||||
-rw-r--r-- | storage/innobase/sync/sync0arr.cc | 960 | ||||
-rw-r--r-- | storage/innobase/sync/sync0debug.cc | 7 |
18 files changed, 14 insertions, 2273 deletions
diff --git a/storage/innobase/CMakeLists.txt b/storage/innobase/CMakeLists.txt index 530124e16aa..5a5c268763a 100644 --- a/storage/innobase/CMakeLists.txt +++ b/storage/innobase/CMakeLists.txt @@ -187,7 +187,6 @@ SET(INNOBASE_SOURCES include/mtr0mtr.h include/mtr0mtr.ic include/mtr0types.h - include/os0event.h include/os0file.h include/os0file.ic include/os0thread.h @@ -239,8 +238,6 @@ SET(INNOBASE_SOURCES include/srv0mon.ic include/srv0srv.h include/srv0start.h - include/sync0arr.h - include/sync0arr.ic include/sync0debug.h include/sync0policy.h include/sux_lock.h @@ -294,7 +291,6 @@ SET(INNOBASE_SOURCES mem/mem0mem.cc mtr/mtr0mtr.cc os/os0file.cc - os/os0event.cc os/os0thread.cc page/page0cur.cc page/page0page.cc @@ -328,7 +324,6 @@ SET(INNOBASE_SOURCES srv/srv0srv.cc srv/srv0start.cc sync/srw_lock.cc - sync/sync0arr.cc sync/sync0debug.cc sync/sync0sync.cc trx/trx0i_s.cc diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 9393761974a..e38cccf0f34 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -18444,14 +18444,6 @@ static MYSQL_SYSVAR_UINT(purge_threads, srv_n_purge_threads, "Number of tasks for purging transaction history", NULL, NULL, 4, 1, innodb_purge_threads_MAX, 0); -static MYSQL_SYSVAR_ULONG(sync_array_size, srv_sync_array_size, - PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, - "Size of the mutex/lock wait array.", - NULL, NULL, - 1, /* Default setting */ - 1, /* Minimum value */ - 1024, 0); /* Maximum value */ - static MYSQL_SYSVAR_UINT(fast_shutdown, srv_fast_shutdown, PLUGIN_VAR_OPCMDARG, "Speeds up the shutdown process of the InnoDB storage engine. Possible" @@ -19471,7 +19463,6 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(undo_log_truncate), MYSQL_SYSVAR(undo_directory), MYSQL_SYSVAR(undo_tablespaces), - MYSQL_SYSVAR(sync_array_size), MYSQL_SYSVAR(compression_failure_threshold_pct), MYSQL_SYSVAR(compression_pad_pct_max), MYSQL_SYSVAR(default_row_format), @@ -19554,7 +19545,6 @@ i_s_innodb_sys_foreign, i_s_innodb_sys_foreign_cols, i_s_innodb_sys_tablespaces, i_s_innodb_sys_virtual, -i_s_innodb_sys_semaphore_waits, i_s_innodb_tablespaces_encryption maria_declare_plugin_end; diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc index 6eaacfd800a..6314bdc940d 100644 --- a/storage/innobase/handler/i_s.cc +++ b/storage/innobase/handler/i_s.cc @@ -22,7 +22,6 @@ this program; if not, write to the Free Software Foundation, Inc., InnoDB INFORMATION SCHEMA tables interface to MySQL. Created July 18, 2007 Vasil Dimov -Modified Dec 29, 2014 Jan Lindström (Added sys_semaphore_waits) *******************************************************/ #include "univ.i" @@ -54,7 +53,6 @@ Modified Dec 29, 2014 Jan Lindström (Added sys_semaphore_waits) #include "fts0priv.h" #include "btr0btr.h" #include "page0zip.h" -#include "sync0arr.h" #include "fil0fil.h" #include "fil0crypt.h" #include "dict0crea.h" @@ -171,20 +169,6 @@ time_t MYSQL_TYPE_DATETIME --------------------------------- */ -/** Implemented on sync0arr.cc */ -/*******************************************************************//** -Function to populate INFORMATION_SCHEMA.INNODB_SYS_SEMAPHORE_WAITS table. -Loop through each item on sync array, and extract the column -information and fill the INFORMATION_SCHEMA.INNODB_SYS_SEMAPHORE_WAITS table. -@return 0 on success */ -UNIV_INTERN -int -sync_arr_fill_sys_semphore_waits_table( -/*===================================*/ - THD* thd, /*!< in: thread */ - TABLE_LIST* tables, /*!< in/out: tables to fill */ - Item* ); /*!< in: condition (not used) */ - /*******************************************************************//** Common function to fill any of the dynamic tables: INFORMATION_SCHEMA.innodb_trx @@ -245,6 +229,7 @@ field_store_time_t( /*******************************************************************//** Auxiliary function to store char* value in MYSQL_TYPE_STRING field. @return 0 on success */ +static int field_store_string( /*===============*/ @@ -6879,143 +6864,3 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_tablespaces_encryption = STRUCT_FLD(version_info, INNODB_VERSION_STR), STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE) }; - -namespace Show { -/* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_SYS_SEMAPHORE_WAITS */ -static ST_FIELD_INFO innodb_sys_semaphore_waits_fields_info[] = -{ - // SYS_SEMAPHORE_WAITS_THREAD_ID 0 - Column("THREAD_ID", ULonglong(), NOT_NULL), - - // SYS_SEMAPHORE_WAITS_OBJECT_NAME 1 - Column("OBJECT_NAME", Varchar(OS_FILE_MAX_PATH), NULLABLE), - - // SYS_SEMAPHORE_WAITS_FILE 2 - Column("FILE", Varchar(OS_FILE_MAX_PATH), NULLABLE), - - // SYS_SEMAPHORE_WAITS_LINE 3 - Column("LINE", ULong(), NOT_NULL), - - // SYS_SEMAPHORE_WAITS_WAIT_TIME 4 - Column("WAIT_TIME", ULonglong(), NOT_NULL), - - // SYS_SEMAPHORE_WAITS_WAIT_OBJECT 5 - Column("WAIT_OBJECT", ULonglong(), NOT_NULL), - - // SYS_SEMAPHORE_WAITS_WAIT_TYPE 6 - Column("WAIT_TYPE", Varchar(16), NULLABLE), - - // SYS_SEMAPHORE_WAITS_HOLDER_THREAD_ID 7 - Column("HOLDER_THREAD_ID", ULonglong(), NOT_NULL), - - // SYS_SEMAPHORE_WAITS_HOLDER_FILE 8 - Column("HOLDER_FILE", Varchar(OS_FILE_MAX_PATH), NULLABLE), - - // SYS_SEMAPHORE_WAITS_HOLDER_LINE 9 - Column("HOLDER_LINE", ULong(), NOT_NULL), - - // SYS_SEMAPHORE_WAITS_CREATED_FILE 10 - Column("CREATED_FILE", Varchar(OS_FILE_MAX_PATH), NULLABLE), - - // SYS_SEMAPHORE_WAITS_CREATED_LINE 11 - Column("CREATED_LINE", ULong(), NOT_NULL), - - // SYS_SEMAPHORE_WAITS_WRITER_THREAD 12 - Column("WRITER_THREAD", ULonglong(), NOT_NULL), - - // SYS_SEMAPHORE_WAITS_RESERVATION_MODE 13 - Column("RESERVATION_MODE", Varchar(16), NULLABLE), - - // SYS_SEMAPHORE_WAITS_READERS 14 - Column("READERS", ULong(), NOT_NULL), - - // SYS_SEMAPHORE_WAITS_WAITERS_FLAG 15 - Column("WAITERS_FLAG", ULonglong(), NOT_NULL), - - // SYS_SEMAPHORE_WAITS_LOCK_WORD 16 - Column("LOCK_WORD", ULonglong(), NOT_NULL), - - // SYS_SEMAPHORE_WAITS_LAST_WRITER_FILE 17 - Column("LAST_WRITER_FILE", Varchar(OS_FILE_MAX_PATH), NULLABLE), - - // SYS_SEMAPHORE_WAITS_LAST_WRITER_LINE 18 - Column("LAST_WRITER_LINE", ULong(), NOT_NULL), - - // SYS_SEMAPHORE_WAITS_OS_WAIT_COUNT 19 - Column("OS_WAIT_COUNT", ULong(), NOT_NULL), - - CEnd() -}; -} // namespace Show - - - -/*******************************************************************//** -Bind the dynamic table INFORMATION_SCHEMA.INNODB_SYS_SEMAPHORE_WAITS -@return 0 on success */ -static -int -innodb_sys_semaphore_waits_init( -/*============================*/ - void* p) /*!< in/out: table schema object */ -{ - ST_SCHEMA_TABLE* schema; - - DBUG_ENTER("innodb_sys_semaphore_waits_init"); - - schema = (ST_SCHEMA_TABLE*) p; - - schema->fields_info = Show::innodb_sys_semaphore_waits_fields_info; - schema->fill_table = sync_arr_fill_sys_semphore_waits_table; - - DBUG_RETURN(0); -} - -UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_semaphore_waits = -{ - /* the plugin type (a MYSQL_XXX_PLUGIN value) */ - /* int */ - STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN), - - /* pointer to type-specific plugin descriptor */ - /* void* */ - STRUCT_FLD(info, &i_s_info), - - /* plugin name */ - /* const char* */ - STRUCT_FLD(name, "INNODB_SYS_SEMAPHORE_WAITS"), - - /* plugin author (for SHOW PLUGINS) */ - /* const char* */ - STRUCT_FLD(author, maria_plugin_author), - - /* general descriptive text (for SHOW PLUGINS) */ - /* const char* */ - STRUCT_FLD(descr, "InnoDB SYS_SEMAPHORE_WAITS"), - - /* the plugin license (PLUGIN_LICENSE_XXX) */ - /* int */ - STRUCT_FLD(license, PLUGIN_LICENSE_GPL), - - /* the function to invoke when plugin is loaded */ - /* int (*)(void*); */ - STRUCT_FLD(init, innodb_sys_semaphore_waits_init), - - /* the function to invoke when plugin is unloaded */ - /* int (*)(void*); */ - STRUCT_FLD(deinit, i_s_common_deinit), - - /* plugin version (for SHOW PLUGINS) */ - /* unsigned int */ - STRUCT_FLD(version, INNODB_VERSION_SHORT), - - /* struct st_mysql_show_var* */ - STRUCT_FLD(status_vars, NULL), - - /* struct st_mysql_sys_var** */ - STRUCT_FLD(system_vars, NULL), - - /* Maria extension */ - STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE), -}; diff --git a/storage/innobase/handler/i_s.h b/storage/innobase/handler/i_s.h index 9947721407a..395bc3e7909 100644 --- a/storage/innobase/handler/i_s.h +++ b/storage/innobase/handler/i_s.h @@ -61,7 +61,6 @@ extern struct st_maria_plugin i_s_innodb_sys_foreign_cols; extern struct st_maria_plugin i_s_innodb_sys_tablespaces; extern struct st_maria_plugin i_s_innodb_sys_virtual; extern struct st_maria_plugin i_s_innodb_tablespaces_encryption; -extern struct st_maria_plugin i_s_innodb_sys_semaphore_waits; /** The latest successfully looked up innodb_fts_aux_table */ extern table_id_t innodb_ft_aux_table_id; @@ -99,47 +98,4 @@ do { \ #define STRUCT_FLD(name, value) value #endif -/* Don't use a static const variable here, as some C++ compilers (notably -HPUX aCC: HP ANSI C++ B3910B A.03.65) can't handle it. */ -#define END_OF_ST_FIELD_INFO \ - {STRUCT_FLD(field_name, NULL), \ - STRUCT_FLD(field_length, 0), \ - STRUCT_FLD(field_type, MYSQL_TYPE_NULL), \ - STRUCT_FLD(value, 0), \ - STRUCT_FLD(field_flags, 0), \ - STRUCT_FLD(old_name, ""), \ - STRUCT_FLD(open_method, SKIP_OPEN_TABLE)} - -/** Fields on INFORMATION_SCHEMA.SYS_SEMAMPHORE_WAITS table */ -#define SYS_SEMAPHORE_WAITS_THREAD_ID 0 -#define SYS_SEMAPHORE_WAITS_OBJECT_NAME 1 -#define SYS_SEMAPHORE_WAITS_FILE 2 -#define SYS_SEMAPHORE_WAITS_LINE 3 -#define SYS_SEMAPHORE_WAITS_WAIT_TIME 4 -#define SYS_SEMAPHORE_WAITS_WAIT_OBJECT 5 -#define SYS_SEMAPHORE_WAITS_WAIT_TYPE 6 -#define SYS_SEMAPHORE_WAITS_HOLDER_THREAD_ID 7 -#define SYS_SEMAPHORE_WAITS_HOLDER_FILE 8 -#define SYS_SEMAPHORE_WAITS_HOLDER_LINE 9 -#define SYS_SEMAPHORE_WAITS_CREATED_FILE 10 -#define SYS_SEMAPHORE_WAITS_CREATED_LINE 11 -#define SYS_SEMAPHORE_WAITS_WRITER_THREAD 12 -#define SYS_SEMAPHORE_WAITS_RESERVATION_MODE 13 -#define SYS_SEMAPHORE_WAITS_READERS 14 -#define SYS_SEMAPHORE_WAITS_WAITERS_FLAG 15 -#define SYS_SEMAPHORE_WAITS_LOCK_WORD 16 -#define SYS_SEMAPHORE_WAITS_LAST_WRITER_FILE 17 -#define SYS_SEMAPHORE_WAITS_LAST_WRITER_LINE 18 -#define SYS_SEMAPHORE_WAITS_OS_WAIT_COUNT 19 - -/*******************************************************************//** -Auxiliary function to store char* value in MYSQL_TYPE_STRING field. -@return 0 on success */ -int -field_store_string( -/*===============*/ - Field* field, /*!< in/out: target field for storage */ - const char* str); /*!< in: NUL-terminated utf-8 string, - or NULL */ - #endif /* i_s_h */ diff --git a/storage/innobase/include/ib0mutex.h b/storage/innobase/include/ib0mutex.h index 781b688e0b1..b83a1aac419 100644 --- a/storage/innobase/include/ib0mutex.h +++ b/storage/innobase/include/ib0mutex.h @@ -30,8 +30,6 @@ Created 2013-03-26 Sunny Bains. #define ib0mutex_h #include "my_cpu.h" -#include "os0event.h" -#include "sync0arr.h" /** OS mutex for tracking lock/unlock for debugging */ template <template <typename> class Policy> @@ -363,167 +361,6 @@ private: std::atomic<uint32_t> m_lock_word; }; -template <template <typename> class Policy> -struct TTASEventMutex { - - typedef Policy<TTASEventMutex> MutexPolicy; - - TTASEventMutex() - UNIV_NOTHROW - : - m_lock_word(MUTEX_STATE_UNLOCKED), - m_event() - { - /* Check that lock_word is aligned. */ - ut_ad(!((ulint) &m_lock_word % sizeof(ulint))); - } - - ~TTASEventMutex() - UNIV_NOTHROW - { - ut_ad(state() == MUTEX_STATE_UNLOCKED); - } - - /** 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, const char*, uint32_t) UNIV_NOTHROW - { - ut_a(m_event == 0); - ut_ad(state() == MUTEX_STATE_UNLOCKED); - - m_event = os_event_create(sync_latch_get_name(id)); - } - - /** This is the real desctructor. This mutex can be created in BSS and - its desctructor will be called on exit(). We can't call - os_event_destroy() at that stage. */ - void destroy() - UNIV_NOTHROW - { - ut_ad(state() == MUTEX_STATE_UNLOCKED); - - /* We have to free the event before InnoDB shuts down. */ - os_event_destroy(m_event); - m_event = 0; - } - - /** Try and lock the mutex. Note: POSIX returns 0 on success. - @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 - { - if (m_lock_word.exchange(MUTEX_STATE_UNLOCKED, - std::memory_order_release) - == MUTEX_STATE_WAITERS) { - os_event_set(m_event); - sync_array_object_signalled(); - } - } - - /** Acquire the mutex. - @param[in] max_spins max number of spins - @param[in] max_delay max delay per spin - @param[in] filename from where called - @param[in] line within filename */ - void enter( - uint32_t max_spins, - uint32_t max_delay, - const char* filename, - uint32_t line) - UNIV_NOTHROW - { - uint32_t n_spins = 0; - uint32_t n_waits = 0; - const uint32_t step = max_spins; - - while (!try_lock()) { - if (n_spins++ == max_spins) { - max_spins += step; - n_waits++; - os_thread_yield(); - - sync_cell_t* cell; - sync_array_t *sync_arr = sync_array_get_and_reserve_cell( - this, - filename, line, &cell); - - uint32_t oldval = MUTEX_STATE_LOCKED; - m_lock_word.compare_exchange_strong( - oldval, - MUTEX_STATE_WAITERS, - std::memory_order_relaxed, - std::memory_order_relaxed); - - if (oldval == MUTEX_STATE_UNLOCKED) { - sync_array_free_cell(sync_arr, cell); - } else { - sync_array_wait_event(sync_arr, cell); - } - } else { - ut_delay(max_delay); - } - } - - m_policy.add(n_spins, n_waits); - } - - /** @return the lock state. */ - int32 state() const - UNIV_NOTHROW - { - return m_lock_word.load(std::memory_order_relaxed); - } - - /** The event that the mutex will wait in sync0arr.cc - @return even instance */ - os_event_t event() - UNIV_NOTHROW - { - return(m_event); - } - - /** @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 */ - TTASEventMutex(const TTASEventMutex&); - TTASEventMutex& operator=(const TTASEventMutex&); - - /** mutex state */ - std::atomic<uint32_t> m_lock_word; - - /** Used by sync0arr.cc for the wait queue */ - os_event_t m_event; - - /** Policy data */ - MutexPolicy m_policy; -}; - /** Mutex interface for all policy mutexes. This class handles the interfacing with the Performance Schema instrumentation. */ template <typename MutexImpl> diff --git a/storage/innobase/include/os0event.h b/storage/innobase/include/os0event.h deleted file mode 100644 index 52f6500ae63..00000000000 --- a/storage/innobase/include/os0event.h +++ /dev/null @@ -1,131 +0,0 @@ -/***************************************************************************** -Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved. - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free Software -Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., -51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA - -*****************************************************************************/ - -/**************************************************//** -@file include/os0event.h -The interface to the operating system condition variables - -Created 2012-09-23 Sunny Bains (split from os0sync.h) -*******************************************************/ - -#ifndef os0event_h -#define os0event_h - -#include "univ.i" - -// Forward declaration. -struct os_event; -typedef struct os_event* os_event_t; - -/** Denotes an infinite delay for os_event_wait_time() */ -#define OS_SYNC_INFINITE_TIME ULINT_UNDEFINED - -/** Return value of os_event_wait_time() when the time is exceeded */ -#define OS_SYNC_TIME_EXCEEDED 1 - -/** -Creates an event semaphore, i.e., a semaphore which may just have two states: -signaled and nonsignaled. The created event is manual reset: it must be reset -explicitly by calling os_event_reset(). -@return the event handle */ -os_event_t os_event_create(const char*); - -/** -Sets an event semaphore to the signaled state: lets waiting threads -proceed. */ -void -os_event_set( -/*=========*/ - os_event_t event); /*!< in/out: event to set */ - -/** -Check if the event is set. -@return true if set */ -bool -os_event_is_set( -/*============*/ - const os_event_t event); /*!< in: event to set */ - -/** -Resets an event semaphore to the nonsignaled state. Waiting threads will -stop to wait for the event. -The return value should be passed to os_even_wait_low() if it is desired -that this thread should not wait in case of an intervening call to -os_event_set() between this os_event_reset() and the -os_event_wait_low() call. See comments for os_event_wait_low(). */ -int64_t -os_event_reset( -/*===========*/ - os_event_t event); /*!< in/out: event to reset */ - -/** -Frees an event object. */ -void -os_event_destroy( -/*=============*/ - os_event_t& event); /*!< in/own: event to free */ - -/** -Waits for an event object until it is in the signaled state. - -Typically, if the event has been signalled after the os_event_reset() -we'll return immediately because event->is_set == TRUE. -There are, however, situations (e.g.: sync_array code) where we may -lose this information. For example: - -thread A calls os_event_reset() -thread B calls os_event_set() [event->is_set == TRUE] -thread C calls os_event_reset() [event->is_set == FALSE] -thread A calls os_event_wait() [infinite wait!] -thread C calls os_event_wait() [infinite wait!] - -Where such a scenario is possible, to avoid infinite wait, the -value returned by os_event_reset() should be passed in as -reset_sig_count. */ -void -os_event_wait_low( -/*==============*/ - os_event_t event, /*!< in/out: event to wait */ - int64_t reset_sig_count);/*!< in: zero or the value - returned by previous call of - os_event_reset(). */ - -/** Blocking infinite wait on an event, until signealled. -@param e - event to wait on. */ -#define os_event_wait(e) os_event_wait_low((e), 0) - -/** -Waits for an event object until it is in the signaled state or -a timeout is exceeded. In Unix the timeout is always infinite. -@return 0 if success, OS_SYNC_TIME_EXCEEDED if timeout was exceeded */ -ulint -os_event_wait_time_low( -/*===================*/ - os_event_t event, /*!< in/out: event to wait */ - ulint time_in_usec, /*!< in: timeout in - microseconds, or - OS_SYNC_INFINITE_TIME */ - int64_t reset_sig_count); /*!< in: zero or the value - returned by previous call of - os_event_reset(). */ - -/** Blocking timed wait on an event. -@param e - event to wait on. -@param t - timeout in microseconds */ -#define os_event_wait_time(e, t) os_event_wait_time_low((e), (t), 0) - -#endif /* !os0event_h */ diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index 8554a48018f..5aedd122a0f 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -45,6 +45,7 @@ Created 10/10/1995 Heikki Tuuri #include "que0types.h" #include "trx0types.h" #include "fil0fil.h" +#include "ut0counter.h" #include "mysql/psi/mysql_stage.h" #include "mysql/psi/psi.h" @@ -184,7 +185,7 @@ struct srv_stats_t }; /** We are prepared for a situation that we have this many threads waiting for -a semaphore inside InnoDB. srv_start() sets the value. */ +a transactional lock inside InnoDB. srv_start() sets the value. */ extern ulint srv_max_n_threads; extern const char* srv_main_thread_op_info; diff --git a/storage/innobase/include/sync0arr.h b/storage/innobase/include/sync0arr.h deleted file mode 100644 index 48ee967aa3e..00000000000 --- a/storage/innobase/include/sync0arr.h +++ /dev/null @@ -1,127 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 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/sync0arr.h -The wait array used in synchronization primitives - -Created 9/5/1995 Heikki Tuuri -*******************************************************/ - -#ifndef sync0arr_h -#define sync0arr_h - -#include "univ.i" - -/** Synchronization wait array cell */ -struct sync_cell_t; - -/** Synchronization wait array */ -struct sync_array_t; - -/******************************************************************//** -Get an instance of the sync wait array and reserve a wait array cell -in the instance for waiting for an object. The event of the cell is -reset to nonsignalled state. -If reserving cell of the instance fails, try to get another new -instance until we can reserve an empty cell of it. -@return the sync array found, never NULL. */ -UNIV_INLINE -sync_array_t* -sync_array_get_and_reserve_cell( - void* object, /*!< in: pointer to the object to wait for */ - const char* file, /*!< in: file where requested */ - unsigned line, /*!< in: line where requested */ - sync_cell_t** cell); /*!< out: the cell reserved, never NULL */ -/******************************************************************//** -Reserves a wait array cell for waiting for an object. -The event of the cell is reset to nonsignalled state. */ -sync_cell_t* -sync_array_reserve_cell( - sync_array_t* arr, /*!< in: wait array */ - void* object, /*!< in: pointer to the object to wait for */ - const char* file, /*!< in: file where requested */ - unsigned line); /*!< in: line where requested */ - -/******************************************************************//** -This function should be called when a thread starts to wait on -a wait array cell. In the debug version this function checks -if the wait for a semaphore will result in a deadlock, in which -case prints info and asserts. */ -void -sync_array_wait_event( - sync_array_t* arr, /*!< in: wait array */ - sync_cell_t*& cell); /*!< in: the reserved cell */ - -/******************************************************************//** -Frees the cell. NOTE! sync_array_wait_event frees the cell -automatically! */ -void -sync_array_free_cell( - sync_array_t* arr, /*!< in: wait array */ - sync_cell_t*& cell); /*!< in: the reserved cell */ - -/** count of how many times an object has been signalled */ -extern ulint sg_count; -#define sync_array_object_signalled() ++sg_count - -/**********************************************************************//** -Prints warnings of long semaphore waits to stderr. -@return TRUE if fatal semaphore wait threshold was exceeded */ -ibool -sync_array_print_long_waits( - os_thread_id_t* waiter, /*!< out: longest waiting thread */ - const void** sema); /*!< out: longest-waited-for semaphore */ - -/**********************************************************************//** -Prints info of the wait array. */ -void -sync_array_print( - FILE* file); /*!< in: file where to print */ - -/** Create the primary system wait arrays */ -void sync_array_init(); - -/** Destroy the sync array wait sub-system. */ -void sync_array_close(); - -/**********************************************************************//** -Get an instance of the sync wait array. */ -UNIV_INLINE -sync_array_t* -sync_array_get(); -/**********************************************************************//** -Prints info of the wait array without using any mutexes/semaphores. */ -UNIV_INTERN -void -sync_array_print_innodb(void); - -/*****************************************************************//** -Gets the nth cell in array. -@return cell */ -UNIV_INTERN -sync_cell_t* -sync_array_get_nth_cell( -/*====================*/ - sync_array_t* arr, /*!< in: sync array */ - ulint n); /*!< in: index */ - -#include "sync0arr.ic" - -#endif /* sync0arr_h */ diff --git a/storage/innobase/include/sync0arr.ic b/storage/innobase/include/sync0arr.ic deleted file mode 100644 index 503206b7170..00000000000 --- a/storage/innobase/include/sync0arr.ic +++ /dev/null @@ -1,82 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1995, 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/sync0arr.ic -The wait array for synchronization primitives - -Inline code - -Created 9/5/1995 Heikki Tuuri -*******************************************************/ - -extern ulint sync_array_size; -extern sync_array_t** sync_wait_array; - -#include "ut0counter.h" - -/**********************************************************************//** -Get an instance of the sync wait array. -@return an instance of the sync wait array. */ - -UNIV_INLINE -sync_array_t* -sync_array_get() -/*============*/ -{ - if (sync_array_size <= 1) { - return(sync_wait_array[0]); - } - - return(sync_wait_array[get_rnd_value() % sync_array_size]); -} - -/******************************************************************//** -Get an instance of the sync wait array and reserve a wait array cell -in the instance for waiting for an object. The event of the cell is -reset to nonsignalled state. -If reserving cell of the instance fails, try to get another new -instance until we can reserve an empty cell of it. -@return the sync array reserved, never NULL. */ -UNIV_INLINE -sync_array_t* -sync_array_get_and_reserve_cell( - void* object, /*!< in: pointer to the object to wait for */ - const char* file, /*!< in: file where requested */ - unsigned line, /*!< in: line where requested */ - sync_cell_t** cell) /*!< out: the cell reserved, never NULL */ -{ - sync_array_t* sync_arr = NULL; - - *cell = NULL; - for (ulint i = 0; i < sync_array_size && *cell == NULL; ++i) { - /* Although the sync_array is get in a random way currently, - we still try at most sync_array_size times, in case any - of the sync_array we get is full */ - sync_arr = sync_array_get(); - *cell = sync_array_reserve_cell(sync_arr, object, file, line); - } - - /* This won't be true every time, for the loop above may execute - more than srv_sync_array_size times to reserve a cell. - But an assertion here makes the code more solid. */ - ut_a(*cell != NULL); - - return(sync_arr); -} diff --git a/storage/innobase/include/sync0types.h b/storage/innobase/include/sync0types.h index 20dc9494c20..f8df704c9d9 100644 --- a/storage/innobase/include/sync0types.h +++ b/storage/innobase/include/sync0types.h @@ -178,8 +178,6 @@ LatchDebug internals in sync0debug.cc */ enum latch_level_t { SYNC_UNKNOWN = 0, - SYNC_MUTEX = 1, - RW_LOCK_SX, RW_LOCK_X_WAIT, RW_LOCK_S, diff --git a/storage/innobase/include/ut0mutex.h b/storage/innobase/include/ut0mutex.h index cb43583c21d..89c903b48f1 100644 --- a/storage/innobase/include/ut0mutex.h +++ b/storage/innobase/include/ut0mutex.h @@ -41,7 +41,6 @@ UT_MUTEX_TYPE(TTASFutexMutex, GenericPolicy, FutexMutex); UT_MUTEX_TYPE(TTASMutex, GenericPolicy, SpinMutex); UT_MUTEX_TYPE(OSTrackMutex, GenericPolicy, SysMutex); -UT_MUTEX_TYPE(TTASEventMutex, GenericPolicy, SyncArrayMutex); #ifdef MUTEX_FUTEX /** The default mutex type. */ @@ -50,9 +49,6 @@ typedef FutexMutex ib_mutex_t; #elif defined(MUTEX_SYS) typedef SysMutex ib_mutex_t; #define MUTEX_TYPE "Uses system mutexes" -#elif defined(MUTEX_EVENT) -typedef SyncArrayMutex ib_mutex_t; -#define MUTEX_TYPE "Uses event mutexes" #else #error "ib_mutex_t type is unknown" #endif /* MUTEX_FUTEX */ diff --git a/storage/innobase/include/ut0new.h b/storage/innobase/include/ut0new.h index 57c94a57020..3fc7664c34e 100644 --- a/storage/innobase/include/ut0new.h +++ b/storage/innobase/include/ut0new.h @@ -868,7 +868,6 @@ constexpr const char* const auto_event_names[] = "lexyy", "lock0lock", "mem0mem", - "os0event", "os0file", "pars0lex", "rem0rec", @@ -879,7 +878,6 @@ constexpr const char* const auto_event_names[] = "row0mysql", "row0sel", "srv0start", - "sync0arr", "sync0debug", "sync0start", "sync0types", diff --git a/storage/innobase/innodb.cmake b/storage/innobase/innodb.cmake index 385e87f828e..83232a4d66c 100644 --- a/storage/innobase/innodb.cmake +++ b/storage/innobase/innodb.cmake @@ -137,11 +137,9 @@ IF(HAVE_C99_INITIALIZERS) ADD_DEFINITIONS(-DHAVE_C99_INITIALIZERS) ENDIF() -SET(MUTEXTYPE "event" CACHE STRING "Mutex type: event, sys or futex") +SET(MUTEXTYPE "sys" CACHE STRING "Mutex type: sys or futex") -IF(MUTEXTYPE MATCHES "event") - ADD_DEFINITIONS(-DMUTEX_EVENT) -ELSEIF(MUTEXTYPE MATCHES "futex" AND CMAKE_SYSTEM_NAME STREQUAL "Linux") +IF(MUTEXTYPE MATCHES "futex" AND DEFINED HAVE_IB_LINUX_FUTEX) ADD_DEFINITIONS(-DMUTEX_FUTEX) ELSE() ADD_DEFINITIONS(-DMUTEX_SYS) diff --git a/storage/innobase/os/os0event.cc b/storage/innobase/os/os0event.cc deleted file mode 100644 index f18633ccd45..00000000000 --- a/storage/innobase/os/os0event.cc +++ /dev/null @@ -1,515 +0,0 @@ -/***************************************************************************** - -Copyright (c) 2013, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2019, 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 os/os0event.cc -The interface to the operating system condition variables. - -Created 2012-09-23 Sunny Bains -*******************************************************/ - -#include "os0event.h" -#include "ut0mutex.h" -#include <my_sys.h> - -#ifdef _WIN32 -#include <windows.h> -#include <synchapi.h> -/** Native condition variable. */ -typedef CONDITION_VARIABLE os_cond_t; -#else -/** Native condition variable */ -typedef pthread_cond_t os_cond_t; -#endif /* _WIN32 */ - -/** InnoDB condition variable. */ -struct os_event { - os_event() UNIV_NOTHROW; - - ~os_event() UNIV_NOTHROW; - - /** - Destroys a condition variable */ - void destroy() UNIV_NOTHROW - { -#ifndef _WIN32 - int ret = pthread_cond_destroy(&cond_var); - ut_a(ret == 0); -#endif /* !_WIN32 */ - - mutex.destroy(); - } - - /** Set the event */ - void set() UNIV_NOTHROW - { - mutex.enter(); - - if (!m_set) { - broadcast(); - } - - mutex.exit(); - } - - int64_t reset() UNIV_NOTHROW - { - mutex.enter(); - - if (m_set) { - m_set = false; - } - - int64_t ret = signal_count; - - mutex.exit(); - - return(ret); - } - - /** - Waits for an event object until it is in the signaled state. - - Typically, if the event has been signalled after the os_event_reset() - we'll return immediately because event->m_set == true. - There are, however, situations (e.g.: sync_array code) where we may - lose this information. For example: - - thread A calls os_event_reset() - thread B calls os_event_set() [event->m_set == true] - thread C calls os_event_reset() [event->m_set == false] - thread A calls os_event_wait() [infinite wait!] - thread C calls os_event_wait() [infinite wait!] - - Where such a scenario is possible, to avoid infinite wait, the - value returned by reset() should be passed in as - reset_sig_count. */ - void wait_low(int64_t reset_sig_count) UNIV_NOTHROW; - - /** - Waits for an event object until it is in the signaled state or - a timeout is exceeded. - @param time_in_usec - timeout in microseconds, - or OS_SYNC_INFINITE_TIME - @param reset_sig_count- zero or the value returned by - previous call of os_event_reset(). - @return 0 if success, OS_SYNC_TIME_EXCEEDED if timeout was exceeded */ - ulint wait_time_low( - ulint time_in_usec, - int64_t reset_sig_count) UNIV_NOTHROW; - - /** @return true if the event is in the signalled state. */ - bool is_set() const UNIV_NOTHROW - { - mutex.enter(); - bool is_set = m_set; - mutex.exit(); - return is_set; - } - -private: - /** - Initialize a condition variable */ - void init() UNIV_NOTHROW - { - - mutex.init(); - -#ifdef _WIN32 - InitializeConditionVariable(&cond_var); -#else - { - int ret; - - ret = pthread_cond_init(&cond_var, NULL); - ut_a(ret == 0); - } -#endif /* _WIN32 */ - } - - /** - Wait on condition variable */ - void wait() UNIV_NOTHROW - { -#ifdef _WIN32 - if (!SleepConditionVariableCS(&cond_var, mutex, INFINITE)) { - ut_error; - } -#else - { - int ret; - - ret = pthread_cond_wait(&cond_var, mutex); - ut_a(ret == 0); - } -#endif /* _WIN32 */ - } - - /** - Wakes all threads waiting for condition variable */ - void broadcast() UNIV_NOTHROW - { - m_set = true; - ++signal_count; - -#ifdef _WIN32 - WakeAllConditionVariable(&cond_var); -#else - { - int ret; - - ret = pthread_cond_broadcast(&cond_var); - ut_a(ret == 0); - } -#endif /* _WIN32 */ - } - - /** - Wakes one thread waiting for condition variable */ - void signal() UNIV_NOTHROW - { -#ifdef _WIN32 - WakeConditionVariable(&cond_var); -#else - { - int ret; - - ret = pthread_cond_signal(&cond_var); - ut_a(ret == 0); - } -#endif /* _WIN32 */ - } - - /** - Do a timed wait on condition variable. - @param abstime - timeout - @param time_in_ms - timeout in milliseconds. - @return true if timed out, false otherwise */ - bool timed_wait( -#ifndef _WIN32 - const timespec* abstime -#else - DWORD time_in_ms -#endif /* !_WIN32 */ - ); - -private: - bool m_set; /*!< this is true when the - event is in the signaled - state, i.e., a thread does - not stop if it tries to wait - for this event */ - int64_t signal_count; /*!< this is incremented - each time the event becomes - signaled */ - mutable OSMutex mutex; /*!< this mutex protects - the next fields */ - - - os_cond_t cond_var; /*!< condition variable is - used in waiting for the event */ - -protected: - // Disable copying - os_event(const os_event&); - os_event& operator=(const os_event&); -}; - -/** -Do a timed wait on condition variable. -@param abstime - absolute time to wait -@param time_in_ms - timeout in milliseconds -@return true if timed out */ -bool -os_event::timed_wait( -#ifndef _WIN32 - const timespec* abstime -#else - DWORD time_in_ms -#endif /* !_WIN32 */ -) -{ -#ifdef _WIN32 - BOOL ret; - - ret = SleepConditionVariableCS(&cond_var, mutex, time_in_ms); - - if (!ret) { - DWORD err = GetLastError(); - - /* FQDN=msdn.microsoft.com - @see http://$FQDN/en-us/library/ms686301%28VS.85%29.aspx, - - "Condition variables are subject to spurious wakeups - (those not associated with an explicit wake) and stolen wakeups - (another thread manages to run before the woken thread)." - Check for both types of timeouts. - Conditions are checked by the caller.*/ - if (err == WAIT_TIMEOUT || err == ERROR_TIMEOUT) { - return(true); - } - } - - ut_a(ret); - - return(false); -#else - int ret; - - ret = pthread_cond_timedwait(&cond_var, mutex, abstime); - - switch (ret) { - case 0: - case ETIMEDOUT: - /* We play it safe by checking for EINTR even though - according to the POSIX documentation it can't return EINTR. */ - case EINTR: - break; - - default: - ib::error() << "pthread_cond_timedwait() returned: " << ret - << ": abstime={" << abstime->tv_sec << "," - << abstime->tv_nsec << "}"; - ut_error; - } - - return(ret == ETIMEDOUT); -#endif /* _WIN32 */ -} - -/** -Waits for an event object until it is in the signaled state. - -Typically, if the event has been signalled after the os_event_reset() -we'll return immediately because event->m_set == true. -There are, however, situations (e.g.: sync_array code) where we may -lose this information. For example: - -thread A calls os_event_reset() -thread B calls os_event_set() [event->m_set == true] -thread C calls os_event_reset() [event->m_set == false] -thread A calls os_event_wait() [infinite wait!] -thread C calls os_event_wait() [infinite wait!] - -Where such a scenario is possible, to avoid infinite wait, the -value returned by reset() should be passed in as -reset_sig_count. */ -void -os_event::wait_low( - int64_t reset_sig_count) UNIV_NOTHROW -{ - mutex.enter(); - - if (!reset_sig_count) { - reset_sig_count = signal_count; - } - - while (!m_set && signal_count == reset_sig_count) { - - wait(); - - /* Spurious wakeups may occur: we have to check if the - event really has been signaled after we came here to wait. */ - } - - mutex.exit(); -} - -/** -Waits for an event object until it is in the signaled state or -a timeout is exceeded. -@param time_in_usec - timeout in microseconds, or OS_SYNC_INFINITE_TIME -@param reset_sig_count - zero or the value returned by previous call - of os_event_reset(). -@return 0 if success, OS_SYNC_TIME_EXCEEDED if timeout was exceeded */ -ulint -os_event::wait_time_low( - ulint time_in_usec, - int64_t reset_sig_count) UNIV_NOTHROW -{ - bool timed_out = false; - -#ifdef _WIN32 - DWORD time_in_ms; - - if (time_in_usec != OS_SYNC_INFINITE_TIME) { - time_in_ms = DWORD(time_in_usec / 1000); - } else { - time_in_ms = INFINITE; - } -#else - struct timespec abstime; - - if (time_in_usec != OS_SYNC_INFINITE_TIME) { - ulonglong usec = ulonglong(time_in_usec) + my_hrtime().val; - abstime.tv_sec = static_cast<time_t>(usec / 1000000); - abstime.tv_nsec = static_cast<uint>((usec % 1000000) * 1000); - } else { - abstime.tv_nsec = 999999999; - abstime.tv_sec = (time_t) ULINT_MAX; - } - - ut_a(abstime.tv_nsec <= 999999999); - -#endif /* _WIN32 */ - - mutex.enter(); - - if (!reset_sig_count) { - reset_sig_count = signal_count; - } - - do { - if (m_set || signal_count != reset_sig_count) { - - break; - } - -#ifndef _WIN32 - timed_out = timed_wait(&abstime); -#else - timed_out = timed_wait(time_in_ms); -#endif /* !_WIN32 */ - - } while (!timed_out); - - mutex.exit(); - - return(timed_out ? OS_SYNC_TIME_EXCEEDED : 0); -} - -/** Constructor */ -os_event::os_event() UNIV_NOTHROW -{ - init(); - - m_set = false; - - /* We return this value in os_event_reset(), - which can then be be used to pass to the - os_event_wait_low(). The value of zero is - reserved in os_event_wait_low() for the case - when the caller does not want to pass any - signal_count value. To distinguish between - the two cases we initialize signal_count - to 1 here. */ - - signal_count = 1; -} - -/** Destructor */ -os_event::~os_event() UNIV_NOTHROW -{ - destroy(); -} - -/** -Creates an event semaphore, i.e., a semaphore which may just have two -states: signaled and nonsignaled. The created event is manual reset: it -must be reset explicitly by calling sync_os_reset_event. -@return the event handle */ -os_event_t os_event_create(const char*) -{ - return(UT_NEW_NOKEY(os_event())); -} - -/** -Check if the event is set. -@return true if set */ -bool -os_event_is_set( -/*============*/ - const os_event_t event) /*!< in: event to test */ -{ - return(event->is_set()); -} - -/** -Sets an event semaphore to the signaled state: lets waiting threads -proceed. */ -void -os_event_set( -/*=========*/ - os_event_t event) /*!< in/out: event to set */ -{ - event->set(); -} - -/** -Resets an event semaphore to the nonsignaled state. Waiting threads will -stop to wait for the event. -The return value should be passed to os_even_wait_low() if it is desired -that this thread should not wait in case of an intervening call to -os_event_set() between this os_event_reset() and the -os_event_wait_low() call. See comments for os_event_wait_low(). -@return current signal_count. */ -int64_t -os_event_reset( -/*===========*/ - os_event_t event) /*!< in/out: event to reset */ -{ - return(event->reset()); -} - -/** -Waits for an event object until it is in the signaled state or -a timeout is exceeded. -@return 0 if success, OS_SYNC_TIME_EXCEEDED if timeout was exceeded */ -ulint -os_event_wait_time_low( -/*===================*/ - os_event_t event, /*!< in/out: event to wait */ - ulint time_in_usec, /*!< in: timeout in - microseconds, or - OS_SYNC_INFINITE_TIME */ - int64_t reset_sig_count) /*!< in: zero or the value - returned by previous call of - os_event_reset(). */ -{ - return(event->wait_time_low(time_in_usec, reset_sig_count)); -} - -/** -Waits for an event object until it is in the signaled state. - -Where such a scenario is possible, to avoid infinite wait, the -value returned by os_event_reset() should be passed in as -reset_sig_count. */ -void -os_event_wait_low( -/*==============*/ - os_event_t event, /*!< in: event to wait */ - int64_t reset_sig_count) /*!< in: zero or the value - returned by previous call of - os_event_reset(). */ -{ - event->wait_low(reset_sig_count); -} - -/** -Frees an event object. */ -void -os_event_destroy( -/*=============*/ - os_event_t& event) /*!< in/own: event to free */ - -{ - UT_DELETE(event); - event = NULL; -} diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index d176a69bee6..bb9b62dcde1 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -838,11 +838,11 @@ srv_printf_innodb_monitor( "-----------------\n", file); srv_print_master_thread_info(file); + /* This section is intentionally left blank, for tools like "innotop" */ fputs("----------\n" "SEMAPHORES\n" "----------\n", file); - - sync_array_print(file); + /* 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 @@ -1347,21 +1347,11 @@ static void srv_monitor() srv_refresh_innodb_monitor_stats(current_time); } -/*********************************************************************//** -A task which prints warnings about semaphore waits which have lasted -too long. These can be used to track bugs which cause hangs. -*/ +/** Periodic task which prints the info output by various InnoDB monitors.*/ void srv_monitor_task(void*) { /* number of successive fatal timeouts observed */ - static ulint fatal_cnt; static lsn_t old_lsn = recv_sys.recovered_lsn; - /* longest waiting thread for a semaphore */ - os_thread_id_t waiter; - static os_thread_id_t old_waiter = os_thread_get_curr_id(); - /* the semaphore that is being waited for */ - const void* sema = NULL; - static const void* old_sema = NULL; ut_ad(!srv_read_only_mode); @@ -1383,31 +1373,6 @@ void srv_monitor_task(void*) eviction policy. */ buf_LRU_stat_update(); - if (sync_array_print_long_waits(&waiter, &sema) - && sema == old_sema && os_thread_eq(waiter, old_waiter)) { -#if defined(WITH_WSREP) && defined(WITH_INNODB_DISALLOW_WRITES) - if (UNIV_UNLIKELY(innodb_disallow_writes)) { - fprintf(stderr, - "WSREP: avoiding InnoDB self crash due to " - "long semaphore wait of > %lu seconds\n" - "Server is processing SST donor operation, " - "fatal_cnt now: " ULINTPF, - srv_fatal_semaphore_wait_threshold, fatal_cnt); - return; - } -#endif /* WITH_WSREP */ - if (fatal_cnt++) { - ib::fatal() << "Semaphore wait has lasted > " - << srv_fatal_semaphore_wait_threshold - << " seconds. We intentionally crash the" - " server because it appears to be hung."; - } - } else { - fatal_cnt = 0; - old_waiter = waiter; - old_sema = sema; - } - srv_monitor(); } diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index fa9484d8545..b8a1a4e2cfc 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -100,7 +100,7 @@ Created 2/16/1996 Heikki Tuuri #include "ut0crc32.h" /** We are prepared for a situation that we have this many threads waiting for -a semaphore inside InnoDB. srv_start() sets the value. */ +a transactional lock inside InnoDB. srv_start() sets the value. */ ulint srv_max_n_threads; /** Log sequence number at shutdown */ @@ -1109,27 +1109,11 @@ dberr_t srv_start(bool create_new_db) mysql_stage_register("innodb", srv_stages, static_cast<int>(UT_ARR_SIZE(srv_stages))); - /* Set the maximum number of threads which can wait for a semaphore - inside InnoDB: this is the 'sync wait array' size */ - - srv_max_n_threads = 1 /* io_ibuf_thread */ - + 1 /* io_log_thread */ - + 1 /* srv_print_monitor_task */ - + 1 /* srv_purge_coordinator_thread */ - + 1 /* buf_dump_thread */ - + 1 /* dict_stats_thread */ - + 1 /* fts_optimize_thread */ - + 1 /* trx_rollback_all_recovered */ - + 128 /* added as margin, for use of - InnoDB Memcached etc. */ - + 1/* buf_flush_page_cleaner */ - + max_connections - + srv_n_read_io_threads - + srv_n_write_io_threads - + srv_n_purge_threads - /* FTS Parallel Sort */ - + fts_sort_pll_degree * FTS_NUM_AUX_INDEX - * max_connections; + srv_max_n_threads = + 1 /* dict_stats_thread */ + + 1 /* fts_optimize_thread */ + + 128 /* safety margin */ + + max_connections; srv_boot(); diff --git a/storage/innobase/sync/sync0arr.cc b/storage/innobase/sync/sync0arr.cc deleted file mode 100644 index c8c5e5280f2..00000000000 --- a/storage/innobase/sync/sync0arr.cc +++ /dev/null @@ -1,960 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2008, Google Inc. -Copyright (c) 2013, 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/sync0arr.cc -The wait array used in synchronization primitives - -Created 9/5/1995 Heikki Tuuri -*******************************************************/ - -#include "sync0arr.h" -#include <mysqld_error.h> -#include <mysql/plugin.h> -#include <hash.h> -#include <myisampack.h> -#include <sql_acl.h> -#include <mysys_err.h> -#include <my_sys.h> -#include "srv0srv.h" -#include "srv0start.h" -#include "i_s.h" -#include <sql_plugin.h> -#include <innodb_priv.h> - -#include "lock0lock.h" - -/* - WAIT ARRAY - ========== - -The wait array consists of cells each of which has an an event object created -for it. The threads waiting for a mutex, for example, can reserve a cell -in the array and suspend themselves to wait for the event to become signaled. -When using the wait array, remember to make sure that some thread holding -the synchronization object will eventually know that there is a waiter in -the array and signal the object, to prevent infinite wait. Why we chose -to implement a wait array? First, to make mutexes fast, we had to code -our own implementation of them, which only in usually uncommon cases -resorts to using slow operating system primitives. Then we had the choice of -assigning a unique OS event for each mutex, which would be simpler, or -using a global wait array. In some operating systems, the global wait -array solution is more efficient and flexible, because we can do with -a very small number of OS events, say 200. In NT 3.51, allocating events -seems to be a quadratic algorithm, because 10 000 events are created fast, -but 100 000 events takes a couple of minutes to create. - -As of 5.0.30 the above mentioned design is changed. Since now OS can handle -millions of wait events efficiently, we no longer have this concept of each -cell of wait array having one event. Instead, now the event that a thread -wants to wait on is embedded in the wait object (mutex or rw_lock). We still -keep the global wait array for the sake of diagnostics and also to avoid -infinite wait The error_monitor thread scans the global wait array to signal -any waiting threads who have missed the signal. */ - -typedef TTASEventMutex<GenericPolicy> WaitMutex; - -/** A cell where an individual thread may wait suspended until a resource -is released. The suspending is implemented using an operating system -event semaphore. */ - -struct sync_cell_t { - WaitMutex* mutex; /*!< pointer to the object the - thread is waiting for; if NULL - the cell is free for use */ - const char* file; /*!< in debug version file where - requested */ - ulint line; /*!< in debug version line where - requested, or ULINT_UNDEFINED */ - os_thread_id_t thread_id; /*!< thread id of this waiting - thread */ - bool waiting; /*!< TRUE if the thread has already - called sync_array_event_wait - on this cell */ - int64_t signal_count; /*!< We capture the signal_count - of the mutex when we - reset the event. This value is - then passed on to os_event_wait - and we wait only if the event - has not been signalled in the - period between the reset and - wait call. */ - /** time(NULL) when the wait cell was reserved. - FIXME: sync_array_print_long_waits_low() may display bogus - warnings when the system time is adjusted to the past! */ - time_t reservation_time; -}; - -/* NOTE: It is allowed for a thread to wait for an event allocated for -the array without owning the protecting mutex (depending on the case: -OS or database mutex), but all changes (set or reset) to the state of -the event must be made while owning the mutex. */ - -/** Synchronization array */ -struct sync_array_t { - - /** Constructor - Creates a synchronization wait array. It is protected by a mutex - which is automatically reserved when the functions operating on it - are called. - @param[in] num_cells Number of cells to create */ - sync_array_t(ulint num_cells) - UNIV_NOTHROW; - - /** Destructor */ - ~sync_array_t() - UNIV_NOTHROW; - - ulint n_reserved; /*!< number of currently reserved - cells in the wait array */ - ulint n_cells; /*!< number of cells in the - wait array */ - sync_cell_t* array; /*!< pointer to wait array */ - SysMutex mutex; /*!< System mutex protecting the - data structure. As this data - structure is used in constructing - the database mutex, to prevent - infinite recursion in implementation, - we fall back to an OS mutex. */ - ulint res_count; /*!< count of cell reservations - since creation of the array */ - ulint next_free_slot; /*!< the next free cell in the array */ - ulint first_free_slot;/*!< the last slot that was freed */ -}; - -/** User configured sync array size */ -ulong srv_sync_array_size = 1; - -/** Locally stored copy of srv_sync_array_size */ -ulint sync_array_size; - -/** The global array of wait cells for implementation of the database's own -mutexes and read-write locks */ -sync_array_t** sync_wait_array; - -/** count of how many times an object has been signalled */ -ulint sg_count; - -#define sync_array_exit(a) mutex_exit(&(a)->mutex) -#define sync_array_enter(a) mutex_enter(&(a)->mutex) - -#ifdef UNIV_DEBUG -/******************************************************************//** -This function is called only in the debug version. Detects a deadlock -of one or more threads because of waits of semaphores. -@return TRUE if deadlock detected */ -static -bool -sync_array_detect_deadlock( -/*=======================*/ - sync_array_t* arr, /*!< in: wait array; NOTE! the caller must - own the mutex to array */ - sync_cell_t* start, /*!< in: cell where recursive search started */ - sync_cell_t* cell, /*!< in: cell to search */ - ulint depth); /*!< in: recursion depth */ -#endif /* UNIV_DEBUG */ - -/** Constructor -Creates a synchronization wait array. It is protected by a mutex -which is automatically reserved when the functions operating on it -are called. -@param[in] num_cells Number of cells to create */ -sync_array_t::sync_array_t(ulint num_cells) - UNIV_NOTHROW - : - n_reserved(), - n_cells(num_cells), - array(UT_NEW_ARRAY_NOKEY(sync_cell_t, num_cells)), - mutex(), - res_count(), - next_free_slot(), - first_free_slot(ULINT_UNDEFINED) -{ - ut_a(num_cells > 0); - - memset(array, 0x0, sizeof(sync_cell_t) * n_cells); - - /* Then create the mutex to protect the wait array */ - mutex_create(LATCH_ID_SYNC_ARRAY_MUTEX, &mutex); -} - -/** Validate the integrity of the wait array. Check -that the number of reserved cells equals the count variable. -@param[in,out] arr sync wait array */ -static -void -sync_array_validate(sync_array_t* arr) -{ - ulint i; - ulint count = 0; - - sync_array_enter(arr); - - for (i = 0; i < arr->n_cells; i++) { - sync_cell_t* cell; - - cell = sync_array_get_nth_cell(arr, i); - - if (cell->mutex) { - count++; - } - } - - ut_a(count == arr->n_reserved); - - sync_array_exit(arr); -} - -/** Destructor */ -sync_array_t::~sync_array_t() - UNIV_NOTHROW -{ - ut_a(n_reserved == 0); - - sync_array_validate(this); - - /* Release the mutex protecting the wait array */ - - mutex_free(&mutex); - - UT_DELETE_ARRAY(array); -} - -/*****************************************************************//** -Gets the nth cell in array. -@return cell */ -UNIV_INTERN -sync_cell_t* -sync_array_get_nth_cell( -/*====================*/ - sync_array_t* arr, /*!< in: sync array */ - ulint n) /*!< in: index */ -{ - ut_a(n < arr->n_cells); - - return(arr->array + n); -} - -/******************************************************************//** -Frees the resources in a wait array. */ -static -void -sync_array_free( -/*============*/ - sync_array_t* arr) /*!< in, own: sync wait array */ -{ - UT_DELETE(arr); -} - -/******************************************************************//** -Reserves a wait array cell for waiting for an object. -The event of the cell is reset to nonsignalled state. -@return sync cell to wait on */ -sync_cell_t* -sync_array_reserve_cell( - sync_array_t* arr, /*!< in: wait array */ - void* object, /*!< in: pointer to the object to wait for */ - const char* file, /*!< in: file where requested */ - unsigned line) /*!< in: line where requested */ -{ - sync_cell_t* cell; - - sync_array_enter(arr); - - if (arr->first_free_slot != ULINT_UNDEFINED) { - /* Try and find a slot in the free list */ - ut_ad(arr->first_free_slot < arr->next_free_slot); - cell = sync_array_get_nth_cell(arr, arr->first_free_slot); - arr->first_free_slot = cell->line; - } else if (arr->next_free_slot < arr->n_cells) { - /* Try and find a slot after the currently allocated slots */ - cell = sync_array_get_nth_cell(arr, arr->next_free_slot); - ++arr->next_free_slot; - } else { - sync_array_exit(arr); - - // We should return NULL and if there is more than - // one sync array, try another sync array instance. - return(NULL); - } - - ++arr->res_count; - - ut_ad(arr->n_reserved < arr->n_cells); - ut_ad(arr->next_free_slot <= arr->n_cells); - - ++arr->n_reserved; - - /* Reserve the cell. */ - ut_ad(!cell->mutex); - - cell->mutex = static_cast<WaitMutex*>(object); - - cell->waiting = false; - - cell->file = file; - cell->line = line; - - sync_array_exit(arr); - - cell->thread_id = os_thread_get_curr_id(); - - cell->reservation_time = time(NULL); - - /* Make sure the event is reset and also store the value of - signal_count at which the event was reset. */ - cell->signal_count = os_event_reset(cell->mutex->event()); - - return(cell); -} - -/******************************************************************//** -Frees the cell. NOTE! sync_array_wait_event frees the cell -automatically! */ -void -sync_array_free_cell( -/*=================*/ - sync_array_t* arr, /*!< in: wait array */ - sync_cell_t*& cell) /*!< in/out: the cell in the array */ -{ - sync_array_enter(arr); - - ut_a(cell->mutex); - - cell->waiting = false; - cell->signal_count = 0; - cell->mutex = NULL; - - /* Setup the list of free slots in the array */ - cell->line = arr->first_free_slot; - - arr->first_free_slot = cell - arr->array; - - ut_a(arr->n_reserved > 0); - arr->n_reserved--; - - if (arr->next_free_slot > arr->n_cells / 2 && arr->n_reserved == 0) { -#ifdef UNIV_DEBUG - for (ulint i = 0; i < arr->next_free_slot; ++i) { - cell = sync_array_get_nth_cell(arr, i); - - ut_ad(!cell->waiting); - ut_ad(!cell->mutex); - ut_ad(cell->signal_count == 0); - } -#endif /* UNIV_DEBUG */ - arr->next_free_slot = 0; - arr->first_free_slot = ULINT_UNDEFINED; - } - sync_array_exit(arr); - - cell = 0; -} - -/******************************************************************//** -This function should be called when a thread starts to wait on -a wait array cell. In the debug version this function checks -if the wait for a semaphore will result in a deadlock, in which -case prints info and asserts. */ -void -sync_array_wait_event( -/*==================*/ - sync_array_t* arr, /*!< in: wait array */ - sync_cell_t*& cell) /*!< in: index of the reserved cell */ -{ - sync_array_enter(arr); - - ut_ad(!cell->waiting); - ut_ad(cell->mutex); - ut_ad(os_thread_get_curr_id() == cell->thread_id); - - cell->waiting = true; - -#ifdef UNIV_DEBUG - if (sync_array_detect_deadlock(arr, cell, cell, 0)) { - - ib::fatal() << "########################################" - " Deadlock Detected!"; - } -#endif /* UNIV_DEBUG */ - sync_array_exit(arr); - - tpool::tpool_wait_begin(); - - os_event_wait_low(cell->mutex->event(), cell->signal_count); - - tpool::tpool_wait_end(); - - sync_array_free_cell(arr, cell); - - cell = 0; -} - -/******************************************************************//** -Reports info of a wait array cell. */ -static -void -sync_array_cell_print( -/*==================*/ - FILE* file, /*!< in: file where to print */ - sync_cell_t* cell) /*!< in: sync cell */ -{ - fprintf(file, - "--Thread " ULINTPF " has waited at %s line " ULINTPF - " for %.2f seconds the semaphore:\n", - ulint(cell->thread_id), - innobase_basename(cell->file), cell->line, - difftime(time(NULL), cell->reservation_time)); - - WaitMutex* mutex = cell->mutex; - const WaitMutex::MutexPolicy& policy = mutex->policy(); -#ifdef UNIV_DEBUG - const char* name = policy.context.get_enter_filename(); - if (name == NULL) { - /* The mutex might have been released. */ - name = "NULL"; - } -#endif /* UNIV_DEBUG */ - - fprintf(file, - "Mutex at %p, %s, lock var %x\n" -#ifdef UNIV_DEBUG - "Last time reserved in file %s line %u" -#endif /* UNIV_DEBUG */ - "\n", - (void*) mutex, - policy.to_string().c_str(), - mutex->state() -#ifdef UNIV_DEBUG - ,name, policy.context.get_enter_line() -#endif /* UNIV_DEBUG */ - ); - - if (!cell->waiting) { - fputs("wait has ended\n", file); - } -} - -#ifdef UNIV_DEBUG -/******************************************************************//** -Looks for a cell with the given thread id. -@return pointer to cell or NULL if not found */ -static -sync_cell_t* -sync_array_find_thread( -/*===================*/ - sync_array_t* arr, /*!< in: wait array */ - os_thread_id_t thread) /*!< in: thread id */ -{ - ulint i; - - for (i = 0; i < arr->n_cells; i++) { - sync_cell_t* cell; - - cell = sync_array_get_nth_cell(arr, i); - - if (cell->mutex - && os_thread_eq(cell->thread_id, thread)) { - - return(cell); /* Found */ - } - } - - return(NULL); /* Not found */ -} - -/******************************************************************//** -Recursion step for deadlock detection. -@return TRUE if deadlock detected */ -static -ibool -sync_array_deadlock_step( -/*=====================*/ - sync_array_t* arr, /*!< in: wait array; NOTE! the caller must - own the mutex to array */ - sync_cell_t* start, /*!< in: cell where recursive search - started */ - os_thread_id_t thread, /*!< in: thread to look at */ - ulint pass, /*!< in: pass value */ - ulint depth) /*!< in: recursion depth */ -{ - sync_cell_t* new_cell; - - if (pass != 0) { - /* If pass != 0, then we do not know which threads are - responsible of releasing the lock, and no deadlock can - be detected. */ - - return(FALSE); - } - - new_cell = sync_array_find_thread(arr, thread); - - if (new_cell == start) { - /* Deadlock */ - fputs("########################################\n" - "DEADLOCK of threads detected!\n", stderr); - - return(TRUE); - - } else if (new_cell) { - return(sync_array_detect_deadlock( - arr, start, new_cell, depth + 1)); - } - return(FALSE); -} - -/******************************************************************//** -This function is called only in the debug version. Detects a deadlock -of one or more threads because of waits of semaphores. -@return TRUE if deadlock detected */ -static -bool -sync_array_detect_deadlock( -/*=======================*/ - sync_array_t* arr, /*!< in: wait array; NOTE! the caller must - own the mutex to array */ - sync_cell_t* start, /*!< in: cell where recursive search started */ - sync_cell_t* cell, /*!< in: cell to search */ - ulint depth) /*!< in: recursion depth */ -{ - os_thread_id_t thread; - ibool ret; - - ut_a(arr); - ut_a(start); - ut_a(cell); - ut_ad(cell->mutex); - ut_ad(os_thread_get_curr_id() == start->thread_id); - ut_ad(depth < 100); - - depth++; - - if (!cell->waiting) { - /* No deadlock here */ - return(false); - } - - WaitMutex* mutex = cell->mutex; - const WaitMutex::MutexPolicy& policy = mutex->policy(); - - if (mutex->state() != MUTEX_STATE_UNLOCKED) { - thread = policy.context.get_thread_id(); - - /* Note that mutex->thread_id above may be - also OS_THREAD_ID_UNDEFINED, because the - thread which held the mutex maybe has not - yet updated the value, or it has already - released the mutex: in this case no deadlock - can occur, as the wait array cannot contain - a thread with ID_UNDEFINED value. */ - ret = sync_array_deadlock_step( - arr, start, thread, 0, depth); - - if (ret) { - const char* name; - - name = policy.context.get_enter_filename(); - - if (name == NULL) { - /* The mutex might have been - released. */ - name = "NULL"; - } - - ib::info() - << "Mutex " << mutex << " owned by" - " thread " << thread - << " file " << name << " line " - << policy.context.get_enter_line(); - - sync_array_cell_print(stderr, cell); - - return(true); - } - } - - /* No deadlock */ - return(false); -} -#endif /* UNIV_DEBUG */ - -/**********************************************************************//** -Prints warnings of long semaphore waits to stderr. -@return TRUE if fatal semaphore wait threshold was exceeded */ -static -bool -sync_array_print_long_waits_low( -/*============================*/ - sync_array_t* arr, /*!< in: sync array instance */ - os_thread_id_t* waiter, /*!< out: longest waiting thread */ - const void** sema, /*!< out: longest-waited-for semaphore */ - ibool* noticed)/*!< out: TRUE if long wait noticed */ -{ - double fatal_timeout = static_cast<double>( - srv_fatal_semaphore_wait_threshold); - ibool fatal = FALSE; - double longest_diff = 0; - ulint i; - - /* For huge tables, skip the check during CHECK TABLE etc... */ - if (btr_validate_index_running) { - return(false); - } - -#if defined HAVE_valgrind && !__has_feature(memory_sanitizer) - /* Increase the timeouts if running under valgrind because it executes - extremely slowly. HAVE_valgrind does not necessary mean that - we are running under valgrind but we have no better way to tell. - See Bug#58432 innodb.innodb_bug56143 fails under valgrind - for an example */ -# define SYNC_ARRAY_TIMEOUT 2400 - fatal_timeout *= 10; -#else -# define SYNC_ARRAY_TIMEOUT 240 -#endif - const time_t now = time(NULL); - - for (ulint i = 0; i < arr->n_cells; i++) { - sync_cell_t* cell = sync_array_get_nth_cell(arr, i); - - if (!cell->mutex || !cell->waiting) { - - continue; - } - - double diff = difftime(now, cell->reservation_time); - - if (diff > SYNC_ARRAY_TIMEOUT) { - ib::warn() << "A long semaphore wait:"; - sync_array_cell_print(stderr, cell); - *noticed = TRUE; - } - - if (diff > fatal_timeout) { - fatal = TRUE; - } - - if (diff > longest_diff) { - longest_diff = diff; - *sema = cell->mutex; - *waiter = cell->thread_id; - } - } - - /* We found a long semaphore wait, print all threads that are - waiting for a semaphore. */ - if (*noticed) { - for (i = 0; i < arr->n_cells; i++) { - sync_cell_t* cell = sync_array_get_nth_cell(arr, i); - - if (!cell->mutex || !cell->waiting) { - continue; - } - - ib::info() << "A semaphore wait:"; - sync_array_cell_print(stderr, cell); - } - } - -#undef SYNC_ARRAY_TIMEOUT - - return(fatal); -} - -/**********************************************************************//** -Prints warnings of long semaphore waits to stderr. -@return TRUE if fatal semaphore wait threshold was exceeded */ -ibool -sync_array_print_long_waits( -/*========================*/ - os_thread_id_t* waiter, /*!< out: longest waiting thread */ - const void** sema) /*!< out: longest-waited-for semaphore */ -{ - ulint i; - ibool fatal = FALSE; - ibool noticed = FALSE; - - for (i = 0; i < sync_array_size; ++i) { - - sync_array_t* arr = sync_wait_array[i]; - - sync_array_enter(arr); - - if (sync_array_print_long_waits_low( - arr, waiter, sema, ¬iced)) { - - fatal = TRUE; - } - - sync_array_exit(arr); - } - - if (noticed) { - /* If some crucial semaphore is reserved, then also the InnoDB - Monitor can hang, and we do not get diagnostics. Since in - many cases an InnoDB hang is caused by a pwrite() or a pread() - call hanging inside the operating system, let us print right - now the values of pending calls of these. */ - - fprintf(stderr, - "InnoDB: Pending reads " UINT64PF - ", writes " UINT64PF "\n", - MONITOR_VALUE(MONITOR_OS_PENDING_READS), - MONITOR_VALUE(MONITOR_OS_PENDING_WRITES)); - - lock_wait_timeout_task(nullptr); - } - - return(fatal); -} - -/**********************************************************************//** -Prints info of the wait array. */ -static -void -sync_array_print_info_low( -/*======================*/ - FILE* file, /*!< in: file where to print */ - sync_array_t* arr) /*!< in: wait array */ -{ - ulint i; - ulint count = 0; - - fprintf(file, - "OS WAIT ARRAY INFO: reservation count " ULINTPF "\n", - arr->res_count); - - for (i = 0; count < arr->n_reserved; ++i) { - sync_cell_t* cell = sync_array_get_nth_cell(arr, i); - - if (cell->mutex) { - count++; - sync_array_cell_print(file, cell); - } - } -} - -/**********************************************************************//** -Prints info of the wait array. */ -static -void -sync_array_print_info( -/*==================*/ - FILE* file, /*!< in: file where to print */ - sync_array_t* arr) /*!< in: wait array */ -{ - sync_array_enter(arr); - - sync_array_print_info_low(file, arr); - - sync_array_exit(arr); -} - -/** Create the primary system wait arrays */ -void sync_array_init() -{ - ut_a(sync_wait_array == NULL); - ut_a(srv_sync_array_size > 0); - ut_a(srv_max_n_threads > 0); - - sync_array_size = srv_sync_array_size; - - sync_wait_array = UT_NEW_ARRAY_NOKEY(sync_array_t*, sync_array_size); - - ulint n_slots = 1 + (srv_max_n_threads - 1) / sync_array_size; - - for (ulint i = 0; i < sync_array_size; ++i) { - - sync_wait_array[i] = UT_NEW_NOKEY(sync_array_t(n_slots)); - } -} - -/** Destroy the sync array wait sub-system. */ -void sync_array_close() -{ - for (ulint i = 0; i < sync_array_size; ++i) { - sync_array_free(sync_wait_array[i]); - } - - UT_DELETE_ARRAY(sync_wait_array); - sync_wait_array = NULL; -} - -/**********************************************************************//** -Print info about the sync array(s). */ -void -sync_array_print( -/*=============*/ - FILE* file) /*!< in/out: Print to this stream */ -{ - for (ulint i = 0; i < sync_array_size; ++i) { - sync_array_print_info(file, sync_wait_array[i]); - } - - fprintf(file, - "OS WAIT ARRAY INFO: signal count " ULINTPF "\n", sg_count); - -} - -/**********************************************************************//** -Prints info of the wait array without using any mutexes/semaphores. */ -UNIV_INTERN -void -sync_array_print_innodb(void) -/*=========================*/ -{ - ulint i; - sync_array_t* arr = sync_array_get(); - - fputs("InnoDB: Semaphore wait debug output started for InnoDB:\n", stderr); - - for (i = 0; i < arr->n_cells; i++) { - sync_cell_t* cell = sync_array_get_nth_cell(arr, i); - - if (!cell->mutex || !cell->waiting) { - continue; - } - - fputs("InnoDB: Warning: semaphore wait:\n", - stderr); - sync_array_cell_print(stderr, cell); - } - - fputs("InnoDB: Semaphore wait debug output ended:\n", stderr); - -} - -/**********************************************************************//** -Get number of items on sync array. */ -UNIV_INTERN -ulint -sync_arr_get_n_items(void) -/*======================*/ -{ - sync_array_t* sync_arr = sync_array_get(); - return (ulint) sync_arr->n_cells; -} - -/******************************************************************//** -Get specified item from sync array if it is reserved. Set given -pointer to array item if it is reserved. -@return true if item is reserved, false othervise */ -UNIV_INTERN -ibool -sync_arr_get_item( -/*==============*/ - ulint i, /*!< in: requested item */ - sync_cell_t **cell) /*!< out: cell contents if item - reserved */ -{ - sync_array_t* sync_arr; - sync_cell_t* wait_cell; - void* wait_object; - ibool found = FALSE; - - sync_arr = sync_array_get(); - wait_cell = sync_array_get_nth_cell(sync_arr, i); - - if (wait_cell) { - wait_object = wait_cell->mutex; - - if(wait_object != NULL && wait_cell->waiting) { - found = TRUE; - *cell = wait_cell; - } - } - - return found; -} - -/*******************************************************************//** -Function to populate INFORMATION_SCHEMA.INNODB_SYS_SEMAPHORE_WAITS table. -Loop through each item on sync array, and extract the column -information and fill the INFORMATION_SCHEMA.INNODB_SYS_SEMAPHORE_WAITS table. -@return 0 on success */ -UNIV_INTERN -int -sync_arr_fill_sys_semphore_waits_table( -/*===================================*/ - THD* thd, /*!< in: thread */ - TABLE_LIST* tables, /*!< in/out: tables to fill */ - Item* ) /*!< in: condition (not used) */ -{ - Field** fields; - ulint n_items; - - DBUG_ENTER("i_s_sys_semaphore_waits_fill_table"); - RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name.str); - - /* deny access to user without PROCESS_ACL privilege */ - if (check_global_access(thd, PROCESS_ACL)) { - DBUG_RETURN(0); - } - - fields = tables->table->field; - n_items = sync_arr_get_n_items(); - - for(ulint i=0; i < n_items;i++) { - sync_cell_t *cell=NULL; - if (sync_arr_get_item(i, &cell)) { - /* JAN: FIXME - OK(fields[SYS_SEMAPHORE_WAITS_THREAD_ID]->store(, - ulint(cell->thread), true)); - */ - OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_FILE], innobase_basename(cell->file))); - OK(fields[SYS_SEMAPHORE_WAITS_LINE]->store(cell->line, true)); - fields[SYS_SEMAPHORE_WAITS_LINE]->set_notnull(); - OK(fields[SYS_SEMAPHORE_WAITS_WAIT_TIME]->store( - difftime(time(NULL), - cell->reservation_time))); - - if (WaitMutex* mutex = cell->mutex) { - // JAN: FIXME - // OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_OBJECT_NAME], mutex->cmutex_name)); - OK(fields[SYS_SEMAPHORE_WAITS_WAIT_OBJECT]->store((longlong)mutex, true)); - OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_WAIT_TYPE], "MUTEX")); - //OK(fields[SYS_SEMAPHORE_WAITS_HOLDER_THREAD_ID]->store(mutex->thread_id, true)); - //OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_HOLDER_FILE], innobase_basename(mutex->file_name))); - //OK(fields[SYS_SEMAPHORE_WAITS_HOLDER_LINE]->store(mutex->line, true)); - //fields[SYS_SEMAPHORE_WAITS_HOLDER_LINE]->set_notnull(); - //OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_CREATED_FILE], innobase_basename(mutex->cfile_name))); - //OK(fields[SYS_SEMAPHORE_WAITS_CREATED_LINE]->store(mutex->cline, true)); - //fields[SYS_SEMAPHORE_WAITS_CREATED_LINE]->set_notnull(); - //OK(fields[SYS_SEMAPHORE_WAITS_WAITERS_FLAG]->store(mutex->waiters, true)); - //OK(fields[SYS_SEMAPHORE_WAITS_LOCK_WORD]->store(mutex->lock_word, true)); - //OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_LAST_WRITER_FILE], innobase_basename(mutex->file_name))); - //OK(fields[SYS_SEMAPHORE_WAITS_LAST_WRITER_LINE]->store(mutex->line, true)); - //fields[SYS_SEMAPHORE_WAITS_LAST_WRITER_LINE]->set_notnull(); - //OK(fields[SYS_SEMAPHORE_WAITS_OS_WAIT_COUNT]->store(mutex->count_os_wait, true)); - } - - OK(schema_table_store_record(thd, tables->table)); - } - } - - DBUG_RETURN(0); -} diff --git a/storage/innobase/sync/sync0debug.cc b/storage/innobase/sync/sync0debug.cc index 6424db6dc61..cdef44a6652 100644 --- a/storage/innobase/sync/sync0debug.cc +++ b/storage/innobase/sync/sync0debug.cc @@ -388,7 +388,6 @@ LatchDebug::LatchDebug() m_mutex.init(); LEVEL_MAP_INSERT(SYNC_UNKNOWN); - LEVEL_MAP_INSERT(SYNC_MUTEX); LEVEL_MAP_INSERT(RW_LOCK_SX); LEVEL_MAP_INSERT(RW_LOCK_X_WAIT); LEVEL_MAP_INSERT(RW_LOCK_S); @@ -668,7 +667,6 @@ LatchDebug::check_order( basic_check(latches, level, SYNC_DICT); break; - case SYNC_MUTEX: case SYNC_UNKNOWN: case RW_LOCK_X: case RW_LOCK_X_WAIT: @@ -1030,8 +1028,6 @@ sync_check_init() sync_latch_meta_init(); - sync_array_init(); - ut_d(sync_check_enable()); } @@ -1040,8 +1036,5 @@ void sync_check_close() { ut_d(LatchDebug::shutdown()); - - sync_array_close(); - sync_latch_meta_destroy(); } |