📄 sync0sync.c
字号:
if (slot->level == level) { return(TRUE); } } } return(FALSE);}/**********************************************************************Checks that the level array for the current thread is empty. */iboolsync_thread_levels_empty_gen(/*=========================*/ /* out: TRUE if empty except the exceptions specified below */ ibool dict_mutex_allowed) /* in: TRUE if dictionary mutex is allowed to be owned by the thread, also purge_is_running mutex is allowed */{ sync_level_t* arr; sync_thread_t* thread_slot; sync_level_t* slot; ulint i; if (!sync_order_checks_on) { return(TRUE); } mutex_enter(&sync_thread_mutex); thread_slot = sync_thread_level_arrays_find_slot(); if (thread_slot == NULL) { mutex_exit(&sync_thread_mutex); return(TRUE); } 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 && (!dict_mutex_allowed || (slot->level != SYNC_DICT && slot->level != SYNC_DICT_OPERATION))) { mutex_exit(&sync_thread_mutex); ut_error; return(FALSE); } } mutex_exit(&sync_thread_mutex); return(TRUE);}/**********************************************************************Checks that the level array for the current thread is empty. */iboolsync_thread_levels_empty(void)/*==========================*/ /* out: TRUE if empty */{ return(sync_thread_levels_empty_gen(FALSE));}/**********************************************************************Adds a latch and its level in the thread level array. Allocates the memoryfor the array if called first time for this OS thread. Makes the checksagainst other latch levels stored in the array for this thread. */voidsync_thread_add_level(/*==================*/ void* latch, /* in: pointer to a mutex or an rw-lock */ ulint level) /* in: level in the latching order; if SYNC_LEVEL_NONE, nothing is done */{ sync_level_t* array; sync_level_t* slot; sync_thread_t* thread_slot; ulint i; if (!sync_order_checks_on) { return; } if ((latch == (void*)&sync_thread_mutex) || (latch == (void*)&mutex_list_mutex)#ifdef UNIV_SYNC_DEBUG || (latch == (void*)&rw_lock_debug_mutex)#endif /* UNIV_SYNC_DEBUG */ || (latch == (void*)&rw_lock_list_mutex)) { return; } if (level == SYNC_LEVEL_NONE) { return; } mutex_enter(&sync_thread_mutex); 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); thread_slot = sync_thread_level_arrays_find_free(); thread_slot->id = os_thread_get_curr_id(); thread_slot->levels = array; for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) { slot = sync_thread_levels_get_nth(array, i); slot->latch = NULL; } } array = thread_slot->levels; /* NOTE that there is a problem with _NODE and _LEAF levels: if the B-tree height changes, then a leaf can change to an internal node or the other way around. We do not know at present if this can cause unnecessary assertion failures below. */ if (level == SYNC_NO_ORDER_CHECK) { /* Do no order checking */ } else if (level == SYNC_MEM_POOL) { ut_a(sync_thread_levels_g(array, SYNC_MEM_POOL)); } else if (level == SYNC_MEM_HASH) { ut_a(sync_thread_levels_g(array, SYNC_MEM_HASH)); } else if (level == SYNC_RECV) { ut_a(sync_thread_levels_g(array, SYNC_RECV)); } else if (level == SYNC_LOG) { ut_a(sync_thread_levels_g(array, SYNC_LOG)); } else if (level == SYNC_THR_LOCAL) { ut_a(sync_thread_levels_g(array, SYNC_THR_LOCAL)); } else if (level == SYNC_ANY_LATCH) { ut_a(sync_thread_levels_g(array, SYNC_ANY_LATCH)); } else if (level == SYNC_TRX_SYS_HEADER) { ut_a(sync_thread_levels_g(array, SYNC_TRX_SYS_HEADER)); } else if (level == SYNC_DOUBLEWRITE) { ut_a(sync_thread_levels_g(array, SYNC_DOUBLEWRITE)); } else if (level == SYNC_BUF_BLOCK) { ut_a((sync_thread_levels_contain(array, SYNC_BUF_POOL) && sync_thread_levels_g(array, SYNC_BUF_BLOCK - 1)) || sync_thread_levels_g(array, SYNC_BUF_BLOCK)); } else if (level == SYNC_BUF_POOL) { ut_a(sync_thread_levels_g(array, SYNC_BUF_POOL)); } else if (level == SYNC_SEARCH_SYS) { ut_a(sync_thread_levels_g(array, SYNC_SEARCH_SYS)); } else if (level == SYNC_TRX_LOCK_HEAP) { ut_a(sync_thread_levels_g(array, SYNC_TRX_LOCK_HEAP)); } else if (level == SYNC_REC_LOCK) { ut_a((sync_thread_levels_contain(array, SYNC_KERNEL) && sync_thread_levels_g(array, SYNC_REC_LOCK - 1)) || sync_thread_levels_g(array, SYNC_REC_LOCK)); } else if (level == SYNC_KERNEL) { ut_a(sync_thread_levels_g(array, SYNC_KERNEL)); } else if (level == SYNC_IBUF_BITMAP) { ut_a((sync_thread_levels_contain(array, SYNC_IBUF_BITMAP_MUTEX) && sync_thread_levels_g(array, SYNC_IBUF_BITMAP - 1)) || sync_thread_levels_g(array, SYNC_IBUF_BITMAP)); } else if (level == SYNC_IBUF_BITMAP_MUTEX) { ut_a(sync_thread_levels_g(array, SYNC_IBUF_BITMAP_MUTEX)); } else if (level == SYNC_FSP_PAGE) { ut_a(sync_thread_levels_contain(array, SYNC_FSP)); } else if (level == SYNC_FSP) { ut_a(sync_thread_levels_contain(array, SYNC_FSP) || sync_thread_levels_g(array, SYNC_FSP)); } else if (level == SYNC_EXTERN_STORAGE) { ut_a(TRUE); } else if (level == SYNC_TRX_UNDO_PAGE) { 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)); } else if (level == SYNC_RSEG_HEADER) { ut_a(sync_thread_levels_contain(array, SYNC_RSEG)); } else if (level == SYNC_RSEG_HEADER_NEW) { ut_a(sync_thread_levels_contain(array, SYNC_KERNEL) && sync_thread_levels_contain(array, SYNC_FSP_PAGE)); } else if (level == SYNC_RSEG) { ut_a(sync_thread_levels_g(array, SYNC_RSEG)); } else if (level == SYNC_TRX_UNDO) { ut_a(sync_thread_levels_g(array, SYNC_TRX_UNDO)); } else if (level == SYNC_PURGE_LATCH) { ut_a(sync_thread_levels_g(array, SYNC_PURGE_LATCH)); } else if (level == SYNC_PURGE_SYS) { ut_a(sync_thread_levels_g(array, SYNC_PURGE_SYS)); } else if (level == SYNC_TREE_NODE) { ut_a(sync_thread_levels_contain(array, SYNC_INDEX_TREE) || sync_thread_levels_g(array, SYNC_TREE_NODE - 1)); } else if (level == SYNC_TREE_NODE_FROM_HASH) { ut_a(1); } else if (level == SYNC_TREE_NODE_NEW) { ut_a(sync_thread_levels_contain(array, SYNC_FSP_PAGE) || sync_thread_levels_contain(array, SYNC_IBUF_MUTEX)); } else if (level == SYNC_INDEX_TREE) { ut_a((sync_thread_levels_contain(array, SYNC_IBUF_MUTEX) && sync_thread_levels_contain(array, SYNC_FSP) && sync_thread_levels_g(array, SYNC_FSP_PAGE - 1)) || sync_thread_levels_g(array, SYNC_TREE_NODE - 1)); } else if (level == SYNC_IBUF_MUTEX) { ut_a(sync_thread_levels_g(array, SYNC_FSP_PAGE - 1)); } else if (level == SYNC_IBUF_PESS_INSERT_MUTEX) { ut_a(sync_thread_levels_g(array, SYNC_FSP - 1) && !sync_thread_levels_contain(array, SYNC_IBUF_MUTEX)); } else if (level == SYNC_IBUF_HEADER) { ut_a(sync_thread_levels_g(array, SYNC_FSP - 1) && !sync_thread_levels_contain(array, SYNC_IBUF_MUTEX) && !sync_thread_levels_contain(array, SYNC_IBUF_PESS_INSERT_MUTEX)); } else if (level == SYNC_DICT_AUTOINC_MUTEX) { ut_a(sync_thread_levels_g(array, SYNC_DICT_AUTOINC_MUTEX)); } else if (level == SYNC_DICT_OPERATION) { ut_a(sync_thread_levels_g(array, SYNC_DICT_OPERATION)); } else if (level == SYNC_DICT_HEADER) { ut_a(sync_thread_levels_g(array, SYNC_DICT_HEADER)); } else if (level == SYNC_DICT) {#ifdef UNIV_DEBUG ut_a(buf_debug_prints || sync_thread_levels_g(array, SYNC_DICT));#else /* UNIV_DEBUG */ ut_a(sync_thread_levels_g(array, SYNC_DICT));#endif /* UNIV_DEBUG */ } else { ut_error; } for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) { slot = sync_thread_levels_get_nth(array, i); if (slot->latch == NULL) { slot->latch = latch; slot->level = level; break; } } ut_a(i < SYNC_THREAD_N_LEVELS); mutex_exit(&sync_thread_mutex);} /**********************************************************************Removes a latch from the thread level array if it is found there. */iboolsync_thread_reset_level(/*====================*/ /* out: TRUE if found from the array; it is an error if the latch is not found */ void* latch) /* in: pointer to a mutex or an rw-lock */{ sync_level_t* array; sync_level_t* slot; sync_thread_t* thread_slot; ulint i; if (!sync_order_checks_on) { return(FALSE); } if ((latch == (void*)&sync_thread_mutex) || (latch == (void*)&mutex_list_mutex)#ifdef UNIV_SYNC_DEBUG || (latch == (void*)&rw_lock_debug_mutex)#endif /* UNIV_SYNC_DEBUG */ || (latch == (void*)&rw_lock_list_mutex)) { return(FALSE); } mutex_enter(&sync_thread_mutex); thread_slot = sync_thread_level_arrays_find_slot(); if (thread_slot == NULL) { ut_error; mutex_exit(&sync_thread_mutex); return(FALSE); } array = thread_slot->levels; for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) { slot = sync_thread_levels_get_nth(array, i); if (slot->latch == latch) { slot->latch = NULL; mutex_exit(&sync_thread_mutex); return(TRUE); } } ut_error; mutex_exit(&sync_thread_mutex); return(FALSE);} /**********************************************************************Initializes the synchronization data structures. */voidsync_init(void)/*===========*/{ sync_thread_t* thread_slot; ulint i; ut_a(sync_initialized == FALSE); sync_initialized = TRUE; /* Create the primary system wait array which is protected by an OS mutex */ sync_primary_wait_array = sync_array_create(OS_THREAD_MAX_N, SYNC_ARRAY_OS_MUTEX); /* 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++) { thread_slot = sync_thread_level_arrays_get_nth(i); thread_slot->levels = NULL; } /* Init the mutex list and create the mutex to protect it. */ UT_LIST_INIT(mutex_list); mutex_create(&mutex_list_mutex); mutex_set_level(&mutex_list_mutex, SYNC_NO_ORDER_CHECK); mutex_create(&sync_thread_mutex); mutex_set_level(&sync_thread_mutex, SYNC_NO_ORDER_CHECK); /* Init the rw-lock list and create the mutex to protect it. */ UT_LIST_INIT(rw_lock_list); mutex_create(&rw_lock_list_mutex); mutex_set_level(&rw_lock_list_mutex, SYNC_NO_ORDER_CHECK);#ifdef UNIV_SYNC_DEBUG mutex_create(&rw_lock_debug_mutex); mutex_set_level(&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 */}/**********************************************************************Frees the resources in InnoDB's own synchronization data structures. Useos_sync_free() after calling this. */voidsync_close(void)/*===========*/{ mutex_t* mutex; sync_array_free(sync_primary_wait_array); mutex = UT_LIST_GET_FIRST(mutex_list); while (mutex) { mutex_free(mutex); mutex = UT_LIST_GET_FIRST(mutex_list); } mutex_free(&mutex_list_mutex); mutex_free(&sync_thread_mutex); }/***********************************************************************Prints wait info of the sync system. */voidsync_print_wait_info(/*=================*/ FILE* file) /* in: file where to print */{#ifdef UNIV_SYNC_DEBUG fprintf(stderr, "Mutex exits %lu, rws exits %lu, rwx exits %lu\n", mutex_exit_count, rw_s_exit_count, rw_x_exit_count);#endif fprintf(file,"Mutex spin waits %lu, rounds %lu, OS waits %lu\n""RW-shared spins %lu, OS waits %lu; RW-excl spins %lu, OS waits %lu\n", (ulong) mutex_spin_wait_count, (ulong) mutex_spin_round_count, (ulong) mutex_os_wait_count, (ulong) rw_s_spin_wait_count, (ulong) rw_s_os_wait_count, (ulong) rw_x_spin_wait_count, (ulong) rw_x_os_wait_count);}/***********************************************************************Prints info of the sync system. */voidsync_print(/*=======*/ FILE* file) /* in: file where to print */{#ifdef UNIV_SYNC_DEBUG mutex_list_print_info(); rw_lock_list_print_info();#endif /* UNIV_SYNC_DEBUG */ sync_array_print_info(file, sync_primary_wait_array); sync_print_wait_info(file);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -