diff options
Diffstat (limited to 'storage/xtradb/sync/sync0sync.c')
-rw-r--r-- | storage/xtradb/sync/sync0sync.c | 535 |
1 files changed, 336 insertions, 199 deletions
diff --git a/storage/xtradb/sync/sync0sync.c b/storage/xtradb/sync/sync0sync.c index 225f28df78e..4b35d6db177 100644 --- a/storage/xtradb/sync/sync0sync.c +++ b/storage/xtradb/sync/sync0sync.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved. +Copyright (c) 1995, 2011, Innobase Oy. All Rights Reserved. Copyright (c) 2008, Google Inc. Portions of this file contain modifications contributed and copyrighted by @@ -40,6 +40,10 @@ Created 9/5/1995 Heikki Tuuri #include "srv0srv.h" #include "buf0types.h" #include "os0sync.h" /* for HAVE_ATOMIC_BUILTINS */ +#ifdef UNIV_SYNC_DEBUG +# include "srv0start.h" /* srv_is_being_started */ +#endif /* UNIV_SYNC_DEBUG */ +#include "ha_prototypes.h" /* REASONS FOR IMPLEMENTING THE SPIN LOCK MUTEX @@ -167,13 +171,13 @@ Q.E.D. */ /** The number of iterations in the mutex_spin_wait() spin loop. Intended for performance monitoring. */ -static ib_int64_t mutex_spin_round_count = 0; +UNIV_INTERN ib_int64_t mutex_spin_round_count = 0; /** The number of mutex_spin_wait() calls. Intended for performance monitoring. */ -static ib_int64_t mutex_spin_wait_count = 0; +UNIV_INTERN ib_int64_t mutex_spin_wait_count = 0; /** The number of OS waits in mutex_spin_wait(). Intended for performance monitoring. */ -static ib_int64_t mutex_os_wait_count = 0; +UNIV_INTERN ib_int64_t mutex_os_wait_count = 0; /** The number of mutex_exit() calls. Intended for performance monitoring. */ UNIV_INTERN ib_int64_t mutex_exit_count = 0; @@ -185,12 +189,12 @@ UNIV_INTERN sync_array_t* sync_primary_wait_array; /** This variable is set to TRUE when sync_init is called */ UNIV_INTERN ibool sync_initialized = FALSE; +#ifdef UNIV_SYNC_DEBUG /** An acquired mutex or rw-lock and its level in the latching order */ typedef struct sync_level_struct sync_level_t; /** Mutexes or rw-locks held by a thread */ typedef struct sync_thread_struct sync_thread_t; -#ifdef UNIV_SYNC_DEBUG /** The latch levels currently owned by threads are stored in this data structure; the size of this array is OS_THREAD_MAX_N */ @@ -198,6 +202,10 @@ UNIV_INTERN sync_thread_t* sync_thread_level_arrays; /** Mutex protecting sync_thread_level_arrays */ UNIV_INTERN mutex_t sync_thread_mutex; + +# ifdef UNIV_PFS_MUTEX +UNIV_INTERN mysql_pfs_key_t sync_thread_mutex_key; +# endif /* UNIV_PFS_MUTEX */ #endif /* UNIV_SYNC_DEBUG */ /** Global list of database mutexes (not OS mutexes) created. */ @@ -206,27 +214,50 @@ UNIV_INTERN ut_list_base_node_t mutex_list; /** Mutex protecting the mutex_list variable */ UNIV_INTERN mutex_t mutex_list_mutex; +#ifdef UNIV_PFS_MUTEX +UNIV_INTERN mysql_pfs_key_t mutex_list_mutex_key; +#endif /* UNIV_PFS_MUTEX */ + #ifdef UNIV_SYNC_DEBUG /** Latching order checks start when this is set TRUE */ 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 */ +static const ulint SYNC_THREAD_N_LEVELS = 10000; + +typedef struct sync_arr_struct sync_arr_t; + +/** Array for tracking sync levels per thread. */ +struct sync_arr_struct { + ulint in_use; /*!< Number of active cells */ + ulint n_elems; /*!< Number of elements in the array */ + ulint max_elems; /*!< Maximum elements */ + ulint next_free; /*!< ULINT_UNDEFINED or index of next + free slot */ + sync_level_t* elems; /*!< Array elements */ +}; /** Mutexes or rw-locks held by a thread */ struct sync_thread_struct{ - os_thread_id_t id; /*!< OS thread id */ - sync_level_t* levels; /*!< level array for this thread; if - this is NULL this slot is unused */ + os_thread_id_t id; /*!< OS thread id */ + sync_arr_t* levels; /*!< level array for this thread; if + this is NULL this slot is unused */ }; -/** Number of slots reserved for each OS thread in the sync level array */ -#define SYNC_THREAD_N_LEVELS 10000 - /** An acquired mutex or rw-lock and its level in the latching order */ struct sync_level_struct{ - void* latch; /*!< pointer to a mutex or an rw-lock; NULL means that - the slot is empty */ - ulint level; /*!< level of the latch in the latching order */ + void* latch; /*!< pointer to a mutex or an + rw-lock; NULL means that + the slot is empty */ + ulint level; /*!< level of the latch in the + latching order. This field is + overloaded to serve as a node in a + linked list of free nodes too. When + latch == NULL then this will contain + the ordinal value of the next free + element */ }; +#endif /* UNIV_SYNC_DEBUG */ /******************************************************************//** Creates, or rather, initializes a mutex object in a specified memory @@ -238,14 +269,14 @@ void mutex_create_func( /*==============*/ mutex_t* mutex, /*!< in: pointer to memory */ - const char* cmutex_name, /*!< in: mutex name */ #ifdef UNIV_DEBUG # ifdef UNIV_SYNC_DEBUG ulint level, /*!< in: level */ # endif /* UNIV_SYNC_DEBUG */ -#endif /* UNIV_DEBUG */ const char* cfile_name, /*!< in: file name where created */ - ulint cline) /*!< in: file line where created */ + ulint cline, /*!< in: file line where created */ +#endif /* UNIV_DEBUG */ + const char* cmutex_name) /*!< in: mutex name */ { #if defined(HAVE_ATOMIC_BUILTINS) mutex_reset_lock_word(mutex); @@ -304,13 +335,14 @@ mutex_create_func( } /******************************************************************//** +NOTE! Use the corresponding macro mutex_free(), not directly this function! Calling this function is obligatory only if the memory buffer containing the mutex is freed. Removes a mutex object from the mutex list. The mutex is checked to be in the reset state. */ UNIV_INTERN void -mutex_free( -/*=======*/ +mutex_free_func( +/*============*/ mutex_t* mutex) /*!< in: mutex */ { ut_ad(mutex_validate(mutex)); @@ -745,27 +777,28 @@ mutex_n_reserved(void) /*==================*/ { mutex_t* mutex; - ulint count = 0; + ulint count = 0; mutex_enter(&mutex_list_mutex); - mutex = UT_LIST_GET_FIRST(mutex_list); + for (mutex = UT_LIST_GET_FIRST(mutex_list); + mutex != NULL; + mutex = UT_LIST_GET_NEXT(list, mutex)) { - while (mutex != NULL) { if (mutex_get_lock_word(mutex) != 0) { count++; } - - mutex = UT_LIST_GET_NEXT(list, mutex); } mutex_exit(&mutex_list_mutex); ut_a(count >= 1); - return(count - 1); /* Subtract one, because this function itself - was holding one mutex (mutex_list_mutex) */ + /* Subtract one, because this function itself was holding + one mutex (mutex_list_mutex) */ + + return(count - 1); } /******************************************************************//** @@ -781,20 +814,6 @@ sync_all_freed(void) } /******************************************************************//** -Gets the value in the nth slot in the thread level arrays. -@return pointer to thread slot */ -static -sync_thread_t* -sync_thread_level_arrays_get_nth( -/*=============================*/ - ulint n) /*!< in: slot number */ -{ - ut_ad(n < OS_THREAD_MAX_N); - - return(sync_thread_level_arrays + n); -} - -/******************************************************************//** Looks for the thread slot for the calling thread. @return pointer to thread slot, NULL if not found */ static @@ -803,15 +822,15 @@ sync_thread_level_arrays_find_slot(void) /*====================================*/ { - sync_thread_t* slot; - os_thread_id_t id; ulint i; + os_thread_id_t id; id = os_thread_get_curr_id(); for (i = 0; i < OS_THREAD_MAX_N; i++) { + sync_thread_t* slot; - slot = sync_thread_level_arrays_get_nth(i); + slot = &sync_thread_level_arrays[i]; if (slot->levels && os_thread_eq(slot->id, id)) { @@ -831,12 +850,12 @@ sync_thread_level_arrays_find_free(void) /*====================================*/ { - sync_thread_t* slot; ulint i; for (i = 0; i < OS_THREAD_MAX_N; i++) { + sync_thread_t* slot; - slot = sync_thread_level_arrays_get_nth(i); + slot = &sync_thread_level_arrays[i]; if (slot->levels == NULL) { @@ -848,19 +867,44 @@ sync_thread_level_arrays_find_free(void) } /******************************************************************//** -Gets the value in the nth slot in the thread level array. -@return pointer to level slot */ +Print warning. */ static -sync_level_t* -sync_thread_levels_get_nth( -/*=======================*/ - sync_level_t* arr, /*!< in: pointer to level array for an OS - thread */ - ulint n) /*!< in: slot number */ +void +sync_print_warning( +/*===============*/ + const sync_level_t* slot) /*!< in: slot for which to + print warning */ { - ut_ad(n < SYNC_THREAD_N_LEVELS); + mutex_t* mutex; - return(arr + n); + mutex = slot->latch; + + if (mutex->magic_n == MUTEX_MAGIC_N) { + fprintf(stderr, + "Mutex '%s'\n", + mutex->cmutex_name); + + if (mutex_get_lock_word(mutex) != 0) { + ulint line; + const char* file_name; + os_thread_id_t thread_id; + + mutex_get_debug_info( + mutex, &file_name, &line, &thread_id); + + fprintf(stderr, + "InnoDB: Locked mutex:" + " addr %p thread %ld file %s line %ld\n", + (void*) mutex, os_thread_pf(thread_id), + file_name, (ulong) line); + } else { + fputs("Not locked\n", stderr); + } + } else { + rw_lock_t* lock = slot->latch; + + rw_lock_print(lock); + } } /******************************************************************//** @@ -871,68 +915,29 @@ static ibool sync_thread_levels_g( /*=================*/ - sync_level_t* arr, /*!< in: pointer to level array for an OS + sync_arr_t* arr, /*!< in: pointer to level array for an OS thread */ ulint limit, /*!< in: level limit */ ulint warn) /*!< in: TRUE=display a diagnostic message */ { - sync_level_t* slot; - rw_lock_t* lock; - mutex_t* mutex; ulint i; - for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) { - - slot = sync_thread_levels_get_nth(arr, i); - - if (slot->latch != NULL) { - if (slot->level <= limit) { - - if (!warn) { - - return(FALSE); - } + for (i = 0; i < arr->n_elems; i++) { + const sync_level_t* slot; - lock = slot->latch; - mutex = slot->latch; + slot = &arr->elems[i]; + if (slot->latch != NULL && slot->level <= limit) { + if (warn) { fprintf(stderr, "InnoDB: sync levels should be" " > %lu but a level is %lu\n", (ulong) limit, (ulong) slot->level); - if (mutex->magic_n == MUTEX_MAGIC_N) { - fprintf(stderr, - "Mutex '%s'\n", - mutex->cmutex_name); - - if (mutex_get_lock_word(mutex) != 0) { - const char* file_name; - ulint line; - os_thread_id_t thread_id; - - mutex_get_debug_info( - mutex, &file_name, - &line, &thread_id); - - fprintf(stderr, - "InnoDB: Locked mutex:" - " addr %p thread %ld" - " file %s line %ld\n", - (void*) mutex, - os_thread_pf( - thread_id), - file_name, - (ulong) line); - } else { - fputs("Not locked\n", stderr); - } - } else { - rw_lock_print(lock); - } - - return(FALSE); + sync_print_warning(slot); } + + return(FALSE); } } @@ -941,31 +946,29 @@ sync_thread_levels_g( /******************************************************************//** Checks if the level value is stored in the level array. -@return TRUE if stored */ +@return slot if found or NULL */ static -ibool +const sync_level_t* sync_thread_levels_contain( /*=======================*/ - sync_level_t* arr, /*!< in: pointer to level array for an OS + sync_arr_t* arr, /*!< in: pointer to level array for an OS thread */ ulint level) /*!< in: level */ { - sync_level_t* slot; ulint i; - for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) { + for (i = 0; i < arr->n_elems; i++) { + const sync_level_t* slot; - slot = sync_thread_levels_get_nth(arr, i); + slot = &arr->elems[i]; - if (slot->latch != NULL) { - if (slot->level == level) { + if (slot->latch != NULL && slot->level == level) { - return(TRUE); - } + return(slot); } } - return(FALSE); + return(NULL); } /******************************************************************//** @@ -979,10 +982,9 @@ 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; + sync_arr_t* arr; + sync_thread_t* thread_slot; if (!sync_order_checks_on) { @@ -1002,9 +1004,10 @@ sync_thread_levels_contains( arr = thread_slot->levels; - for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) { + for (i = 0; i < arr->n_elems; i++) { + sync_level_t* slot; - slot = sync_thread_levels_get_nth(arr, i); + slot = &arr->elems[i]; if (slot->latch != NULL && slot->level == level) { @@ -1026,14 +1029,11 @@ void* sync_thread_levels_nonempty_gen( /*============================*/ ibool dict_mutex_allowed) /*!< in: TRUE if dictionary mutex is - allowed to be owned by the thread, - also purge_is_running mutex is - allowed */ + allowed to be owned by the thread */ { - sync_level_t* arr; - sync_thread_t* thread_slot; - sync_level_t* slot; ulint i; + sync_arr_t* arr; + sync_thread_t* thread_slot; if (!sync_order_checks_on) { @@ -1053,9 +1053,10 @@ sync_thread_levels_nonempty_gen( arr = thread_slot->levels; - for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) { + for (i = 0; i < arr->n_elems; ++i) { + const sync_level_t* slot; - slot = sync_thread_levels_get_nth(arr, i); + slot = &arr->elems[i]; if (slot->latch != NULL && (!dict_mutex_allowed @@ -1075,14 +1076,61 @@ sync_thread_levels_nonempty_gen( } /******************************************************************//** -Checks that the level array for the current thread is empty. -@return TRUE if empty */ +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 -ibool -sync_thread_levels_empty(void) -/*==========================*/ +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); } /******************************************************************//** @@ -1097,10 +1145,10 @@ sync_thread_add_level( ulint level) /*!< in: level in the latching order; if SYNC_LEVEL_VARYING, nothing is done */ { - sync_level_t* array; + ulint i; sync_level_t* slot; + sync_arr_t* array; sync_thread_t* thread_slot; - ulint i; if (!sync_order_checks_on) { @@ -1125,20 +1173,23 @@ sync_thread_add_level( thread_slot = sync_thread_level_arrays_find_slot(); if (thread_slot == NULL) { - /* We have to allocate the level array for a new thread */ - array = ut_malloc(sizeof(sync_level_t) * SYNC_THREAD_N_LEVELS); + ulint sz; - thread_slot = sync_thread_level_arrays_find_free(); + sz = sizeof(*array) + + (sizeof(*array->elems) * SYNC_THREAD_N_LEVELS); - thread_slot->id = os_thread_get_curr_id(); - thread_slot->levels = array; + /* We have to allocate the level array for a new thread */ + array = calloc(sz, sizeof(char)); + ut_a(array != NULL); - for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) { + array->next_free = ULINT_UNDEFINED; + array->max_elems = SYNC_THREAD_N_LEVELS; + array->elems = (sync_level_t*) &array[1]; - slot = sync_thread_levels_get_nth(array, i); + thread_slot = sync_thread_level_arrays_find_free(); - slot->latch = NULL; - } + thread_slot->levels = array; + thread_slot->id = os_thread_get_curr_id(); } array = thread_slot->levels; @@ -1154,24 +1205,24 @@ sync_thread_add_level( case SYNC_TREE_NODE_FROM_HASH: /* Do no order checking */ break; + case SYNC_TRX_SYS_HEADER: + if (srv_is_being_started) { + /* This is violated during trx_sys_create_rsegs() + when creating additional rollback segments when + upgrading in innobase_start_or_create_for_mysql(). */ + break; + } case SYNC_MEM_POOL: case SYNC_MEM_HASH: case SYNC_RECV: case SYNC_WORK_QUEUE: case SYNC_LOG: + case SYNC_LOG_FLUSH_ORDER: case SYNC_THR_LOCAL: case SYNC_ANY_LATCH: - case SYNC_TRX_SYS_HEADER: + case SYNC_OUTER_ANY_LATCH: case SYNC_FILE_FORMAT_TAG: case SYNC_DOUBLEWRITE: - case SYNC_BUF_LRU_LIST: - case SYNC_BUF_FLUSH_LIST: - case SYNC_BUF_PAGE_HASH: - case SYNC_BUF_FREE_LIST: - case SYNC_BUF_ZIP_FREE: - case SYNC_BUF_ZIP_HASH: - case SYNC_BUF_POOL: - case SYNC_SEARCH_SYS: case SYNC_SEARCH_SYS_CONF: case SYNC_TRX_LOCK_HEAP: case SYNC_KERNEL: @@ -1179,7 +1230,7 @@ sync_thread_add_level( case SYNC_RSEG: case SYNC_TRX_UNDO: case SYNC_PURGE_LATCH: - case SYNC_PURGE_SYS: + case SYNC_PURGE_QUEUE: case SYNC_DICT_AUTOINC_MUTEX: case SYNC_DICT_OPERATION: case SYNC_DICT_HEADER: @@ -1192,13 +1243,32 @@ sync_thread_add_level( ut_error; } break; + case SYNC_SEARCH_SYS: + case SYNC_BUF_LRU_LIST: + case SYNC_BUF_FLUSH_LIST: + case SYNC_BUF_PAGE_HASH: + case SYNC_BUF_FREE_LIST: + case SYNC_BUF_ZIP_FREE: + case SYNC_BUF_ZIP_HASH: + case SYNC_BUF_POOL: + /* We can have multiple mutexes of this type therefore we + can only check whether the greater than condition holds. */ + if (!sync_thread_levels_g(array, level-1, TRUE)) { + fprintf(stderr, + "InnoDB: sync_thread_levels_g(array, %lu)" + " does not hold!\n", level-1); + ut_error; + } + break; + case SYNC_BUF_BLOCK: /* Either the thread must own the buffer pool mutex - (buf_pool_mutex), or it is allowed to latch only ONE - buffer block (block->mutex or buf_pool_zip_mutex). */ + (buf_pool->mutex), or it is allowed to latch only ONE + buffer block (block->mutex or buf_pool->zip_mutex). */ if (!sync_thread_levels_g(array, level, FALSE)) { ut_a(sync_thread_levels_g(array, level - 1, TRUE)); - ut_a(sync_thread_levels_contain(array, SYNC_BUF_LRU_LIST)); + /* the exact rule is not fixed yet, for now */ + //ut_a(sync_thread_levels_contain(array, SYNC_BUF_LRU_LIST)); } break; case SYNC_REC_LOCK: @@ -1218,8 +1288,12 @@ sync_thread_add_level( ut_a(sync_thread_levels_g(array, SYNC_IBUF_BITMAP - 1, TRUE)); } else { - ut_a(sync_thread_levels_g(array, SYNC_IBUF_BITMAP, - TRUE)); + /* This is violated during trx_sys_create_rsegs() + when creating additional rollback segments when + upgrading in innobase_start_or_create_for_mysql(). */ + ut_a(srv_is_being_started + || sync_thread_levels_g(array, SYNC_IBUF_BITMAP, + TRUE)); } break; case SYNC_FSP_PAGE: @@ -1230,10 +1304,16 @@ sync_thread_add_level( || sync_thread_levels_g(array, SYNC_FSP, TRUE)); break; case SYNC_TRX_UNDO_PAGE: + /* Purge is allowed to read in as many UNDO pages as it likes, + there was a bogus rule here earlier that forced the caller to + acquire the purge_sys_t::mutex. The purge mutex did not really + protect anything because it was only ever acquired by the + single purge thread. The purge thread can read the UNDO pages + without any covering mutex. */ + ut_a(sync_thread_levels_contain(array, SYNC_TRX_UNDO) || sync_thread_levels_contain(array, SYNC_RSEG) - || sync_thread_levels_contain(array, SYNC_PURGE_SYS) - || sync_thread_levels_g(array, SYNC_TRX_UNDO_PAGE, TRUE)); + || sync_thread_levels_g(array, level - 1, TRUE)); break; case SYNC_RSEG_HEADER: ut_a(sync_thread_levels_contain(array, SYNC_RSEG)); @@ -1286,19 +1366,26 @@ sync_thread_add_level( ut_error; } - for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) { + if (array->next_free == ULINT_UNDEFINED) { + ut_a(array->n_elems < array->max_elems); - slot = sync_thread_levels_get_nth(array, i); + i = array->n_elems++; + } else { + i = array->next_free; + array->next_free = array->elems[i].level; + } - if (slot->latch == NULL) { - slot->latch = latch; - slot->level = level; + ut_a(i < array->n_elems); + ut_a(i != ULINT_UNDEFINED); - break; - } - } + ++array->in_use; + + slot = &array->elems[i]; - ut_a(i < SYNC_THREAD_N_LEVELS); + ut_a(slot->latch == NULL); + + slot->latch = latch; + slot->level = level; mutex_exit(&sync_thread_mutex); } @@ -1314,8 +1401,7 @@ sync_thread_reset_level( /*====================*/ void* latch) /*!< in: pointer to a mutex or an rw-lock */ { - sync_level_t* array; - sync_level_t* slot; + sync_arr_t* array; sync_thread_t* thread_slot; ulint i; @@ -1346,17 +1432,37 @@ sync_thread_reset_level( array = thread_slot->levels; - for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) { + for (i = 0; i < array->n_elems; i++) { + sync_level_t* slot; + + slot = &array->elems[i]; - slot = sync_thread_levels_get_nth(array, i); + if (slot->latch != latch) { + continue; + } - if (slot->latch == latch) { - slot->latch = NULL; + slot->latch = NULL; - mutex_exit(&sync_thread_mutex); + /* Update the free slot list. See comment in sync_level_t + for the level field. */ + slot->level = array->next_free; + array->next_free = i; - return(TRUE); + ut_a(array->in_use >= 1); + --array->in_use; + + /* If all cells are idle then reset the free + list. The assumption is that this will save + time when we need to scan up to n_elems. */ + + if (array->in_use == 0) { + array->n_elems = 0; + array->next_free = ULINT_UNDEFINED; } + + mutex_exit(&sync_thread_mutex); + + return(TRUE); } if (((mutex_t*) latch)->magic_n != MUTEX_MAGIC_N) { @@ -1386,11 +1492,6 @@ void sync_init(void) /*===========*/ { -#ifdef UNIV_SYNC_DEBUG - sync_thread_t* thread_slot; - ulint i; -#endif /* UNIV_SYNC_DEBUG */ - ut_a(sync_initialized == FALSE); sync_initialized = TRUE; @@ -1404,35 +1505,64 @@ sync_init(void) /* Create the thread latch level array where the latch levels are stored for each OS thread */ - sync_thread_level_arrays = ut_malloc(OS_THREAD_MAX_N - * sizeof(sync_thread_t)); - for (i = 0; i < OS_THREAD_MAX_N; i++) { + sync_thread_level_arrays = calloc( + sizeof(sync_thread_t), OS_THREAD_MAX_N); + ut_a(sync_thread_level_arrays != NULL); - thread_slot = sync_thread_level_arrays_get_nth(i); - thread_slot->levels = NULL; - } #endif /* UNIV_SYNC_DEBUG */ /* Init the mutex list and create the mutex to protect it. */ UT_LIST_INIT(mutex_list); - mutex_create(&mutex_list_mutex, SYNC_NO_ORDER_CHECK); + mutex_create(mutex_list_mutex_key, &mutex_list_mutex, + SYNC_NO_ORDER_CHECK); #ifdef UNIV_SYNC_DEBUG - mutex_create(&sync_thread_mutex, SYNC_NO_ORDER_CHECK); + mutex_create(sync_thread_mutex_key, &sync_thread_mutex, + SYNC_NO_ORDER_CHECK); #endif /* UNIV_SYNC_DEBUG */ /* Init the rw-lock list and create the mutex to protect it. */ UT_LIST_INIT(rw_lock_list); - mutex_create(&rw_lock_list_mutex, SYNC_NO_ORDER_CHECK); + mutex_create(rw_lock_list_mutex_key, &rw_lock_list_mutex, + SYNC_NO_ORDER_CHECK); #ifdef UNIV_SYNC_DEBUG - mutex_create(&rw_lock_debug_mutex, SYNC_NO_ORDER_CHECK); + mutex_create(rw_lock_debug_mutex_key, &rw_lock_debug_mutex, + SYNC_NO_ORDER_CHECK); rw_lock_debug_event = os_event_create(NULL); rw_lock_debug_waiters = FALSE; #endif /* UNIV_SYNC_DEBUG */ } +#ifdef UNIV_SYNC_DEBUG +/******************************************************************//** +Frees all debug memory. */ +static +void +sync_thread_level_arrays_free(void) +/*===============================*/ + +{ + ulint i; + + for (i = 0; i < OS_THREAD_MAX_N; i++) { + sync_thread_t* slot; + + slot = &sync_thread_level_arrays[i]; + + /* If this slot was allocated then free the slot memory too. */ + if (slot->levels != NULL) { + free(slot->levels); + slot->levels = NULL; + } + } + + free(sync_thread_level_arrays); + sync_thread_level_arrays = NULL; +} +#endif /* UNIV_SYNC_DEBUG */ + /******************************************************************//** Frees the resources in InnoDB's own synchronization data structures. Use os_sync_free() after calling this. */ @@ -1445,17 +1575,20 @@ sync_close(void) sync_array_free(sync_primary_wait_array); - mutex = UT_LIST_GET_FIRST(mutex_list); + for (mutex = UT_LIST_GET_FIRST(mutex_list); + mutex != NULL; + /* No op */) { - while (mutex) { #ifdef UNIV_MEM_DEBUG if (mutex == &mem_hash_mutex) { mutex = UT_LIST_GET_NEXT(list, mutex); continue; } #endif /* UNIV_MEM_DEBUG */ + mutex_free(mutex); - mutex = UT_LIST_GET_FIRST(mutex_list); + + mutex = UT_LIST_GET_FIRST(mutex_list); } mutex_free(&mutex_list_mutex); @@ -1464,6 +1597,8 @@ sync_close(void) /* Switch latching order checks on in sync0sync.c */ sync_order_checks_on = FALSE; + + sync_thread_level_arrays_free(); #endif /* UNIV_SYNC_DEBUG */ sync_initialized = FALSE; @@ -1484,14 +1619,16 @@ sync_print_wait_info( fprintf(file, "Mutex spin waits %llu, rounds %llu, OS waits %llu\n" - "RW-shared spins %llu, OS waits %llu;" - " RW-excl spins %llu, OS waits %llu\n", + "RW-shared spins %llu, rounds %llu, OS waits %llu\n" + "RW-excl spins %llu, rounds %llu, OS waits %llu\n", mutex_spin_wait_count, mutex_spin_round_count, mutex_os_wait_count, rw_s_spin_wait_count, + rw_s_spin_round_count, rw_s_os_wait_count, rw_x_spin_wait_count, + rw_x_spin_round_count, rw_x_os_wait_count); fprintf(file, |