Commit ba2d45dc authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-24142: Remove INFORMATION_SCHEMA.INNODB_MUTEXES

Let us remove sux_lock::waits and the associated bookkeeping.
Starting with commit 1669c889
the PERFORMANCE_SCHEMA instrumentation interface is keeping
track of lock waits.

The view INFORMATION_SCHEMA.INNODB_MUTEXES only exported counts
of rw-lock waits.

Also, SHOW ENGINE INNODB MUTEX will no longer export any information
about rw-locks.
parent 9702be2c
......@@ -13,5 +13,4 @@
--loose-innodb-sys-foreign-cols
--loose-innodb-sys-tables
--loose-innodb-sys-tablestats
--loose-innodb-mutexes
--loose-innodb-tablespaces-encryption
......@@ -29,7 +29,6 @@ INNODB_CMP_RESET
INNODB_LOCKS
INNODB_LOCK_WAITS
INNODB_METRICS
INNODB_MUTEXES
INNODB_SYS_COLUMNS
INNODB_SYS_FIELDS
INNODB_SYS_FOREIGN
......@@ -109,7 +108,6 @@ INNODB_CMP_RESET page_size
INNODB_LOCKS lock_id
INNODB_LOCK_WAITS requesting_trx_id
INNODB_METRICS NAME
INNODB_MUTEXES NAME
INNODB_SYS_COLUMNS TABLE_ID
INNODB_SYS_FIELDS INDEX_ID
INNODB_SYS_FOREIGN ID
......@@ -189,7 +187,6 @@ INNODB_CMP_RESET page_size
INNODB_LOCKS lock_id
INNODB_LOCK_WAITS requesting_trx_id
INNODB_METRICS NAME
INNODB_MUTEXES NAME
INNODB_SYS_COLUMNS TABLE_ID
INNODB_SYS_FIELDS INDEX_ID
INNODB_SYS_FOREIGN ID
......@@ -274,7 +271,6 @@ INNODB_CMP_RESET information_schema.INNODB_CMP_RESET 1
INNODB_LOCKS information_schema.INNODB_LOCKS 1
INNODB_LOCK_WAITS information_schema.INNODB_LOCK_WAITS 1
INNODB_METRICS information_schema.INNODB_METRICS 1
INNODB_MUTEXES information_schema.INNODB_MUTEXES 1
INNODB_SYS_COLUMNS information_schema.INNODB_SYS_COLUMNS 1
INNODB_SYS_FIELDS information_schema.INNODB_SYS_FIELDS 1
INNODB_SYS_FOREIGN information_schema.INNODB_SYS_FOREIGN 1
......@@ -344,7 +340,6 @@ Database: information_schema
| INNODB_LOCKS |
| INNODB_LOCK_WAITS |
| INNODB_METRICS |
| INNODB_MUTEXES |
| INNODB_SYS_COLUMNS |
| INNODB_SYS_FIELDS |
| INNODB_SYS_FOREIGN |
......@@ -414,7 +409,6 @@ Database: INFORMATION_SCHEMA
| INNODB_LOCKS |
| INNODB_LOCK_WAITS |
| INNODB_METRICS |
| INNODB_MUTEXES |
| INNODB_SYS_COLUMNS |
| INNODB_SYS_FIELDS |
| INNODB_SYS_FOREIGN |
......@@ -459,5 +453,5 @@ Wildcard: inf_rmation_schema
| information_schema |
SELECT table_schema, count(*) FROM information_schema.TABLES WHERE table_schema IN ('mysql', 'INFORMATION_SCHEMA', 'test', 'mysqltest') GROUP BY TABLE_SCHEMA;
table_schema count(*)
information_schema 65
information_schema 64
mysql 31
......@@ -40,8 +40,6 @@ create sql security invoker view i_locks as select * from information_schema.inn
create sql security definer view d_locks as select * from information_schema.innodb_locks;
create sql security invoker view i_metrics as select * from information_schema.innodb_metrics;
create sql security definer view d_metrics as select * from information_schema.innodb_metrics;
create sql security invoker view i_mutexes as select * from information_schema.innodb_mutexes;
create sql security definer view d_mutexes as select * from information_schema.innodb_mutexes;
create sql security invoker view i_sys_columns as select * from information_schema.innodb_sys_columns;
create sql security definer view d_sys_columns as select * from information_schema.innodb_sys_columns;
create sql security invoker view i_sys_fields as select * from information_schema.innodb_sys_fields;
......@@ -189,13 +187,6 @@ ERROR 42000: Access denied; you need (at least one of) the PROCESS privilege(s)
select count(*) > -1 from d_metrics;
count(*) > -1
1
select count(*) > -1 from information_schema.innodb_mutexes;
ERROR 42000: Access denied; you need (at least one of) the PROCESS privilege(s) for this operation
select count(*) > -1 from i_mutexes;
ERROR 42000: Access denied; you need (at least one of) the PROCESS privilege(s) for this operation
select count(*) > -1 from d_mutexes;
count(*) > -1
1
select count(*) > -1 from information_schema.innodb_sys_columns;
ERROR 42000: Access denied; you need (at least one of) the PROCESS privilege(s) for this operation
select count(*) > -1 from i_sys_columns;
......
connect con1,localhost,root,,;
connect con2,localhost,root,,;
connect con3,localhost,root,,;
create table t1(a int not null primary key, b int, c int,d CHAR(100)) engine=innodb;
create procedure innodb_insert_proc (repeat_count int)
begin
declare current_num int;
set current_num = 0;
while current_num < repeat_count do
insert into t1 values(current_num, RAND(), RAND(), substring(MD5(RAND()), -64));
set current_num = current_num + 1;
end while;
end//
commit;
set autocommit=0;
call innodb_insert_proc(20000);
commit;
set autocommit=1;
connection con1;
delete from t1 where a between 1000 and 1300;
connection con2;
update t1 set b=b+1 where a between 2000 and 2600;
connection con3;
insert into t1 select a+30000,b,c,d from t1 where a between 3000 and 4000;
connection default;
delete from t1 where a between 6000 and 7000;
connection con1;
connection con2;
connection con3;
connection default;
disconnect con1;
disconnect con2;
disconnect con3;
drop procedure innodb_insert_proc;
drop table t1;
......@@ -363,10 +363,6 @@ 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_mutexes;
NAME OS_WAITS
Warnings:
Warning 1012 InnoDB: SELECTing from INFORMATION_SCHEMA.innodb_mutexes 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:
......
......@@ -26,6 +26,5 @@
--enable-plugin-innodb-sys-foreign-cols
--enable-plugin-innodb-sys-tablespaces
--enable-plugin-innodb-sys-virtual
--enable-plugin-innodb-mutexes
--enable-plugin-innodb-sys-semaphore-waits
--enable-plugin-innodb-tablespaces-encryption
......@@ -64,9 +64,6 @@ create sql security definer view d_locks as select * from information_schema.inn
create sql security invoker view i_metrics as select * from information_schema.innodb_metrics;
create sql security definer view d_metrics as select * from information_schema.innodb_metrics;
create sql security invoker view i_mutexes as select * from information_schema.innodb_mutexes;
create sql security definer view d_mutexes as select * from information_schema.innodb_mutexes;
create sql security invoker view i_sys_columns as select * from information_schema.innodb_sys_columns;
create sql security definer view d_sys_columns as select * from information_schema.innodb_sys_columns;
......@@ -209,12 +206,6 @@ select count(*) > -1 from information_schema.innodb_metrics;
select count(*) > -1 from i_metrics;
select count(*) > -1 from d_metrics;
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
select count(*) > -1 from information_schema.innodb_mutexes;
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
select count(*) > -1 from i_mutexes;
select count(*) > -1 from d_mutexes;
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
select count(*) > -1 from information_schema.innodb_sys_columns;
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
......
--innodb-mutexes
\ No newline at end of file
--source include/have_innodb.inc
connect(con1,localhost,root,,);
connect(con2,localhost,root,,);
connect(con3,localhost,root,,);
create table t1(a int not null primary key, b int, c int,d CHAR(100)) engine=innodb;
delimiter //;
create procedure innodb_insert_proc (repeat_count int)
begin
declare current_num int;
set current_num = 0;
while current_num < repeat_count do
insert into t1 values(current_num, RAND(), RAND(), substring(MD5(RAND()), -64));
set current_num = current_num + 1;
end while;
end//
delimiter ;//
commit;
set autocommit=0;
call innodb_insert_proc(20000);
commit;
set autocommit=1;
connection con1;
send delete from t1 where a between 1000 and 1300;
connection con2;
send update t1 set b=b+1 where a between 2000 and 2600;
connection con3;
send insert into t1 select a+30000,b,c,d from t1 where a between 3000 and 4000;
connection default;
send delete from t1 where a between 6000 and 7000;
connection con1;
reap;
connection con2;
reap;
connection con3;
reap;
connection default;
reap;
disconnect con1;
disconnect con2;
disconnect con3;
# test that below does not crash, actual result is not
# repeatable
--disable_query_log
--disable_result_log
--disable_warnings
select * from information_schema.innodb_mutexes;
--enable_query_log
--enable_result_log
--enable_warnings
drop procedure innodb_insert_proc;
drop table t1;
\ No newline at end of file
......@@ -59,7 +59,4 @@
--loose-innodb_sys_datafiles
--loose-innodb_changed_pages
--loose-innodb_tablespaces_encryption
--loose-innodb_mutexes
--loose-innodb_sys_semaphore_waits
--loose-innodb_mutexes
--loose-innodb_sys_semaphore_waits
......@@ -27,5 +27,4 @@ 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_mutexes;
select * from information_schema.innodb_sys_semaphore_waits;
SHOW CREATE TABLE INFORMATION_SCHEMA.INNODB_MUTEXES;
Table Create Table
INNODB_MUTEXES CREATE TEMPORARY TABLE `INNODB_MUTEXES` (
`NAME` varchar(4000) NOT NULL DEFAULT '',
`OS_WAITS` bigint(21) unsigned NOT NULL DEFAULT 0
) ENGINE=MEMORY DEFAULT CHARSET=utf8
--source include/have_innodb.inc
SHOW CREATE TABLE INFORMATION_SCHEMA.INNODB_MUTEXES;
......@@ -462,7 +462,6 @@ innodb.innodb_information_schema_buffer : MDEV-23418 - Wrong result
innodb.innodb_max_recordsize_32k : MDEV-14801 - Operation failed
innodb.innodb_max_recordsize_64k : MDEV-15203 - Wrong result
innodb.innodb_monitor : MDEV-10939 - Testcase timeout
innodb.innodb_mutexes : MDEV-23416 - Extra warning
innodb.innodb_mysql : MDEV-19873 - Wrong result
innodb.innodb_scrub : Modified in 10.5.7
innodb.innodb_simulate_comp_failures_small : MDEV-20526 - ASAN use-after-poison
......
......@@ -15838,60 +15838,6 @@ innodb_show_mutex_status(
DBUG_RETURN(0);
}
/** Implement SHOW ENGINE INNODB MUTEX for rw-locks.
@param hton the innodb handlerton
@param thd connection
@param fn function for printing statistics
@return 0 on success. */
static
int
innodb_show_rwlock_status(handlerton* ut_d(hton), THD *thd, stat_print_fn *fn)
{
DBUG_ENTER("innodb_show_rwlock_status");
ut_ad(hton == innodb_hton_ptr);
constexpr size_t prefix_len= sizeof "waits=" - 1;
char waits[prefix_len + 20 + 1];
snprintf(waits, sizeof waits, "waits=" UINT64PF, buf_pool.waited());
if (fn(thd, STRING_WITH_LEN(innobase_hton_name),
STRING_WITH_LEN("buf_block_t::lock"), waits, strlen(waits)))
DBUG_RETURN(1);
DBUG_RETURN(!dict_sys.for_each_index([&](const dict_index_t &i)
{
uint32_t waited= i.lock.waited();
if (!waited)
return true;
snprintf(waits + prefix_len, sizeof waits - prefix_len, "%u", waited);
std::ostringstream s;
s << i.name << '(' << i.table->name << ')';
return !fn(thd, STRING_WITH_LEN(innobase_hton_name),
s.str().data(), s.str().size(), waits, strlen(waits));
}));
}
/** Implements the SHOW MUTEX STATUS command.
@param[in,out] hton the innodb handlerton
@param[in,out] thd the MySQL query thread of the caller
@param[in,out] stat_print function for printing statistics
@return 0 on success. */
static
int
innodb_show_latch_status(
handlerton* hton,
THD* thd,
stat_print_fn* stat_print)
{
int ret = innodb_show_mutex_status(hton, thd, stat_print);
if (ret != 0) {
return(ret);
}
return(innodb_show_rwlock_status(hton, thd, stat_print));
}
/************************************************************************//**
Return 0 on success and non-zero on failure. Note: the bool return type
seems to be abused here, should be an int. */
......@@ -15913,7 +15859,7 @@ innobase_show_status(
return(innodb_show_status(hton, thd, stat_print) != 0);
case HA_ENGINE_MUTEX:
return(innodb_show_latch_status(hton, thd, stat_print) != 0);
return(innodb_show_mutex_status(hton, thd, stat_print) != 0);
case HA_ENGINE_LOGS:
/* Not handled */
......@@ -17229,9 +17175,6 @@ innodb_monitor_set_option(
if (monitor_id == (MONITOR_LATCHES)) {
mutex_monitor.reset();
buf_pool.reset_waited();
dict_sys.for_each_index([](const dict_index_t &i)
{i.lock.reset_waited(); return true;});
}
break;
......@@ -19628,7 +19571,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_mutexes,
i_s_innodb_sys_semaphore_waits,
i_s_innodb_tablespaces_encryption
maria_declare_plugin_end;
......
......@@ -6880,129 +6880,6 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_tablespaces_encryption =
STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
};
namespace Show {
/** INNODB_MUTEXES *********************************************/
/* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_MUTEXES */
static ST_FIELD_INFO innodb_mutexes_fields_info[] =
{
Column("NAME", Varchar(OS_FILE_MAX_PATH), NOT_NULL),
Column("OS_WAITS", ULonglong(), NOT_NULL),
CEnd()
};
} // namespace Show
/*******************************************************************//**
Function to populate INFORMATION_SCHEMA.INNODB_MUTEXES table.
@see innodb_show_rwlock_status
@return 0 on success */
static
int
i_s_innodb_mutexes_fill_table(
/*==========================*/
THD* thd, /*!< in: thread */
TABLE_LIST* tables, /*!< in/out: tables to fill */
Item* ) /*!< in: condition (not used) */
{
DBUG_ENTER("i_s_innodb_mutexes_fill_table");
RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name.str);
if (check_global_access(thd, PROCESS_ACL))
DBUG_RETURN(0);
Field **fields= tables->table->field;
OK(fields[0]->store(STRING_WITH_LEN("buf_block_t::lock"),
system_charset_info));
OK(fields[1]->store(buf_pool.waited(), true));
fields[0]->set_notnull();
fields[1]->set_notnull();
OK(schema_table_store_record(thd, tables->table));
DBUG_RETURN(!dict_sys.for_each_index([&](const dict_index_t &i)
{
uint32_t waited= i.lock.waited();
if (!waited)
return true;
if (fields[1]->store(waited, true))
return false;
std::ostringstream s;
s << i.name << '(' << i.table->name << ')';
return !fields[0]->store(s.str().data(), s.str().size(),
system_charset_info) &&
!schema_table_store_record(thd, tables->table);
}));
}
/*******************************************************************//**
Bind the dynamic table INFORMATION_SCHEMA.INNODB_MUTEXES
@return 0 on success */
static
int
innodb_mutexes_init(
/*================*/
void* p) /*!< in/out: table schema object */
{
ST_SCHEMA_TABLE* schema;
DBUG_ENTER("innodb_mutexes_init");
schema = (ST_SCHEMA_TABLE*) p;
schema->fields_info = Show::innodb_mutexes_fields_info;
schema->fill_table = i_s_innodb_mutexes_fill_table;
DBUG_RETURN(0);
}
UNIV_INTERN struct st_maria_plugin i_s_innodb_mutexes =
{
/* 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_MUTEXES"),
/* plugin author (for SHOW PLUGINS) */
/* const char* */
STRUCT_FLD(author, plugin_author),
/* general descriptive text (for SHOW PLUGINS) */
/* const char* */
STRUCT_FLD(descr, "Information on InnoDB rw-locks"),
/* 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_mutexes_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),
};
namespace Show {
/* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_SYS_SEMAPHORE_WAITS */
static ST_FIELD_INFO innodb_sys_semaphore_waits_fields_info[] =
......
......@@ -59,7 +59,6 @@ extern struct st_maria_plugin i_s_innodb_sys_fields;
extern struct st_maria_plugin i_s_innodb_sys_foreign;
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_mutexes;
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;
......
......@@ -1318,22 +1318,6 @@ class buf_pool_t
@return whether the allocation succeeded */
inline bool create(size_t bytes);
/** Compute the sum of buf_block_t::lock::waited()
@param total_waited sum of buf_block_t::lock::waited() */
void waited(uint64_t &total_waited) const
{
for (const buf_block_t *block= blocks, * const end= blocks + size;
block != end; block++)
total_waited+= block->lock.waited();
}
/** Invoke buf_block_t::lock::reset_waited() on all blocks */
void reset_waited()
{
for (buf_block_t *block= blocks, * const end= blocks + size;
block != end; block++)
block->lock.reset_waited();
}
#ifdef UNIV_DEBUG
/** Find a block that points to a ROW_FORMAT=COMPRESSED page
@param data pointer to the start of a ROW_FORMAT=COMPRESSED page frame
......@@ -1411,30 +1395,6 @@ class buf_pool_t
return size;
}
/** @return sum of buf_block_t::lock::waited() */
uint64_t waited()
{
ut_ad(is_initialised());
uint64_t waited_count= 0;
page_hash.read_lock_all(); /* prevent any race with resize() */
for (const chunk_t *chunk= chunks, * const end= chunks + n_chunks;
chunk != end; chunk++)
chunks->waited(waited_count);
page_hash.read_unlock_all();
return waited_count;
}
/** Invoke buf_block_t::lock::reset_waited() on all blocks */
void reset_waited()
{
ut_ad(is_initialised());
page_hash.read_lock_all(); /* prevent any race with resize() */
for (const chunk_t *chunk= chunks, * const end= chunks + n_chunks;
chunk != end; chunk++)
chunks->reset_waited();
page_hash.read_unlock_all();
}
/** Determine whether a frame is intended to be withdrawn during resize().
@param ptr pointer within a buf_block_t::frame
@return whether the frame will be withdrawn */
......@@ -1836,28 +1796,6 @@ class buf_pool_t
}
}
/** Acquire all latches in shared mode */
void read_lock_all()
{
for (auto n= pad(n_cells) & ~ELEMENTS_PER_LATCH;;
n-= ELEMENTS_PER_LATCH + 1)
{
reinterpret_cast<page_hash_latch&>(array[n]).read_lock();
if (!n)
break;
}
}
/** Release all latches in shared mode */
void read_unlock_all()
{
for (auto n= pad(n_cells) & ~ELEMENTS_PER_LATCH;;
n-= ELEMENTS_PER_LATCH + 1)
{
reinterpret_cast<page_hash_latch&>(array[n]).read_unlock();
if (!n)
break;
}
}
/** Exclusively aqcuire all latches */
inline void write_lock_all();
......
......@@ -1531,19 +1531,6 @@ class dict_sys_t
return table->can_be_evicted ? find<true>(table) : find<false>(table);
}
#endif
private:
/** Invoke f on each index of a table, until it returns false
@param f function object
@param t table
@retval false if f returned false
@retval true if f never returned false */
template<typename F>
inline bool for_each_index(const F &f, const dict_table_t *t);
public:
/** Invoke f on each index of each persistent table, until it returns false
@retval false if f returned false
@retval true if f never returned false */
template<typename F> inline bool for_each_index(const F &f);
/** Move a table to the non-LRU list from the LRU list. */
void prevent_eviction(dict_table_t* table)
......@@ -1611,39 +1598,6 @@ extern dict_sys_t dict_sys;
#define dict_sys_lock() dict_sys.lock(__FILE__, __LINE__)
#define dict_sys_unlock() dict_sys.unlock()
template<typename F>
inline bool dict_sys_t::for_each_index(const F &f, const dict_table_t *t)
{
const dict_index_t *i= UT_LIST_GET_FIRST(t->indexes);
do
{
if (!i->is_corrupted() && !f(*i))
return false;
i= UT_LIST_GET_NEXT(indexes, i);
}
while (i);
return true;
}
template<typename F>
inline bool dict_sys_t::for_each_index(const F &f)
{
struct Locking
{
Locking() { mutex_enter(&dict_sys.mutex); }
~Locking() { mutex_exit(&dict_sys.mutex); }
} locking;
for (const dict_table_t *t= UT_LIST_GET_FIRST(table_non_LRU);
t; t= UT_LIST_GET_NEXT(table_LRU, t))
if (!for_each_index(f, t))
return false;
for (const dict_table_t *t= UT_LIST_GET_FIRST(table_LRU);
t; t= UT_LIST_GET_NEXT(table_LRU, t))
if (!for_each_index(f, t))
return false;
return true;
}
/* Auxiliary structs for checking a table definition @{ */
/* This struct is used to specify the name and type that a column must
......
......@@ -85,44 +85,15 @@ class srw_lock_low final : private rw_lock
#endif
bool rd_lock_try() { uint32_t l; return read_trylock(l); }
bool wr_lock_try() { return write_trylock(); }
/** @return whether the lock was acquired without waiting
@tparam support_u_lock dummy parameter for UNIV_PFS_RWLOCK */
/** @tparam support_u_lock dummy parameter for UNIV_PFS_RWLOCK */
template<bool support_u_lock= false>
bool rd_lock()
{
uint32_t l;
if (read_trylock(l))
return true;
read_lock(l);
return false;
}
/** @return whether the lock was acquired without waiting */
bool u_lock()
{
uint32_t l;
if (update_trylock(l))
return true;
update_lock(l);
return false;
}
void rd_lock() { uint32_t l; if (!read_trylock(l)) read_lock(l); }
void u_lock() { uint32_t l; if (!update_trylock(l)) update_lock(l); }
bool u_lock_try() { uint32_t l; return update_trylock(l); }
/** @return whether the lock was upgraded without waiting */
bool u_wr_upgrade()
{
if (upgrade_trylock())
return true;
write_lock(true);
return false;
}
/** @return whether the lock was acquired without waiting */
void u_wr_upgrade() { if (!upgrade_trylock()) write_lock(true); }
/** @tparam support_u_lock dummy parameter for UNIV_PFS_RWLOCK */
template<bool support_u_lock= false>
bool wr_lock()
{
if (write_trylock())
return true;
write_lock(false);
return false;
}
void wr_lock() { if (!write_trylock()) write_lock(false); }
void rd_unlock();
void u_unlock();
void wr_unlock();
......@@ -147,11 +118,11 @@ class srw_lock
PSI_rwlock *pfs_psi;
template<bool support_u_lock>
ATTRIBUTE_NOINLINE bool psi_rd_lock(const char *file, unsigned line);
ATTRIBUTE_NOINLINE void psi_rd_lock(const char *file, unsigned line);
template<bool support_u_lock>
ATTRIBUTE_NOINLINE bool psi_wr_lock(const char *file, unsigned line);
ATTRIBUTE_NOINLINE bool psi_u_lock(const char *file, unsigned line);
ATTRIBUTE_NOINLINE bool psi_u_wr_upgrade(const char *file, unsigned line);
ATTRIBUTE_NOINLINE void psi_wr_lock(const char *file, unsigned line);
ATTRIBUTE_NOINLINE void psi_u_lock(const char *file, unsigned line);
ATTRIBUTE_NOINLINE void psi_u_wr_upgrade(const char *file, unsigned line);
public:
void init(mysql_pfs_key_t key)
{
......@@ -160,7 +131,7 @@ class srw_lock
}
void destroy()
{
if (pfs_psi)
if (psi_likely(pfs_psi != nullptr))
{
PSI_RWLOCK_CALL(destroy_rwlock)(pfs_psi);
pfs_psi= nullptr;
......@@ -168,52 +139,52 @@ class srw_lock
lock.destroy();
}
template<bool support_u_lock= false>
bool rd_lock(const char *file, unsigned line)
void rd_lock(const char *file, unsigned line)
{
if (psi_likely(pfs_psi != nullptr))
return psi_rd_lock<support_u_lock>(file, line);
psi_rd_lock<support_u_lock>(file, line);
else
return lock.rd_lock();
lock.rd_lock();
}
void rd_unlock()
{
if (pfs_psi)
if (psi_likely(pfs_psi != nullptr))
PSI_RWLOCK_CALL(unlock_rwlock)(pfs_psi);
lock.rd_unlock();
}
bool u_lock(const char *file, unsigned line)
void u_lock(const char *file, unsigned line)
{
if (psi_likely(pfs_psi != nullptr))
return psi_u_lock(file, line);
psi_u_lock(file, line);
else
return lock.u_lock();
lock.u_lock();
}
void u_unlock()
{
if (pfs_psi)
if (psi_likely(pfs_psi != nullptr))
PSI_RWLOCK_CALL(unlock_rwlock)(pfs_psi);
lock.u_unlock();
}
template<bool support_u_lock= false>
bool wr_lock(const char *file, unsigned line)
void wr_lock(const char *file, unsigned line)
{
if (psi_likely(pfs_psi != nullptr))
return psi_wr_lock<support_u_lock>(file, line);
psi_wr_lock<support_u_lock>(file, line);
else
return lock.wr_lock();
lock.wr_lock();
}
void wr_unlock()
{
if (pfs_psi)
if (psi_likely(pfs_psi != nullptr))
PSI_RWLOCK_CALL(unlock_rwlock)(pfs_psi);
lock.wr_unlock();
}
bool u_wr_upgrade(const char *file, unsigned line)
void u_wr_upgrade(const char *file, unsigned line)
{
if (psi_likely(pfs_psi != nullptr))
return psi_u_wr_upgrade(file, line);
psi_u_wr_upgrade(file, line);
else
return lock.u_wr_upgrade();
lock.u_wr_upgrade();
}
bool rd_lock_try() { return lock.rd_lock_try(); }
bool u_lock_try() { return lock.u_lock_try(); }
......
......@@ -44,8 +44,6 @@ class sux_lock final
#endif
/** Numbers of U and X locks. Protected by lock. */
uint32_t recursive;
/** Number of blocking waits */
std::atomic<uint32_t> waits;
#ifdef UNIV_DEBUG
/** Protects readers */
mutable srw_mutex readers_lock;
......@@ -69,7 +67,6 @@ class sux_lock final
lock.SRW_LOCK_INIT(key);
ut_ad(!writer.load(std::memory_order_relaxed));
ut_ad(!recursive);
ut_ad(!waits.load(std::memory_order_relaxed));
ut_d(readers_lock.init());
ut_ad(!readers.load(std::memory_order_relaxed));
}
......@@ -91,11 +88,6 @@ class sux_lock final
lock.destroy();
}
/** @return number of blocking waits */
uint32_t waited() const { return waits.load(std::memory_order_relaxed); }
/** Reset the number of blocking waits */
void reset_waited() { waits.store(0, std::memory_order_relaxed); }
/** needed for dict_index_t::clone() */
inline void operator=(const sux_lock&);
......@@ -284,7 +276,6 @@ template<> inline void sux_lock<srw_lock_low>::init()
lock.init();
ut_ad(!writer.load(std::memory_order_relaxed));
ut_ad(!recursive);
ut_ad(!waits.load(std::memory_order_relaxed));
ut_d(readers_lock.init());
ut_ad(!readers.load(std::memory_order_relaxed));
}
......@@ -294,8 +285,7 @@ inline void sux_lock<srw_lock>::s_lock(const char *file, unsigned line)
{
ut_ad(!have_x());
ut_ad(!have_s());
if (!lock.template rd_lock<true>(file, line))
waits.fetch_add(1, std::memory_order_relaxed);
lock.template rd_lock<true>(file, line);
ut_d(s_lock_register());
}
......@@ -307,8 +297,7 @@ inline void sux_lock<srw_lock>::u_lock(const char *file, unsigned line)
writer_recurse<true>();
else
{
if (!lock.u_lock(file, line))
waits.fetch_add(1, std::memory_order_relaxed);
lock.u_lock(file, line);
ut_ad(!recursive);
recursive= RECURSIVE_U;
set_first_owner(id);
......@@ -323,8 +312,7 @@ inline void sux_lock<srw_lock>::x_lock(const char *file, unsigned line)
writer_recurse<false>();
else
{
if (!lock.template wr_lock<true>(file, line))
waits.fetch_add(1, std::memory_order_relaxed);
lock.template wr_lock<true>(file, line);
ut_ad(!recursive);
recursive= RECURSIVE_X;
set_first_owner(id);
......@@ -335,8 +323,7 @@ template<>
inline void sux_lock<srw_lock>::u_x_upgrade(const char *file, unsigned line)
{
ut_ad(have_u_not_x());
if (!lock.u_wr_upgrade(file, line))
waits.fetch_add(1, std::memory_order_relaxed);
lock.u_wr_upgrade(file, line);
recursive/= RECURSIVE_U;
}
#endif
......@@ -346,8 +333,7 @@ inline void sux_lock<srw_lock_low>::s_lock()
{
ut_ad(!have_x());
ut_ad(!have_s());
if (!lock.template rd_lock<true>())
waits.fetch_add(1, std::memory_order_relaxed);
lock.template rd_lock<true>();
ut_d(s_lock_register());
}
......@@ -359,8 +345,7 @@ inline void sux_lock<srw_lock_low>::u_lock()
writer_recurse<true>();
else
{
if (!lock.u_lock())
waits.fetch_add(1, std::memory_order_relaxed);
lock.u_lock();
ut_ad(!recursive);
recursive= RECURSIVE_U;
set_first_owner(id);
......@@ -378,8 +363,7 @@ inline void sux_lock<srw_lock_low>::x_lock(bool for_io)
}
else
{
if (!lock.template wr_lock<true>())
waits.fetch_add(1, std::memory_order_relaxed);
lock.template wr_lock<true>();
ut_ad(!recursive);
recursive= RECURSIVE_X;
set_first_owner(for_io ? FOR_IO : id);
......@@ -390,8 +374,7 @@ template<>
inline void sux_lock<srw_lock_low>::u_x_upgrade()
{
ut_ad(have_u_not_x());
if (!lock.u_wr_upgrade())
waits.fetch_add(1, std::memory_order_relaxed);
lock.u_wr_upgrade();
recursive/= RECURSIVE_U;
}
......
......@@ -230,7 +230,7 @@ void srw_lock_low::wr_unlock() { write_unlock(); readers_wake(); }
#ifdef UNIV_PFS_RWLOCK
template<bool support_u_lock>
bool srw_lock::psi_rd_lock(const char *file, unsigned line)
void srw_lock::psi_rd_lock(const char *file, unsigned line)
{
PSI_rwlock_locker_state state;
uint32_t l;
......@@ -247,28 +247,26 @@ bool srw_lock::psi_rd_lock(const char *file, unsigned line)
}
else if (!nowait)
lock.read_lock(l);
return nowait;
}
template bool srw_lock::psi_rd_lock<false>(const char *, unsigned);
template bool srw_lock::psi_rd_lock<true>(const char *, unsigned);
template void srw_lock::psi_rd_lock<false>(const char *, unsigned);
template void srw_lock::psi_rd_lock<true>(const char *, unsigned);
bool srw_lock::psi_u_lock(const char *file, unsigned line)
void srw_lock::psi_u_lock(const char *file, unsigned line)
{
PSI_rwlock_locker_state state;
if (PSI_rwlock_locker *locker= PSI_RWLOCK_CALL(start_rwlock_wrwait)
(&state, pfs_psi, PSI_RWLOCK_SHAREDEXCLUSIVELOCK, file, line))
{
const bool nowait= lock.u_lock();
lock.u_lock();
PSI_RWLOCK_CALL(end_rwlock_rdwait)(locker, 0);
return nowait;
}
else
return lock.u_lock();
lock.u_lock();
}
template<bool support_u_lock>
bool srw_lock::psi_wr_lock(const char *file, unsigned line)
void srw_lock::psi_wr_lock(const char *file, unsigned line)
{
PSI_rwlock_locker_state state;
const bool nowait= lock.write_trylock();
......@@ -285,13 +283,12 @@ bool srw_lock::psi_wr_lock(const char *file, unsigned line)
}
else if (!nowait)
lock.wr_lock();
return nowait;
}
template bool srw_lock::psi_wr_lock<false>(const char *, unsigned);
template bool srw_lock::psi_wr_lock<true>(const char *, unsigned);
template void srw_lock::psi_wr_lock<false>(const char *, unsigned);
template void srw_lock::psi_wr_lock<true>(const char *, unsigned);
bool srw_lock::psi_u_wr_upgrade(const char *file, unsigned line)
void srw_lock::psi_u_wr_upgrade(const char *file, unsigned line)
{
PSI_rwlock_locker_state state;
const bool nowait= lock.upgrade_trylock();
......@@ -306,6 +303,5 @@ bool srw_lock::psi_u_wr_upgrade(const char *file, unsigned line)
}
else if (!nowait)
lock.write_lock(true);
return nowait;
}
#endif /* UNIV_PFS_RWLOCK */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment