mirror of
https://github.com/MariaDB/server.git
synced 2025-07-10 04:22:00 +03:00
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.
This commit is contained in:
@ -50,8 +50,6 @@ create sql security invoker view i_sys_foreign_cols as select * from information
|
||||
create sql security definer view d_sys_foreign_cols as select * from information_schema.innodb_sys_foreign_cols;
|
||||
create sql security invoker view i_sys_indexes as select * from information_schema.innodb_sys_indexes;
|
||||
create sql security definer view d_sys_indexes as select * from information_schema.innodb_sys_indexes;
|
||||
create sql security invoker view i_sys_semaphore_waits as select * from information_schema.innodb_sys_semaphore_waits;
|
||||
create sql security definer view d_sys_semaphore_waits as select * from information_schema.innodb_sys_semaphore_waits;
|
||||
create sql security invoker view i_sys_tables as select * from information_schema.innodb_sys_tables;
|
||||
create sql security definer view d_sys_tables as select * from information_schema.innodb_sys_tables;
|
||||
create sql security invoker view i_sys_tablespaces as select * from information_schema.innodb_sys_tablespaces;
|
||||
@ -222,13 +220,6 @@ ERROR 42000: Access denied; you need (at least one of) the PROCESS privilege(s)
|
||||
select count(*) > -1 from d_sys_indexes;
|
||||
count(*) > -1
|
||||
1
|
||||
select count(*) > -1 from information_schema.innodb_sys_semaphore_waits;
|
||||
ERROR 42000: Access denied; you need (at least one of) the PROCESS privilege(s) for this operation
|
||||
select count(*) > -1 from i_sys_semaphore_waits;
|
||||
ERROR 42000: Access denied; you need (at least one of) the PROCESS privilege(s) for this operation
|
||||
select count(*) > -1 from d_sys_semaphore_waits;
|
||||
count(*) > -1
|
||||
1
|
||||
select count(*) > -1 from information_schema.innodb_sys_tables;
|
||||
ERROR 42000: Access denied; you need (at least one of) the PROCESS privilege(s) for this operation
|
||||
select count(*) > -1 from i_sys_tables;
|
||||
|
@ -363,7 +363,3 @@ select * from information_schema.innodb_tablespaces_encryption;
|
||||
SPACE NAME ENCRYPTION_SCHEME KEYSERVER_REQUESTS MIN_KEY_VERSION CURRENT_KEY_VERSION KEY_ROTATION_PAGE_NUMBER KEY_ROTATION_MAX_PAGE_NUMBER CURRENT_KEY_ID ROTATING_OR_FLUSHING
|
||||
Warnings:
|
||||
Warning 1012 InnoDB: SELECTing from INFORMATION_SCHEMA.innodb_tablespaces_encryption but the InnoDB storage engine is not installed
|
||||
select * from information_schema.innodb_sys_semaphore_waits;
|
||||
THREAD_ID OBJECT_NAME FILE LINE WAIT_TIME WAIT_OBJECT WAIT_TYPE HOLDER_THREAD_ID HOLDER_FILE HOLDER_LINE CREATED_FILE CREATED_LINE WRITER_THREAD RESERVATION_MODE READERS WAITERS_FLAG LOCK_WORD LAST_WRITER_FILE LAST_WRITER_LINE OS_WAIT_COUNT
|
||||
Warnings:
|
||||
Warning 1012 InnoDB: SELECTing from INFORMATION_SCHEMA.innodb_sys_semaphore_waits but the InnoDB storage engine is not installed
|
||||
|
@ -1,27 +0,0 @@
|
||||
connect con1,localhost,root,,;
|
||||
connect con2,localhost,root,,;
|
||||
drop table if exists t1;
|
||||
connection con1;
|
||||
create table t1 (id integer, x integer) engine = InnoDB;
|
||||
insert into t1 values(0, 0);
|
||||
SET @saved_dbug = @@SESSION.debug_dbug;
|
||||
set DEBUG_DBUG='+d,fatal-semaphore-timeout';
|
||||
set autocommit=0;
|
||||
# Sending query on con1,
|
||||
# the session will hold lock table mutex and sleep
|
||||
SELECT * from t1 where id = 0 FOR UPDATE;
|
||||
connection con2;
|
||||
set autocommit=0;
|
||||
# Sending query on con2,
|
||||
# the session will be blocked on the lock table mutex and
|
||||
# thus be put into sync arry
|
||||
SELECT * from t1 where id = 0 FOR UPDATE;
|
||||
connection default;
|
||||
# Waitting for mysqld to crash
|
||||
# Mysqld crash was detected
|
||||
# Waitting for reconnect after mysqld restarts
|
||||
# Reconnected after mysqld was successfully restarted
|
||||
# Cleaning up before exit
|
||||
SET debug_dbug = @saved_dbug;
|
||||
drop table if exists t1;
|
||||
# Clean exit
|
@ -26,5 +26,4 @@
|
||||
--enable-plugin-innodb-sys-foreign-cols
|
||||
--enable-plugin-innodb-sys-tablespaces
|
||||
--enable-plugin-innodb-sys-virtual
|
||||
--enable-plugin-innodb-sys-semaphore-waits
|
||||
--enable-plugin-innodb-tablespaces-encryption
|
||||
|
@ -79,9 +79,6 @@ create sql security definer view d_sys_foreign_cols as select * from information
|
||||
create sql security invoker view i_sys_indexes as select * from information_schema.innodb_sys_indexes;
|
||||
create sql security definer view d_sys_indexes as select * from information_schema.innodb_sys_indexes;
|
||||
|
||||
create sql security invoker view i_sys_semaphore_waits as select * from information_schema.innodb_sys_semaphore_waits;
|
||||
create sql security definer view d_sys_semaphore_waits as select * from information_schema.innodb_sys_semaphore_waits;
|
||||
|
||||
create sql security invoker view i_sys_tables as select * from information_schema.innodb_sys_tables;
|
||||
create sql security definer view d_sys_tables as select * from information_schema.innodb_sys_tables;
|
||||
|
||||
@ -236,12 +233,6 @@ select count(*) > -1 from information_schema.innodb_sys_indexes;
|
||||
select count(*) > -1 from i_sys_indexes;
|
||||
select count(*) > -1 from d_sys_indexes;
|
||||
|
||||
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
|
||||
select count(*) > -1 from information_schema.innodb_sys_semaphore_waits;
|
||||
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
|
||||
select count(*) > -1 from i_sys_semaphore_waits;
|
||||
select count(*) > -1 from d_sys_semaphore_waits;
|
||||
|
||||
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
|
||||
select count(*) > -1 from information_schema.innodb_sys_tables;
|
||||
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
|
||||
|
@ -59,4 +59,3 @@
|
||||
--loose-innodb_sys_datafiles
|
||||
--loose-innodb_changed_pages
|
||||
--loose-innodb_tablespaces_encryption
|
||||
--loose-innodb_sys_semaphore_waits
|
||||
|
@ -27,4 +27,3 @@ select * from information_schema.innodb_sys_foreign;
|
||||
select * from information_schema.innodb_sys_foreign_cols;
|
||||
select * from information_schema.innodb_sys_tablespaces;
|
||||
select * from information_schema.innodb_tablespaces_encryption;
|
||||
select * from information_schema.innodb_sys_semaphore_waits;
|
||||
|
@ -1,2 +0,0 @@
|
||||
--innodb-fatal-semaphore-wait-threshold=1
|
||||
--innodb-sys-semaphore-waits=1
|
@ -1,115 +0,0 @@
|
||||
--source include/have_innodb.inc
|
||||
--source include/not_windows.inc
|
||||
--source include/not_valgrind.inc
|
||||
--source include/not_embedded.inc
|
||||
# DEBUG_SYNC must be compiled in.
|
||||
--source include/have_debug_sync.inc
|
||||
|
||||
connect (con1,localhost,root,,);
|
||||
connect (con2,localhost,root,,);
|
||||
|
||||
--disable_warnings
|
||||
drop table if exists t1;
|
||||
--enable_warnings
|
||||
|
||||
connection con1;
|
||||
eval create table t1 (id integer, x integer) engine = InnoDB;
|
||||
insert into t1 values(0, 0);
|
||||
|
||||
# Enable the debug injection.
|
||||
SET @saved_dbug = @@SESSION.debug_dbug;
|
||||
set DEBUG_DBUG='+d,fatal-semaphore-timeout';
|
||||
set autocommit=0;
|
||||
|
||||
# The following query will hang for an hour since the debug injection
|
||||
# code will sleep an hour after holding the lock table mutex
|
||||
--echo # Sending query on con1,
|
||||
--echo # the session will hold lock table mutex and sleep
|
||||
--send
|
||||
SELECT * from t1 where id = 0 FOR UPDATE;
|
||||
|
||||
# To make sure con1 holding the lock table mutex and sleeping
|
||||
--sleep 2
|
||||
|
||||
connection con2;
|
||||
set autocommit=0;
|
||||
|
||||
# The following query will be blocked on the lock table mutex held by
|
||||
# con1 so it will be put into sync array.
|
||||
--echo # Sending query on con2,
|
||||
--echo # the session will be blocked on the lock table mutex and
|
||||
--echo # thus be put into sync arry
|
||||
--send
|
||||
SELECT * from t1 where id = 0 FOR UPDATE;
|
||||
|
||||
# Waitting for mysqld to abort due to fatal semaphore timeout.
|
||||
# Please note that, in the master.opt file, the fatal timeout
|
||||
# was set to 1 second, but in mysqld debug mode, this timeout
|
||||
# value will be timed 10 because UNIV_DEBUG_VALGRIND is set
|
||||
# (see sync_array_print_long_waits_low() in storage/innobase/sync/sync0arr.cc)
|
||||
# so the actual timeout will be 1 * 10 = 10 seconds. Besides,
|
||||
# mysqld will abort after detecting this fatal timeout 10 times in
|
||||
# a loop with interval of 1 second (see srv_error_monitor_thread
|
||||
# thread in torage/innobase/srv/srv0srv.cc), so mysqld will abort
|
||||
# in 1 * 10 + 1 * 10 = 20 seconds after con2 being blocked on
|
||||
# the lock table mutex.
|
||||
#
|
||||
# P.S. the default fatal sempahore timeout is 600 seconds,
|
||||
# so mysqld will abort after 600 * 10 + 1 * 10 = 6010 seconds
|
||||
# in debug mode and 600 + 1 * 10 = 610 seconds in release mode.
|
||||
|
||||
connection default;
|
||||
|
||||
--disable_result_log
|
||||
--disable_query_log
|
||||
|
||||
# Since this test generates lot of errors in log, suppress checking errors
|
||||
call mtr.add_suppression(".*");
|
||||
|
||||
# The crash is expected
|
||||
exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect;
|
||||
|
||||
--echo # Waitting for mysqld to crash
|
||||
|
||||
# It will take 20 seconds to detect the long semaphore and mysqld to abort.
|
||||
# This test will be treated as pass as long as mysqld crash/restart is dectected
|
||||
# in 80 seconds.
|
||||
let $counter= 80;
|
||||
let $mysql_errno= 0;
|
||||
while (!$mysql_errno)
|
||||
{
|
||||
--error 0,ER_SERVER_SHUTDOWN,ER_CONNECTION_KILLED,2002,2006,2013
|
||||
show status;
|
||||
|
||||
--error 0,ER_SERVER_SHUTDOWN,ER_CONNECTION_KILLED,2002,2006,2013
|
||||
select * from information_schema.innodb_sys_semaphore_waits;
|
||||
|
||||
dec $counter;
|
||||
if (!$counter)
|
||||
{
|
||||
# This will fail this test.
|
||||
--die Server failed to dissapear
|
||||
}
|
||||
--sleep 1
|
||||
}
|
||||
|
||||
--echo # Mysqld crash was detected
|
||||
--echo # Waitting for reconnect after mysqld restarts
|
||||
|
||||
enable_reconnect;
|
||||
connection default;
|
||||
|
||||
--exec echo "restart:--log-error=$error_log" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
||||
|
||||
# Call script that will poll the server waiting for it to be back online again
|
||||
source include/wait_until_connected_again.inc;
|
||||
|
||||
--echo # Reconnected after mysqld was successfully restarted
|
||||
|
||||
--echo # Cleaning up before exit
|
||||
--disable_warnings
|
||||
SET debug_dbug = @saved_dbug;
|
||||
drop table if exists t1;
|
||||
--enable_warnings
|
||||
|
||||
--echo # Clean exit
|
@ -1 +0,0 @@
|
||||
--innodb_sys_semaphore_waits
|
@ -1,24 +0,0 @@
|
||||
SHOW CREATE TABLE INFORMATION_SCHEMA.INNODB_SYS_SEMAPHORE_WAITS;
|
||||
Table Create Table
|
||||
INNODB_SYS_SEMAPHORE_WAITS CREATE TEMPORARY TABLE `INNODB_SYS_SEMAPHORE_WAITS` (
|
||||
`THREAD_ID` bigint(21) unsigned NOT NULL DEFAULT 0,
|
||||
`OBJECT_NAME` varchar(4000) DEFAULT NULL,
|
||||
`FILE` varchar(4000) DEFAULT NULL,
|
||||
`LINE` int(11) unsigned NOT NULL DEFAULT 0,
|
||||
`WAIT_TIME` bigint(21) unsigned NOT NULL DEFAULT 0,
|
||||
`WAIT_OBJECT` bigint(21) unsigned NOT NULL DEFAULT 0,
|
||||
`WAIT_TYPE` varchar(16) DEFAULT NULL,
|
||||
`HOLDER_THREAD_ID` bigint(21) unsigned NOT NULL DEFAULT 0,
|
||||
`HOLDER_FILE` varchar(4000) DEFAULT NULL,
|
||||
`HOLDER_LINE` int(11) unsigned NOT NULL DEFAULT 0,
|
||||
`CREATED_FILE` varchar(4000) DEFAULT NULL,
|
||||
`CREATED_LINE` int(11) unsigned NOT NULL DEFAULT 0,
|
||||
`WRITER_THREAD` bigint(21) unsigned NOT NULL DEFAULT 0,
|
||||
`RESERVATION_MODE` varchar(16) DEFAULT NULL,
|
||||
`READERS` int(11) unsigned NOT NULL DEFAULT 0,
|
||||
`WAITERS_FLAG` bigint(21) unsigned NOT NULL DEFAULT 0,
|
||||
`LOCK_WORD` bigint(21) unsigned NOT NULL DEFAULT 0,
|
||||
`LAST_WRITER_FILE` varchar(4000) DEFAULT NULL,
|
||||
`LAST_WRITER_LINE` int(11) unsigned NOT NULL DEFAULT 0,
|
||||
`OS_WAIT_COUNT` int(11) unsigned NOT NULL DEFAULT 0
|
||||
) ENGINE=MEMORY DEFAULT CHARSET=utf8
|
@ -1,3 +0,0 @@
|
||||
--source include/have_innodb.inc
|
||||
|
||||
SHOW CREATE TABLE INFORMATION_SCHEMA.INNODB_SYS_SEMAPHORE_WAITS;
|
@ -1,30 +0,0 @@
|
||||
Valid values are between 0 and 1024
|
||||
SELECT @@global.innodb_sync_array_size between 0 and 1024;
|
||||
@@global.innodb_sync_array_size between 0 and 1024
|
||||
1
|
||||
SELECT @@global.innodb_sync_array_size;
|
||||
@@global.innodb_sync_array_size
|
||||
1
|
||||
SELECT @@session.innodb_sync_array_size;
|
||||
ERROR HY000: Variable 'innodb_sync_array_size' is a GLOBAL variable
|
||||
SHOW GLOBAL variables LIKE 'innodb_sync_array_size';
|
||||
Variable_name Value
|
||||
innodb_sync_array_size 1
|
||||
SHOW SESSION variables LIKE 'innodb_sync_array_size';
|
||||
Variable_name Value
|
||||
innodb_sync_array_size 1
|
||||
SELECT * FROM information_schema.global_variables
|
||||
WHERE variable_name='innodb_sync_array_size';
|
||||
VARIABLE_NAME VARIABLE_VALUE
|
||||
INNODB_SYNC_ARRAY_SIZE 1
|
||||
SELECT * FROM information_schema.session_variables
|
||||
WHERE variable_name='innodb_sync_array_size';
|
||||
VARIABLE_NAME VARIABLE_VALUE
|
||||
INNODB_SYNC_ARRAY_SIZE 1
|
||||
SET GLOBAL innodb_sync_array_size=10;
|
||||
ERROR HY000: Variable 'innodb_sync_array_size' is a read only variable
|
||||
SET SESSION innodb_sync_array_size=10;
|
||||
ERROR HY000: Variable 'innodb_sync_array_size' is a read only variable
|
||||
SELECT @@global.innodb_sync_array_size;
|
||||
@@global.innodb_sync_array_size
|
||||
1
|
@ -1665,18 +1665,6 @@ NUMERIC_BLOCK_SIZE NULL
|
||||
ENUM_VALUE_LIST OFF,ON
|
||||
READ_ONLY NO
|
||||
COMMAND_LINE_ARGUMENT OPTIONAL
|
||||
VARIABLE_NAME INNODB_SYNC_ARRAY_SIZE
|
||||
SESSION_VALUE NULL
|
||||
DEFAULT_VALUE 1
|
||||
VARIABLE_SCOPE GLOBAL
|
||||
VARIABLE_TYPE BIGINT UNSIGNED
|
||||
VARIABLE_COMMENT Size of the mutex/lock wait array.
|
||||
NUMERIC_MIN_VALUE 1
|
||||
NUMERIC_MAX_VALUE 1024
|
||||
NUMERIC_BLOCK_SIZE 0
|
||||
ENUM_VALUE_LIST NULL
|
||||
READ_ONLY YES
|
||||
COMMAND_LINE_ARGUMENT OPTIONAL
|
||||
VARIABLE_NAME INNODB_SYNC_DEBUG
|
||||
SESSION_VALUE NULL
|
||||
DEFAULT_VALUE OFF
|
||||
|
@ -1,29 +0,0 @@
|
||||
# 2010-01-27 - Added
|
||||
|
||||
--source include/have_innodb.inc
|
||||
|
||||
# Exists as global only
|
||||
#
|
||||
--echo Valid values are between 0 and 1024
|
||||
SELECT @@global.innodb_sync_array_size between 0 and 1024;
|
||||
SELECT @@global.innodb_sync_array_size;
|
||||
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
|
||||
SELECT @@session.innodb_sync_array_size;
|
||||
|
||||
SHOW GLOBAL variables LIKE 'innodb_sync_array_size';
|
||||
SHOW SESSION variables LIKE 'innodb_sync_array_size';
|
||||
--disable_warnings
|
||||
SELECT * FROM information_schema.global_variables
|
||||
WHERE variable_name='innodb_sync_array_size';
|
||||
SELECT * FROM information_schema.session_variables
|
||||
WHERE variable_name='innodb_sync_array_size';
|
||||
--enable_warnings
|
||||
|
||||
#
|
||||
# Show that it's read-only
|
||||
#
|
||||
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
|
||||
SET GLOBAL innodb_sync_array_size=10;
|
||||
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
|
||||
SET SESSION innodb_sync_array_size=10;
|
||||
SELECT @@global.innodb_sync_array_size;
|
@ -469,7 +469,6 @@ innodb.innodb_stats : MDEV-10682 - wrong result
|
||||
innodb.innodb_stats_drop_locked : Modified in 10.5.7
|
||||
innodb.innodb_stats_persistent : MDEV-21567 - Wrong result in execution plan
|
||||
innodb.innodb_stats_persistent_debug : MDEV-14801 - Operation failed
|
||||
innodb.innodb_sys_semaphore_waits : MDEV-10331 - Semaphore wait
|
||||
innodb.innodb_trx_weight : Configuration deleted in 10.5.7
|
||||
innodb.innodb_zip_innochecksum2 : MDEV-13882 - Warning: difficult to find free blocks
|
||||
innodb.instant_alter_bugs : Modified in 10.5.7
|
||||
|
@ -5049,6 +5049,7 @@ static int init_server_components()
|
||||
MARIADB_REMOVED_OPTION("innodb-replication-delay"),
|
||||
MARIADB_REMOVED_OPTION("innodb-scrub-log"),
|
||||
MARIADB_REMOVED_OPTION("innodb-scrub-log-speed"),
|
||||
MARIADB_REMOVED_OPTION("innodb-sync-array-size"),
|
||||
MARIADB_REMOVED_OPTION("innodb-thread-concurrency"),
|
||||
MARIADB_REMOVED_OPTION("innodb-thread-sleep-delay"),
|
||||
MARIADB_REMOVED_OPTION("innodb-undo-logs"),
|
||||
|
@ -123,6 +123,7 @@ static const char *removed_variables[] =
|
||||
"innodb_stats_sample_pages",
|
||||
"innodb_stats_update_need_lock",
|
||||
"innodb_support_xa",
|
||||
"innodb_sync_array_size",
|
||||
"innodb_thread_concurrency",
|
||||
"innodb_thread_concurrency_timer_based",
|
||||
"innodb_thread_sleep_delay",
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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),
|
||||
};
|
||||
|
@ -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 */
|
||||
|
@ -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>
|
||||
|
@ -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 */
|
@ -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;
|
||||
|
@ -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 */
|
@ -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);
|
||||
}
|
@ -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,
|
||||
|
@ -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 */
|
||||
|
@ -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",
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
srv_max_n_threads =
|
||||
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;
|
||||
+ 128 /* safety margin */
|
||||
+ max_connections;
|
||||
|
||||
srv_boot();
|
||||
|
||||
|
@ -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);
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
Reference in New Issue
Block a user