mirror of
https://github.com/MariaDB/server.git
synced 2025-02-01 19:41:47 +01:00
branches/zip: lock_rec_validate_page(): Only validate the record
queues when the thread is not holding a space->latch. When UNIV_DEBUG is defined while UNIV_SYNC_DEBUG is not, latching order violations will still occur and deadlocks will be possible. sync_thread_levels_nonempty_gen(): Renamed from sync_thread_levels_empty_gen(). Return the violating latch or NULL instead of FALSE or TRUE, except that there will be a ut_error before the non-NULL return. sync_thread_levels_empty_gen(): A macro that negates the return value of sync_thread_levels_nonempty_gen(). sync_thread_levels_contains(): New function, based on sync_thread_levels_nonempty_gen(). This should fix Issue #441.
This commit is contained in:
parent
17c879e27b
commit
d018a80608
3 changed files with 82 additions and 14 deletions
|
@ -238,16 +238,27 @@ ibool
|
||||||
sync_thread_levels_empty(void);
|
sync_thread_levels_empty(void);
|
||||||
/*==========================*/
|
/*==========================*/
|
||||||
/******************************************************************//**
|
/******************************************************************//**
|
||||||
Checks that the level array for the current thread is empty.
|
Checks if the level array for the current thread contains a
|
||||||
@return TRUE if empty except the exceptions specified below */
|
mutex or rw-latch at the specified level.
|
||||||
|
@return a matching latch, or NULL if not found */
|
||||||
UNIV_INTERN
|
UNIV_INTERN
|
||||||
ibool
|
void*
|
||||||
sync_thread_levels_empty_gen(
|
sync_thread_levels_contains(
|
||||||
/*=========================*/
|
/*========================*/
|
||||||
|
ulint level); /*!< in: latching order level
|
||||||
|
(SYNC_DICT, ...)*/
|
||||||
|
/******************************************************************//**
|
||||||
|
Checks if the level array for the current thread is empty.
|
||||||
|
@return a latch, or NULL if empty except the exceptions specified below */
|
||||||
|
UNIV_INTERN
|
||||||
|
void*
|
||||||
|
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
|
also purge_is_running mutex is
|
||||||
allowed */
|
allowed */
|
||||||
|
#define sync_thread_levels_empty_gen(d) (!sync_thread_levels_nonempty_gen(d))
|
||||||
/******************************************************************//**
|
/******************************************************************//**
|
||||||
Gets the debug information for a reserved mutex. */
|
Gets the debug information for a reserved mutex. */
|
||||||
UNIV_INTERN
|
UNIV_INTERN
|
||||||
|
|
|
@ -4766,6 +4766,13 @@ loop:
|
||||||
|| lock->trx->conc_state == TRX_PREPARED
|
|| lock->trx->conc_state == TRX_PREPARED
|
||||||
|| lock->trx->conc_state == TRX_COMMITTED_IN_MEMORY);
|
|| lock->trx->conc_state == TRX_COMMITTED_IN_MEMORY);
|
||||||
|
|
||||||
|
# ifdef UNIV_SYNC_DEBUG
|
||||||
|
/* Only validate the record queues when this thread is not
|
||||||
|
holding a space->latch. Deadlocks are possible due to
|
||||||
|
latching order violation when UNIV_DEBUG is defined while
|
||||||
|
UNIV_SYNC_DEBUG is not. */
|
||||||
|
if (!sync_thread_levels_contains(SYNC_FSP))
|
||||||
|
# endif /* UNIV_SYNC_DEBUG */
|
||||||
for (i = nth_bit; i < lock_rec_get_n_bits(lock); i++) {
|
for (i = nth_bit; i < lock_rec_get_n_bits(lock); i++) {
|
||||||
|
|
||||||
if (i == 1 || lock_rec_get_nth_bit(lock, i)) {
|
if (i == 1 || lock_rec_get_nth_bit(lock, i)) {
|
||||||
|
|
|
@ -958,12 +958,62 @@ sync_thread_levels_contain(
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************//**
|
/******************************************************************//**
|
||||||
Checks that the level array for the current thread is empty.
|
Checks if the level array for the current thread contains a
|
||||||
@return TRUE if empty except the exceptions specified below */
|
mutex or rw-latch at the specified level.
|
||||||
|
@return a matching latch, or NULL if not found */
|
||||||
UNIV_INTERN
|
UNIV_INTERN
|
||||||
ibool
|
void*
|
||||||
sync_thread_levels_empty_gen(
|
sync_thread_levels_contains(
|
||||||
/*=========================*/
|
/*========================*/
|
||||||
|
ulint level) /*!< in: latching order level
|
||||||
|
(SYNC_DICT, ...)*/
|
||||||
|
{
|
||||||
|
sync_level_t* arr;
|
||||||
|
sync_thread_t* thread_slot;
|
||||||
|
sync_level_t* slot;
|
||||||
|
ulint i;
|
||||||
|
|
||||||
|
if (!sync_order_checks_on) {
|
||||||
|
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 < SYNC_THREAD_N_LEVELS; i++) {
|
||||||
|
|
||||||
|
slot = sync_thread_levels_get_nth(arr, i);
|
||||||
|
|
||||||
|
if (slot->latch != NULL && slot->level == level) {
|
||||||
|
|
||||||
|
mutex_exit(&sync_thread_mutex);
|
||||||
|
return(slot->latch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_exit(&sync_thread_mutex);
|
||||||
|
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************//**
|
||||||
|
Checks that the level array for the current thread is empty.
|
||||||
|
@return a latch, or NULL if empty except the exceptions specified below */
|
||||||
|
UNIV_INTERN
|
||||||
|
void*
|
||||||
|
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
|
also purge_is_running mutex is
|
||||||
|
@ -976,7 +1026,7 @@ sync_thread_levels_empty_gen(
|
||||||
|
|
||||||
if (!sync_order_checks_on) {
|
if (!sync_order_checks_on) {
|
||||||
|
|
||||||
return(TRUE);
|
return(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_enter(&sync_thread_mutex);
|
mutex_enter(&sync_thread_mutex);
|
||||||
|
@ -987,7 +1037,7 @@ sync_thread_levels_empty_gen(
|
||||||
|
|
||||||
mutex_exit(&sync_thread_mutex);
|
mutex_exit(&sync_thread_mutex);
|
||||||
|
|
||||||
return(TRUE);
|
return(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
arr = thread_slot->levels;
|
arr = thread_slot->levels;
|
||||||
|
@ -1004,13 +1054,13 @@ sync_thread_levels_empty_gen(
|
||||||
mutex_exit(&sync_thread_mutex);
|
mutex_exit(&sync_thread_mutex);
|
||||||
ut_error;
|
ut_error;
|
||||||
|
|
||||||
return(FALSE);
|
return(slot->latch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_exit(&sync_thread_mutex);
|
mutex_exit(&sync_thread_mutex);
|
||||||
|
|
||||||
return(TRUE);
|
return(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************//**
|
/******************************************************************//**
|
||||||
|
|
Loading…
Add table
Reference in a new issue