📄 sync0rw.c
字号:
} else if (state == RW_LOCK_NOT_LOCKED) { /* Spin waiting for the writer field to become free */ i = 0; while (rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED && i < SYNC_SPIN_ROUNDS) { if (srv_spin_wait_delay) { ut_delay(ut_rnd_interval(0, srv_spin_wait_delay)); } i++; } if (i == SYNC_SPIN_ROUNDS) { os_thread_yield(); } } else if (state == RW_LOCK_WAIT_EX) { /* Spin waiting for the reader count field to become zero */ i = 0; while (rw_lock_get_reader_count(lock) != 0 && i < SYNC_SPIN_ROUNDS) { if (srv_spin_wait_delay) { ut_delay(ut_rnd_interval(0, srv_spin_wait_delay)); } i++; } if (i == SYNC_SPIN_ROUNDS) { os_thread_yield(); } } else { i = 0; /* Eliminate a compiler warning */ ut_error; } if (srv_print_latch_waits) { fprintf(stderr, "Thread %lu spin wait rw-x-lock at %p cfile %s cline %lu rnds %lu\n", os_thread_pf(os_thread_get_curr_id()), lock, lock->cfile_name, (ulong) lock->cline, (ulong) i); } rw_x_spin_wait_count++; /* We try once again to obtain the lock. Acquire the mutex protecting the rw-lock fields */ mutex_enter(rw_lock_get_mutex(lock)); state = rw_lock_x_lock_low(lock, pass, file_name, line); if (state == RW_LOCK_EX) { mutex_exit(rw_lock_get_mutex(lock)); return; /* Locking succeeded */ } rw_x_system_call_count++; sync_array_reserve_cell(sync_primary_wait_array, lock, RW_LOCK_EX, file_name, line, &index); rw_lock_set_waiters(lock, 1); mutex_exit(rw_lock_get_mutex(lock)); if (srv_print_latch_waits) { fprintf(stderr, "Thread %lu OS wait for rw-x-lock at %p cfile %s cline %lu\n", os_thread_pf(os_thread_get_curr_id()), lock, lock->cfile_name, (ulong) lock->cline); } rw_x_system_call_count++; rw_x_os_wait_count++; sync_array_wait_event(sync_primary_wait_array, index); goto lock_loop;}#ifdef UNIV_SYNC_DEBUG/**********************************************************************Acquires the debug mutex. We cannot use the mutex defined in sync0sync,because the debug mutex is also acquired in sync0arr while holding the OSmutex protecting the sync array, and the ordinary mutex_enter mightrecursively call routines in sync0arr, leading to a deadlock on the OSmutex. */voidrw_lock_debug_mutex_enter(void)/*==========================*/{loop: if (0 == mutex_enter_nowait(&rw_lock_debug_mutex, __FILE__, __LINE__)) { return; } os_event_reset(rw_lock_debug_event); rw_lock_debug_waiters = TRUE; if (0 == mutex_enter_nowait(&rw_lock_debug_mutex, __FILE__, __LINE__)) { return; } os_event_wait(rw_lock_debug_event); goto loop; }/**********************************************************************Releases the debug mutex. */voidrw_lock_debug_mutex_exit(void)/*==========================*/{ mutex_exit(&rw_lock_debug_mutex); if (rw_lock_debug_waiters) { rw_lock_debug_waiters = FALSE; os_event_set(rw_lock_debug_event); }}/**********************************************************************Inserts the debug information for an rw-lock. */voidrw_lock_add_debug_info(/*===================*/ rw_lock_t* lock, /* in: rw-lock */ ulint pass, /* in: pass value */ ulint lock_type, /* in: lock type */ const char* file_name, /* in: file where requested */ ulint line) /* in: line where requested */{ rw_lock_debug_t* info; ut_ad(lock); ut_ad(file_name); info = rw_lock_debug_create(); rw_lock_debug_mutex_enter(); info->file_name = file_name; info->line = line; info->lock_type = lock_type; info->thread_id = os_thread_get_curr_id(); info->pass = pass; UT_LIST_ADD_FIRST(list, lock->debug_list, info); rw_lock_debug_mutex_exit(); if ((pass == 0) && (lock_type != RW_LOCK_WAIT_EX)) { sync_thread_add_level(lock, lock->level); }} /**********************************************************************Removes a debug information struct for an rw-lock. */voidrw_lock_remove_debug_info(/*======================*/ rw_lock_t* lock, /* in: rw-lock */ ulint pass, /* in: pass value */ ulint lock_type) /* in: lock type */{ rw_lock_debug_t* info; ut_ad(lock); if ((pass == 0) && (lock_type != RW_LOCK_WAIT_EX)) { sync_thread_reset_level(lock); } rw_lock_debug_mutex_enter(); info = UT_LIST_GET_FIRST(lock->debug_list); while (info != NULL) { if ((pass == info->pass) && ((pass != 0) || os_thread_eq(info->thread_id, os_thread_get_curr_id())) && (info->lock_type == lock_type)) { /* Found! */ UT_LIST_REMOVE(list, lock->debug_list, info); rw_lock_debug_mutex_exit(); rw_lock_debug_free(info); return; } info = UT_LIST_GET_NEXT(list, info); } ut_error;}#endif /* UNIV_SYNC_DEBUG *//**********************************************************************Sets the rw-lock latching level field. */voidrw_lock_set_level(/*==============*/ rw_lock_t* lock, /* in: rw-lock */ ulint level) /* in: level */{ lock->level = level;}#ifdef UNIV_SYNC_DEBUG/**********************************************************************Checks if the thread has locked the rw-lock in the specified mode, withthe pass value == 0. */iboolrw_lock_own(/*========*/ /* out: TRUE if locked */ rw_lock_t* lock, /* in: rw-lock */ ulint lock_type) /* in: lock type: RW_LOCK_SHARED, RW_LOCK_EX */{ rw_lock_debug_t* info; ut_ad(lock); ut_ad(rw_lock_validate(lock)); mutex_enter(&(lock->mutex)); info = UT_LIST_GET_FIRST(lock->debug_list); while (info != NULL) { if (os_thread_eq(info->thread_id, os_thread_get_curr_id()) && (info->pass == 0) && (info->lock_type == lock_type)) { mutex_exit(&(lock->mutex)); /* Found! */ return(TRUE); } info = UT_LIST_GET_NEXT(list, info); } mutex_exit(&(lock->mutex)); return(FALSE);}#endif /* UNIV_SYNC_DEBUG *//**********************************************************************Checks if somebody has locked the rw-lock in the specified mode. */iboolrw_lock_is_locked(/*==============*/ /* out: TRUE if locked */ rw_lock_t* lock, /* in: rw-lock */ ulint lock_type) /* in: lock type: RW_LOCK_SHARED, RW_LOCK_EX */{ ibool ret = FALSE; ut_ad(lock); ut_ad(rw_lock_validate(lock)); mutex_enter(&(lock->mutex)); if (lock_type == RW_LOCK_SHARED) { if (lock->reader_count > 0) { ret = TRUE; } } else if (lock_type == RW_LOCK_EX) { if (lock->writer == RW_LOCK_EX) { ret = TRUE; } } else { ut_error; } mutex_exit(&(lock->mutex)); return(ret);}#ifdef UNIV_SYNC_DEBUG/*******************************************************************Prints debug info of currently locked rw-locks. */voidrw_lock_list_print_info(void)/*=========================*/{ rw_lock_t* lock; ulint count = 0; rw_lock_debug_t* info; mutex_enter(&rw_lock_list_mutex); fputs("-------------\n" "RW-LATCH INFO\n" "-------------\n", stderr); lock = UT_LIST_GET_FIRST(rw_lock_list); while (lock != NULL) { count++; mutex_enter(&(lock->mutex)); if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED) || (rw_lock_get_reader_count(lock) != 0) || (rw_lock_get_waiters(lock) != 0)) { fprintf(stderr, "RW-LOCK: %p ", lock); if (rw_lock_get_waiters(lock)) { fputs(" Waiters for the lock exist\n", stderr); } else { putc('\n', stderr); } info = UT_LIST_GET_FIRST(lock->debug_list); while (info != NULL) { rw_lock_debug_print(info); info = UT_LIST_GET_NEXT(list, info); } } mutex_exit(&(lock->mutex)); lock = UT_LIST_GET_NEXT(list, lock); } fprintf(stderr, "Total number of rw-locks %ld\n", count); mutex_exit(&rw_lock_list_mutex);}/*******************************************************************Prints debug info of an rw-lock. */voidrw_lock_print(/*==========*/ rw_lock_t* lock) /* in: rw-lock */{ rw_lock_debug_t* info; fprintf(stderr, "-------------\n" "RW-LATCH INFO\n" "RW-LATCH: %p ", lock); if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED) || (rw_lock_get_reader_count(lock) != 0) || (rw_lock_get_waiters(lock) != 0)) { if (rw_lock_get_waiters(lock)) { fputs(" Waiters for the lock exist\n", stderr); } else { putc('\n', stderr); } info = UT_LIST_GET_FIRST(lock->debug_list); while (info != NULL) { rw_lock_debug_print(info); info = UT_LIST_GET_NEXT(list, info); } }}/*************************************************************************Prints info of a debug struct. */voidrw_lock_debug_print(/*================*/ rw_lock_debug_t* info) /* in: debug struct */{ ulint rwt; rwt = info->lock_type; fprintf(stderr, "Locked: thread %ld file %s line %ld ", (ulong) os_thread_pf(info->thread_id), info->file_name, (ulong) info->line); if (rwt == RW_LOCK_SHARED) { fputs("S-LOCK", stderr); } else if (rwt == RW_LOCK_EX) { fputs("X-LOCK", stderr); } else if (rwt == RW_LOCK_WAIT_EX) { fputs("WAIT X-LOCK", stderr); } else { ut_error; } if (info->pass != 0) { fprintf(stderr, " pass value %lu", (ulong) info->pass); } putc('\n', stderr);}/*******************************************************************Returns the number of currently locked rw-locks. Works only in the debugversion. */ulintrw_lock_n_locked(void)/*==================*/{ rw_lock_t* lock; ulint count = 0; mutex_enter(&rw_lock_list_mutex); lock = UT_LIST_GET_FIRST(rw_lock_list); while (lock != NULL) { mutex_enter(rw_lock_get_mutex(lock)); if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED) || (rw_lock_get_reader_count(lock) != 0)) { count++; } mutex_exit(rw_lock_get_mutex(lock)); lock = UT_LIST_GET_NEXT(list, lock); } mutex_exit(&rw_lock_list_mutex); return(count);}#endif /* UNIV_SYNC_DEBUG */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -