Commit 6fe99e2d authored by Marko Mäkelä's avatar Marko Mäkelä

Bug 12323643 - CLEAN UP THE INNODB THREAD SHUTDOWN AND ASSERTIONS (WL#5136)

Remove most references to thread id in InnoDB. Three references
remain: the current holder of a mutex, and the current x-lock holder
of a rw-lock, and some references in UNIV_SYNC_DEBUG checks. This
allows MySQL to change the thread associated to a client connection.

Tighten the UNIV_SYNC_DEBUG checks, trying to ensure that no InnoDB
mutex or x-lock is being held when returning control to MySQL. The
only semaphore that may be held is the btr_search_latch in shared mode.

sync_thread_levels_empty_except_dict(): A wrapper for
sync_thread_levels_empty_gen(TRUE).

sync_thread_levels_nonempty_trx(): Check that the current thread is
not holding any InnoDB semaphores, except btr_search_latch if
trx->has_search_latch.

sync_thread_levels_empty(): Unused function; remove.

trx_t: Remove mysql_thread_id and mysql_process_no.

srv_slot_t: Remove id and handle.

row_search_for_mysql(), srv_conc_enter_innodb(),
srv_conc_force_enter_innodb(), srv_conc_force_exit_innodb(),
srv_conc_exit_innodb(), srv_suspend_mysql_thread: Assert
!sync_thread_levels_nonempty_trx().

rb:634 approved by Sunny Bains
parent d8ddf751
...@@ -1716,7 +1716,7 @@ buf_flush_batch( ...@@ -1716,7 +1716,7 @@ buf_flush_batch(
ut_ad(flush_type == BUF_FLUSH_LRU || flush_type == BUF_FLUSH_LIST); ut_ad(flush_type == BUF_FLUSH_LRU || flush_type == BUF_FLUSH_LIST);
#ifdef UNIV_SYNC_DEBUG #ifdef UNIV_SYNC_DEBUG
ut_ad((flush_type != BUF_FLUSH_LIST) ut_ad((flush_type != BUF_FLUSH_LIST)
|| sync_thread_levels_empty_gen(TRUE)); || sync_thread_levels_empty_except_dict());
#endif /* UNIV_SYNC_DEBUG */ #endif /* UNIV_SYNC_DEBUG */
buf_pool_mutex_enter(buf_pool); buf_pool_mutex_enter(buf_pool);
......
...@@ -435,7 +435,7 @@ log_free_check(void) ...@@ -435,7 +435,7 @@ log_free_check(void)
{ {
#ifdef UNIV_SYNC_DEBUG #ifdef UNIV_SYNC_DEBUG
ut_ad(sync_thread_levels_empty_gen(TRUE)); ut_ad(sync_thread_levels_empty_except_dict());
#endif /* UNIV_SYNC_DEBUG */ #endif /* UNIV_SYNC_DEBUG */
if (log_sys->check_flush_or_checkpoint) { if (log_sys->check_flush_or_checkpoint) {
......
...@@ -413,13 +413,6 @@ sync_thread_reset_level( ...@@ -413,13 +413,6 @@ sync_thread_reset_level(
/*====================*/ /*====================*/
void* latch); /*!< in: pointer to a mutex or an rw-lock */ void* latch); /*!< in: pointer to a mutex or an rw-lock */
/******************************************************************//** /******************************************************************//**
Checks that the level array for the current thread is empty.
@return TRUE if empty */
UNIV_INTERN
ibool
sync_thread_levels_empty(void);
/*==========================*/
/******************************************************************//**
Checks if the level array for the current thread contains a Checks if the level array for the current thread contains a
mutex or rw-latch at the specified level. mutex or rw-latch at the specified level.
@return a matching latch, or NULL if not found */ @return a matching latch, or NULL if not found */
...@@ -430,17 +423,33 @@ sync_thread_levels_contains( ...@@ -430,17 +423,33 @@ sync_thread_levels_contains(
ulint level); /*!< in: latching order level ulint level); /*!< in: latching order level
(SYNC_DICT, ...)*/ (SYNC_DICT, ...)*/
/******************************************************************//** /******************************************************************//**
Checks if the level array for the current thread is empty. Checks that the level array for the current thread is empty.
@return a latch, or NULL if empty except the exceptions specified below */ @return a latch, or NULL if empty except the exceptions specified below */
UNIV_INTERN UNIV_INTERN
void* void*
sync_thread_levels_nonempty_gen( sync_thread_levels_nonempty_gen(
/*============================*/ /*============================*/
ibool dict_mutex_allowed); /*!< in: TRUE if dictionary mutex is ibool dict_mutex_allowed) /*!< in: TRUE if dictionary mutex is
allowed to be owned by the thread, allowed to be owned by the thread */
also purge_is_running mutex is __attribute__((warn_unused_result));
allowed */ /******************************************************************//**
#define sync_thread_levels_empty_gen(d) (!sync_thread_levels_nonempty_gen(d)) Checks if the level array for the current thread is empty,
except for data dictionary latches. */
#define sync_thread_levels_empty_except_dict() \
(!sync_thread_levels_nonempty_gen(TRUE))
/******************************************************************//**
Checks if the level array for the current thread is empty,
except for the btr_search_latch.
@return a latch, or NULL if empty except the exceptions specified below */
UNIV_INTERN
void*
sync_thread_levels_nonempty_trx(
/*============================*/
ibool has_search_latch)
/*!< in: TRUE if and only if the thread
is supposed to hold btr_search_latch */
__attribute__((warn_unused_result));
/******************************************************************//** /******************************************************************//**
Gets the debug information for a reserved mutex. */ Gets the debug information for a reserved mutex. */
UNIV_INTERN UNIV_INTERN
......
...@@ -569,11 +569,6 @@ struct trx_struct{ ...@@ -569,11 +569,6 @@ struct trx_struct{
ib_int64_t mysql_log_offset;/* if MySQL binlog is used, this field ib_int64_t mysql_log_offset;/* if MySQL binlog is used, this field
contains the end offset of the binlog contains the end offset of the binlog
entry */ entry */
os_thread_id_t mysql_thread_id;/* id of the MySQL thread associated
with this transaction object */
ulint mysql_process_no;/* since in Linux, 'top' reports
process id's and not thread id's, we
store the process number too */
/*------------------------------*/ /*------------------------------*/
ulint n_mysql_tables_in_use; /* number of Innobase tables ulint n_mysql_tables_in_use; /* number of Innobase tables
used in the processing of the current used in the processing of the current
......
...@@ -1929,7 +1929,6 @@ row_merge_lock_table( ...@@ -1929,7 +1929,6 @@ row_merge_lock_table(
sel_node_t* node; sel_node_t* node;
ut_ad(trx); ut_ad(trx);
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
ut_ad(mode == LOCK_X || mode == LOCK_S); ut_ad(mode == LOCK_X || mode == LOCK_S);
heap = mem_heap_create(512); heap = mem_heap_create(512);
...@@ -2390,7 +2389,6 @@ row_merge_rename_tables( ...@@ -2390,7 +2389,6 @@ row_merge_rename_tables(
pars_info_t* info; pars_info_t* info;
char old_name[MAX_FULL_NAME_LEN + 1]; char old_name[MAX_FULL_NAME_LEN + 1];
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
ut_ad(old_table != new_table); ut_ad(old_table != new_table);
ut_ad(mutex_own(&dict_sys->mutex)); ut_ad(mutex_own(&dict_sys->mutex));
......
...@@ -976,7 +976,6 @@ row_lock_table_autoinc_for_mysql( ...@@ -976,7 +976,6 @@ row_lock_table_autoinc_for_mysql(
ibool was_lock_wait; ibool was_lock_wait;
ut_ad(trx); ut_ad(trx);
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
/* If we already hold an AUTOINC lock on the table then do nothing. /* If we already hold an AUTOINC lock on the table then do nothing.
Note: We peek at the value of the current owner without acquiring Note: We peek at the value of the current owner without acquiring
...@@ -1056,7 +1055,6 @@ row_lock_table_for_mysql( ...@@ -1056,7 +1055,6 @@ row_lock_table_for_mysql(
ibool was_lock_wait; ibool was_lock_wait;
ut_ad(trx); ut_ad(trx);
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
trx->op_info = "setting table lock"; trx->op_info = "setting table lock";
...@@ -1130,7 +1128,6 @@ row_insert_for_mysql( ...@@ -1130,7 +1128,6 @@ row_insert_for_mysql(
ins_node_t* node = prebuilt->ins_node; ins_node_t* node = prebuilt->ins_node;
ut_ad(trx); ut_ad(trx);
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
if (prebuilt->table->ibd_file_missing) { if (prebuilt->table->ibd_file_missing) {
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
...@@ -1364,7 +1361,6 @@ row_update_for_mysql( ...@@ -1364,7 +1361,6 @@ row_update_for_mysql(
trx_t* trx = prebuilt->trx; trx_t* trx = prebuilt->trx;
ut_ad(prebuilt && trx); ut_ad(prebuilt && trx);
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
UT_NOT_USED(mysql_rec); UT_NOT_USED(mysql_rec);
if (prebuilt->table->ibd_file_missing) { if (prebuilt->table->ibd_file_missing) {
...@@ -1532,7 +1528,6 @@ row_unlock_for_mysql( ...@@ -1532,7 +1528,6 @@ row_unlock_for_mysql(
trx_t* trx = prebuilt->trx; trx_t* trx = prebuilt->trx;
ut_ad(prebuilt && trx); ut_ad(prebuilt && trx);
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
if (UNIV_UNLIKELY if (UNIV_UNLIKELY
(!srv_locks_unsafe_for_binlog (!srv_locks_unsafe_for_binlog
...@@ -1834,7 +1829,6 @@ row_create_table_for_mysql( ...@@ -1834,7 +1829,6 @@ row_create_table_for_mysql(
ulint table_name_len; ulint table_name_len;
ulint err; ulint err;
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
#ifdef UNIV_SYNC_DEBUG #ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX)); ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */ #endif /* UNIV_SYNC_DEBUG */
...@@ -2008,7 +2002,6 @@ row_create_index_for_mysql( ...@@ -2008,7 +2002,6 @@ row_create_index_for_mysql(
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX)); ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */ #endif /* UNIV_SYNC_DEBUG */
ut_ad(mutex_own(&(dict_sys->mutex))); ut_ad(mutex_own(&(dict_sys->mutex)));
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
trx->op_info = "creating index"; trx->op_info = "creating index";
...@@ -2411,8 +2404,6 @@ row_discard_tablespace_for_mysql( ...@@ -2411,8 +2404,6 @@ row_discard_tablespace_for_mysql(
table->n_foreign_key_checks_running > 0, we do not allow the table->n_foreign_key_checks_running > 0, we do not allow the
discard. We also reserve the data dictionary latch. */ discard. We also reserve the data dictionary latch. */
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
trx->op_info = "discarding tablespace"; trx->op_info = "discarding tablespace";
trx_start_if_not_started(trx); trx_start_if_not_started(trx);
...@@ -2571,8 +2562,6 @@ row_import_tablespace_for_mysql( ...@@ -2571,8 +2562,6 @@ row_import_tablespace_for_mysql(
ib_uint64_t current_lsn; ib_uint64_t current_lsn;
ulint err = DB_SUCCESS; ulint err = DB_SUCCESS;
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
trx_start_if_not_started(trx); trx_start_if_not_started(trx);
trx->op_info = "importing tablespace"; trx->op_info = "importing tablespace";
...@@ -2756,7 +2745,6 @@ row_truncate_table_for_mysql( ...@@ -2756,7 +2745,6 @@ row_truncate_table_for_mysql(
redo log records on the truncated tablespace, we will assign redo log records on the truncated tablespace, we will assign
a new tablespace identifier to the truncated tablespace. */ a new tablespace identifier to the truncated tablespace. */
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
ut_ad(table); ut_ad(table);
if (srv_created_new_raw) { if (srv_created_new_raw) {
...@@ -3607,7 +3595,6 @@ row_drop_database_for_mysql( ...@@ -3607,7 +3595,6 @@ row_drop_database_for_mysql(
int err = DB_SUCCESS; int err = DB_SUCCESS;
ulint namelen = strlen(name); ulint namelen = strlen(name);
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
ut_a(name != NULL); ut_a(name != NULL);
ut_a(name[namelen - 1] == '/'); ut_a(name[namelen - 1] == '/');
...@@ -3777,7 +3764,6 @@ row_rename_table_for_mysql( ...@@ -3777,7 +3764,6 @@ row_rename_table_for_mysql(
ibool old_is_tmp, new_is_tmp; ibool old_is_tmp, new_is_tmp;
pars_info_t* info = NULL; pars_info_t* info = NULL;
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
ut_a(old_name != NULL); ut_a(old_name != NULL);
ut_a(new_name != NULL); ut_a(new_name != NULL);
......
...@@ -1951,7 +1951,7 @@ row_sel( ...@@ -1951,7 +1951,7 @@ row_sel(
mtr_commit(&mtr); mtr_commit(&mtr);
#ifdef UNIV_SYNC_DEBUG #ifdef UNIV_SYNC_DEBUG
ut_ad(sync_thread_levels_empty_gen(TRUE)); ut_ad(sync_thread_levels_empty_except_dict());
#endif /* UNIV_SYNC_DEBUG */ #endif /* UNIV_SYNC_DEBUG */
err = DB_SUCCESS; err = DB_SUCCESS;
goto func_exit; goto func_exit;
...@@ -1971,7 +1971,7 @@ row_sel( ...@@ -1971,7 +1971,7 @@ row_sel(
mtr_has_extra_clust_latch = FALSE; mtr_has_extra_clust_latch = FALSE;
#ifdef UNIV_SYNC_DEBUG #ifdef UNIV_SYNC_DEBUG
ut_ad(sync_thread_levels_empty_gen(TRUE)); ut_ad(sync_thread_levels_empty_except_dict());
#endif /* UNIV_SYNC_DEBUG */ #endif /* UNIV_SYNC_DEBUG */
goto table_loop; goto table_loop;
...@@ -1988,7 +1988,7 @@ row_sel( ...@@ -1988,7 +1988,7 @@ row_sel(
mtr_commit(&mtr); mtr_commit(&mtr);
#ifdef UNIV_SYNC_DEBUG #ifdef UNIV_SYNC_DEBUG
ut_ad(sync_thread_levels_empty_gen(TRUE)); ut_ad(sync_thread_levels_empty_except_dict());
#endif /* UNIV_SYNC_DEBUG */ #endif /* UNIV_SYNC_DEBUG */
func_exit: func_exit:
...@@ -3370,7 +3370,6 @@ row_search_for_mysql( ...@@ -3370,7 +3370,6 @@ row_search_for_mysql(
rec_offs_init(offsets_); rec_offs_init(offsets_);
ut_ad(index && pcur && search_tuple); ut_ad(index && pcur && search_tuple);
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
if (UNIV_UNLIKELY(prebuilt->table->ibd_file_missing)) { if (UNIV_UNLIKELY(prebuilt->table->ibd_file_missing)) {
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
...@@ -3387,11 +3386,17 @@ row_search_for_mysql( ...@@ -3387,11 +3386,17 @@ row_search_for_mysql(
"InnoDB: how you can resolve the problem.\n", "InnoDB: how you can resolve the problem.\n",
prebuilt->table->name); prebuilt->table->name);
#ifdef UNIV_SYNC_DEBUG
ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
#endif /* UNIV_SYNC_DEBUG */
return(DB_ERROR); return(DB_ERROR);
} }
if (UNIV_UNLIKELY(!prebuilt->index_usable)) { if (UNIV_UNLIKELY(!prebuilt->index_usable)) {
#ifdef UNIV_SYNC_DEBUG
ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
#endif /* UNIV_SYNC_DEBUG */
return(DB_MISSING_HISTORY); return(DB_MISSING_HISTORY);
} }
...@@ -4680,6 +4685,10 @@ row_search_for_mysql( ...@@ -4680,6 +4685,10 @@ row_search_for_mysql(
prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT; prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
} }
} }
#ifdef UNIV_SYNC_DEBUG
ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
#endif /* UNIV_SYNC_DEBUG */
return(err); return(err);
} }
......
...@@ -687,8 +687,6 @@ Unix.*/ ...@@ -687,8 +687,6 @@ Unix.*/
/* Thread slot in the thread table */ /* Thread slot in the thread table */
struct srv_slot_struct{ struct srv_slot_struct{
os_thread_id_t id; /*!< thread id */
os_thread_t handle; /*!< thread handle */
unsigned type:1; /*!< thread type: user, utility etc. */ unsigned type:1; /*!< thread type: user, utility etc. */
unsigned in_use:1; /*!< TRUE if this slot is in use */ unsigned in_use:1; /*!< TRUE if this slot is in use */
unsigned suspended:1; /*!< TRUE if the thread is waiting unsigned suspended:1; /*!< TRUE if the thread is waiting
...@@ -887,8 +885,6 @@ srv_table_reserve_slot( ...@@ -887,8 +885,6 @@ srv_table_reserve_slot(
slot->suspended = FALSE; slot->suspended = FALSE;
slot->type = type; slot->type = type;
ut_ad(srv_slot_get_type(slot) == type); ut_ad(srv_slot_get_type(slot) == type);
slot->id = os_thread_get_curr_id();
slot->handle = os_thread_get_curr();
return(slot); return(slot);
} }
...@@ -907,7 +903,6 @@ srv_suspend_thread( ...@@ -907,7 +903,6 @@ srv_suspend_thread(
ut_ad(mutex_own(&kernel_mutex)); ut_ad(mutex_own(&kernel_mutex));
ut_ad(slot->in_use); ut_ad(slot->in_use);
ut_ad(!slot->suspended); ut_ad(!slot->suspended);
ut_ad(slot->id == os_thread_get_curr_id());
if (srv_print_thread_releases) { if (srv_print_thread_releases) {
fprintf(stderr, fprintf(stderr,
...@@ -962,10 +957,9 @@ srv_release_threads( ...@@ -962,10 +957,9 @@ srv_release_threads(
if (srv_print_thread_releases) { if (srv_print_thread_releases) {
fprintf(stderr, fprintf(stderr,
"Releasing thread %lu type %lu" "Releasing thread type %lu"
" from slot %lu\n", " from slot %lu\n",
(ulong) slot->id, (ulong) type, (ulong) type, (ulong) i);
(ulong) i);
} }
count++; count++;
...@@ -1149,6 +1143,10 @@ srv_conc_enter_innodb( ...@@ -1149,6 +1143,10 @@ srv_conc_enter_innodb(
srv_conc_slot_t* slot = NULL; srv_conc_slot_t* slot = NULL;
ulint i; ulint i;
#ifdef UNIV_SYNC_DEBUG
ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
#endif /* UNIV_SYNC_DEBUG */
if (trx->mysql_thd != NULL if (trx->mysql_thd != NULL
&& thd_is_replication_slave_thread(trx->mysql_thd)) { && thd_is_replication_slave_thread(trx->mysql_thd)) {
...@@ -1272,6 +1270,10 @@ srv_conc_enter_innodb( ...@@ -1272,6 +1270,10 @@ srv_conc_enter_innodb(
/* Go to wait for the event; when a thread leaves InnoDB it will /* Go to wait for the event; when a thread leaves InnoDB it will
release this thread */ release this thread */
ut_ad(!trx->has_search_latch);
#ifdef UNIV_SYNC_DEBUG
ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
#endif /* UNIV_SYNC_DEBUG */
trx->op_info = "waiting in InnoDB queue"; trx->op_info = "waiting in InnoDB queue";
thd_wait_begin(trx->mysql_thd, THD_WAIT_ROW_TABLE_LOCK); thd_wait_begin(trx->mysql_thd, THD_WAIT_ROW_TABLE_LOCK);
...@@ -1307,6 +1309,10 @@ srv_conc_force_enter_innodb( ...@@ -1307,6 +1309,10 @@ srv_conc_force_enter_innodb(
trx_t* trx) /*!< in: transaction object associated with the trx_t* trx) /*!< in: transaction object associated with the
thread */ thread */
{ {
#ifdef UNIV_SYNC_DEBUG
ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
#endif /* UNIV_SYNC_DEBUG */
if (UNIV_LIKELY(!srv_thread_concurrency)) { if (UNIV_LIKELY(!srv_thread_concurrency)) {
return; return;
...@@ -1378,6 +1384,10 @@ srv_conc_force_exit_innodb( ...@@ -1378,6 +1384,10 @@ srv_conc_force_exit_innodb(
if (slot != NULL) { if (slot != NULL) {
os_event_set(slot->event); os_event_set(slot->event);
} }
#ifdef UNIV_SYNC_DEBUG
ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
#endif /* UNIV_SYNC_DEBUG */
} }
/*********************************************************************//** /*********************************************************************//**
...@@ -1389,6 +1399,10 @@ srv_conc_exit_innodb( ...@@ -1389,6 +1399,10 @@ srv_conc_exit_innodb(
trx_t* trx) /*!< in: transaction object associated with the trx_t* trx) /*!< in: transaction object associated with the
thread */ thread */
{ {
#ifdef UNIV_SYNC_DEBUG
ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
#endif /* UNIV_SYNC_DEBUG */
if (trx->n_tickets_to_enter_innodb > 0) { if (trx->n_tickets_to_enter_innodb > 0) {
/* We will pretend the thread is still inside InnoDB though it /* We will pretend the thread is still inside InnoDB though it
now leaves the InnoDB engine. In this way we save now leaves the InnoDB engine. In this way we save
...@@ -1505,10 +1519,9 @@ srv_table_reserve_slot_for_mysql(void) ...@@ -1505,10 +1519,9 @@ srv_table_reserve_slot_for_mysql(void)
slot = srv_mysql_table + i; slot = srv_mysql_table + i;
fprintf(stderr, fprintf(stderr,
"Slot %lu: thread id %lu, type %lu," "Slot %lu: thread type %lu,"
" in use %lu, susp %lu, time %lu\n", " in use %lu, susp %lu, time %lu\n",
(ulong) i, (ulong) i,
(ulong) os_thread_pf(slot->id),
(ulong) slot->type, (ulong) slot->type,
(ulong) slot->in_use, (ulong) slot->in_use,
(ulong) slot->suspended, (ulong) slot->suspended,
...@@ -1525,8 +1538,6 @@ srv_table_reserve_slot_for_mysql(void) ...@@ -1525,8 +1538,6 @@ srv_table_reserve_slot_for_mysql(void)
ut_a(slot->in_use == FALSE); ut_a(slot->in_use == FALSE);
slot->in_use = TRUE; slot->in_use = TRUE;
slot->id = os_thread_get_curr_id();
slot->handle = os_thread_get_curr();
return(slot); return(slot);
} }
...@@ -1733,6 +1744,10 @@ srv_suspend_mysql_thread( ...@@ -1733,6 +1744,10 @@ srv_suspend_mysql_thread(
trx->error_state = DB_INTERRUPTED; trx->error_state = DB_INTERRUPTED;
} }
#ifdef UNIV_SYNC_DEBUG
ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
#endif /* UNIV_SYNC_DEBUG */
} }
/********************************************************************//** /********************************************************************//**
......
...@@ -189,12 +189,12 @@ UNIV_INTERN sync_array_t* sync_primary_wait_array; ...@@ -189,12 +189,12 @@ UNIV_INTERN sync_array_t* sync_primary_wait_array;
/** This variable is set to TRUE when sync_init is called */ /** This variable is set to TRUE when sync_init is called */
UNIV_INTERN ibool sync_initialized = FALSE; UNIV_INTERN ibool sync_initialized = FALSE;
#ifdef UNIV_SYNC_DEBUG
/** An acquired mutex or rw-lock and its level in the latching order */ /** An acquired mutex or rw-lock and its level in the latching order */
typedef struct sync_level_struct sync_level_t; typedef struct sync_level_struct sync_level_t;
/** Mutexes or rw-locks held by a thread */ /** Mutexes or rw-locks held by a thread */
typedef struct sync_thread_struct sync_thread_t; typedef struct sync_thread_struct sync_thread_t;
#ifdef UNIV_SYNC_DEBUG
/** The latch levels currently owned by threads are stored in this data /** The latch levels currently owned by threads are stored in this data
structure; the size of this array is OS_THREAD_MAX_N */ structure; the size of this array is OS_THREAD_MAX_N */
...@@ -221,7 +221,6 @@ UNIV_INTERN mysql_pfs_key_t mutex_list_mutex_key; ...@@ -221,7 +221,6 @@ UNIV_INTERN mysql_pfs_key_t mutex_list_mutex_key;
#ifdef UNIV_SYNC_DEBUG #ifdef UNIV_SYNC_DEBUG
/** Latching order checks start when this is set TRUE */ /** Latching order checks start when this is set TRUE */
UNIV_INTERN ibool sync_order_checks_on = FALSE; UNIV_INTERN ibool sync_order_checks_on = FALSE;
#endif /* UNIV_SYNC_DEBUG */
/** Number of slots reserved for each OS thread in the sync level array */ /** Number of slots reserved for each OS thread in the sync level array */
static const ulint SYNC_THREAD_N_LEVELS = 10000; static const ulint SYNC_THREAD_N_LEVELS = 10000;
...@@ -258,6 +257,7 @@ struct sync_level_struct{ ...@@ -258,6 +257,7 @@ struct sync_level_struct{
the ordinal value of the next free the ordinal value of the next free
element */ element */
}; };
#endif /* UNIV_SYNC_DEBUG */
/******************************************************************//** /******************************************************************//**
Creates, or rather, initializes a mutex object in a specified memory Creates, or rather, initializes a mutex object in a specified memory
...@@ -1020,9 +1020,7 @@ void* ...@@ -1020,9 +1020,7 @@ void*
sync_thread_levels_nonempty_gen( sync_thread_levels_nonempty_gen(
/*============================*/ /*============================*/
ibool dict_mutex_allowed) /*!< in: TRUE if dictionary mutex is ibool dict_mutex_allowed) /*!< in: TRUE if dictionary mutex is
allowed to be owned by the thread, allowed to be owned by the thread */
also purge_is_running mutex is
allowed */
{ {
ulint i; ulint i;
sync_arr_t* arr; sync_arr_t* arr;
...@@ -1069,14 +1067,61 @@ sync_thread_levels_nonempty_gen( ...@@ -1069,14 +1067,61 @@ sync_thread_levels_nonempty_gen(
} }
/******************************************************************//** /******************************************************************//**
Checks that the level array for the current thread is empty. Checks if the level array for the current thread is empty,
@return TRUE if empty */ except for the btr_search_latch.
@return a latch, or NULL if empty except the exceptions specified below */
UNIV_INTERN UNIV_INTERN
ibool void*
sync_thread_levels_empty(void) sync_thread_levels_nonempty_trx(
/*==========================*/ /*============================*/
ibool has_search_latch)
/*!< in: TRUE if and only if the thread
is supposed to hold btr_search_latch */
{ {
return(sync_thread_levels_empty_gen(FALSE)); ulint i;
sync_arr_t* arr;
sync_thread_t* thread_slot;
if (!sync_order_checks_on) {
return(NULL);
}
ut_a(!has_search_latch
|| sync_thread_levels_contains(SYNC_SEARCH_SYS));
mutex_enter(&sync_thread_mutex);
thread_slot = sync_thread_level_arrays_find_slot();
if (thread_slot == NULL) {
mutex_exit(&sync_thread_mutex);
return(NULL);
}
arr = thread_slot->levels;
for (i = 0; i < arr->n_elems; ++i) {
const sync_level_t* slot;
slot = &arr->elems[i];
if (slot->latch != NULL
&& (!has_search_latch
|| slot->level != SYNC_SEARCH_SYS)) {
mutex_exit(&sync_thread_mutex);
ut_error;
return(slot->latch);
}
}
mutex_exit(&sync_thread_mutex);
return(NULL);
} }
/******************************************************************//** /******************************************************************//**
......
...@@ -460,10 +460,6 @@ trx_rollback_active( ...@@ -460,10 +460,6 @@ trx_rollback_active(
(ulong) rows_to_undo, unit); (ulong) rows_to_undo, unit);
mutex_exit(&kernel_mutex); mutex_exit(&kernel_mutex);
trx->mysql_thread_id = os_thread_get_curr_id();
trx->mysql_process_no = os_proc_get_number();
if (trx_get_dict_operation(trx) != TRX_DICT_OP_NONE) { if (trx_get_dict_operation(trx) != TRX_DICT_OP_NONE) {
row_mysql_lock_data_dictionary(trx); row_mysql_lock_data_dictionary(trx);
dictionary_locked = TRUE; dictionary_locked = TRUE;
......
...@@ -214,10 +214,6 @@ trx_allocate_for_mysql(void) ...@@ -214,10 +214,6 @@ trx_allocate_for_mysql(void)
mutex_exit(&kernel_mutex); mutex_exit(&kernel_mutex);
trx->mysql_thread_id = os_thread_get_curr_id();
trx->mysql_process_no = os_proc_get_number();
return(trx); return(trx);
} }
...@@ -1729,12 +1725,6 @@ trx_print( ...@@ -1729,12 +1725,6 @@ trx_print(
fprintf(f, " state %lu", (ulong) trx->conc_state); fprintf(f, " state %lu", (ulong) trx->conc_state);
} }
#ifdef UNIV_LINUX
fprintf(f, ", process no %lu", trx->mysql_process_no);
#endif
fprintf(f, ", OS thread id %lu",
(ulong) os_thread_pf(trx->mysql_thread_id));
if (*trx->op_info) { if (*trx->op_info) {
putc(' ', f); putc(' ', f);
fputs(trx->op_info, f); fputs(trx->op_info, f);
......
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