35 #include "sync0sync.ic"
43 #ifdef UNIV_SYNC_DEBUG
188 #ifdef UNIV_SYNC_DEBUG
192 struct sync_thread_t;
197 UNIV_INTERN sync_thread_t* sync_thread_level_arrays;
202 # ifdef UNIV_PFS_MUTEX
203 UNIV_INTERN mysql_pfs_key_t sync_thread_mutex_key;
213 #ifdef UNIV_PFS_MUTEX
214 UNIV_INTERN mysql_pfs_key_t mutex_list_mutex_key;
217 #ifdef UNIV_SYNC_DEBUG
219 UNIV_INTERN ibool sync_order_checks_on = FALSE;
222 static const ulint SYNC_THREAD_N_LEVELS = 10000;
235 struct sync_thread_t{
267 const char* cmutex_name,
268 # ifdef UNIV_SYNC_DEBUG
272 const char* cfile_name,
275 #if defined(HAVE_ATOMIC_BUILTINS)
276 mutex_reset_lock_word(mutex);
278 os_fast_mutex_init(PFS_NOT_INSTRUMENTED, &mutex->
os_fast_mutex);
284 mutex->magic_n = MUTEX_MAGIC_N;
286 #ifdef UNIV_SYNC_DEBUG
288 mutex->file_name =
"not yet reserved";
289 mutex->level =
level;
292 mutex->
cline = cline;
301 #ifdef UNIV_SYNC_DEBUG
302 || (mutex == &sync_thread_mutex)
330 ut_ad(mutex_validate(mutex));
332 ut_a(mutex_get_waiters(mutex) == 0);
334 #ifdef UNIV_MEM_DEBUG
335 if (mutex == &mem_hash_mutex) {
344 #ifdef UNIV_SYNC_DEBUG
345 && mutex != &sync_thread_mutex
364 #ifdef UNIV_MEM_DEBUG
367 #if !defined(HAVE_ATOMIC_BUILTINS)
389 const char* file_name __attribute__((unused)),
392 ulint line __attribute__((unused)))
395 ut_ad(mutex_validate(mutex));
397 if (!ib_mutex_test_and_set(mutex)) {
400 #ifdef UNIV_SYNC_DEBUG
401 mutex_set_debug_info(mutex, file_name, line);
421 ut_a(mutex->magic_n == MUTEX_MAGIC_N);
436 ut_ad(mutex_validate(mutex));
471 const char* file_name,
478 size_t counter_index;
488 mutex_spin_wait_count.
add(counter_index, 1);
503 if (srv_spin_wait_delay) {
514 mutex_spin_round_count.
add(counter_index, i);
516 if (ib_mutex_test_and_set(mutex) == 0) {
520 #ifdef UNIV_SYNC_DEBUG
521 mutex_set_debug_info(mutex, file_name, line);
542 sync_arr, mutex, SYNC_MUTEX, file_name, line, &index);
553 for (i = 0; i < 4; i++) {
554 if (ib_mutex_test_and_set(mutex) == 0) {
560 #ifdef UNIV_SYNC_DEBUG
561 mutex_set_debug_info(mutex, file_name, line);
576 mutex_os_wait_count.
add(counter_index, 1);
601 #ifdef UNIV_SYNC_DEBUG
606 mutex_set_debug_info(
609 const char* file_name,
615 sync_thread_add_level(mutex, mutex->level, FALSE);
617 mutex->file_name = file_name;
625 mutex_get_debug_info(
628 const char** file_name,
635 *file_name = mutex->file_name;
637 *thread_id = mutex->thread_id;
644 mutex_list_print_info(
649 const char* file_name;
656 "----------\n", file);
662 while (mutex != NULL) {
666 mutex_get_debug_info(mutex, &file_name, &line,
669 "Locked mutex: addr %p thread %ld"
670 " file %s line %ld\n",
678 fprintf(file,
"Total number of mutexes %ld\n", count);
688 mutex_n_reserved(
void)
725 return(mutex_n_reserved() + rw_lock_n_locked() == 0);
733 sync_thread_level_arrays_find_slot(
void)
742 for (i = 0; i < OS_THREAD_MAX_N; i++) {
745 slot = &sync_thread_level_arrays[
i];
761 sync_thread_level_arrays_find_free(
void)
767 for (i = 0; i < OS_THREAD_MAX_N; i++) {
770 slot = &sync_thread_level_arrays[
i];
772 if (slot->levels == NULL) {
787 const sync_level_t* slot)
792 mutex =
static_cast<ib_mutex_t*
>(slot->latch);
794 if (mutex->magic_n == MUTEX_MAGIC_N) {
796 "Mutex created at %s %lu\n",
798 (ulong) mutex->
cline);
802 const char* file_name;
805 mutex_get_debug_info(
806 mutex, &file_name, &line, &thread_id);
809 "InnoDB: Locked mutex:"
810 " addr %p thread %ld file %s line %ld\n",
812 file_name, (ulong) line);
814 fputs(
"Not locked\n", stderr);
819 lock =
static_cast<rw_lock_t*
>(slot->latch);
831 sync_thread_levels_g(
840 for (i = 0; i < arr->n_elems; i++) {
841 const sync_level_t* slot;
843 slot = &arr->elems[
i];
845 if (slot->latch != NULL && slot->level <= limit) {
848 "InnoDB: sync levels should be"
849 " > %lu but a level is %lu\n",
850 (ulong) limit, (ulong) slot->level);
852 sync_print_warning(slot);
867 sync_thread_levels_contain(
875 for (i = 0; i < arr->n_elems; i++) {
876 const sync_level_t* slot;
878 slot = &arr->elems[
i];
880 if (slot->latch != NULL && slot->level == level) {
895 sync_thread_levels_contains(
902 sync_thread_t* thread_slot;
904 if (!sync_order_checks_on) {
909 mutex_enter(&sync_thread_mutex);
911 thread_slot = sync_thread_level_arrays_find_slot();
913 if (thread_slot == NULL) {
915 mutex_exit(&sync_thread_mutex);
920 arr = thread_slot->levels;
922 for (i = 0; i < arr->n_elems; i++) {
925 slot = &arr->elems[
i];
927 if (slot->latch != NULL && slot->level == level) {
929 mutex_exit(&sync_thread_mutex);
934 mutex_exit(&sync_thread_mutex);
944 sync_thread_levels_nonempty_gen(
946 ibool dict_mutex_allowed)
951 sync_thread_t* thread_slot;
953 if (!sync_order_checks_on) {
958 mutex_enter(&sync_thread_mutex);
960 thread_slot = sync_thread_level_arrays_find_slot();
962 if (thread_slot == NULL) {
964 mutex_exit(&sync_thread_mutex);
969 arr = thread_slot->levels;
971 for (i = 0; i < arr->n_elems; ++
i) {
972 const sync_level_t* slot;
974 slot = &arr->elems[
i];
976 if (slot->latch != NULL
977 && (!dict_mutex_allowed
978 || (slot->level != SYNC_DICT
979 && slot->level != SYNC_DICT_OPERATION
980 && slot->level != SYNC_FTS_CACHE))) {
982 mutex_exit(&sync_thread_mutex);
989 mutex_exit(&sync_thread_mutex);
1000 sync_thread_levels_nonempty_trx(
1002 ibool has_search_latch)
1008 sync_thread_t* thread_slot;
1010 if (!sync_order_checks_on) {
1015 ut_a(!has_search_latch
1016 || sync_thread_levels_contains(SYNC_SEARCH_SYS));
1018 mutex_enter(&sync_thread_mutex);
1020 thread_slot = sync_thread_level_arrays_find_slot();
1022 if (thread_slot == NULL) {
1024 mutex_exit(&sync_thread_mutex);
1029 arr = thread_slot->levels;
1031 for (i = 0; i < arr->n_elems; ++
i) {
1032 const sync_level_t* slot;
1034 slot = &arr->elems[
i];
1036 if (slot->latch != NULL
1037 && (!has_search_latch
1038 || slot->level != SYNC_SEARCH_SYS)) {
1040 mutex_exit(&sync_thread_mutex);
1043 return(slot->latch);
1047 mutex_exit(&sync_thread_mutex);
1058 sync_thread_add_level(
1068 sync_thread_t* thread_slot;
1070 if (!sync_order_checks_on) {
1075 if ((latch == (
void*) &sync_thread_mutex)
1077 || (latch == (
void*) &rw_lock_debug_mutex)
1078 || (latch == (
void*) &rw_lock_list_mutex)) {
1083 if (level == SYNC_LEVEL_VARYING) {
1088 mutex_enter(&sync_thread_mutex);
1090 thread_slot = sync_thread_level_arrays_find_slot();
1092 if (thread_slot == NULL) {
1096 + (
sizeof(*array->elems) * SYNC_THREAD_N_LEVELS);
1099 array =
static_cast<sync_arr_t*
>(calloc(sz,
sizeof(
char)));
1100 ut_a(array != NULL);
1102 array->next_free = ULINT_UNDEFINED;
1103 array->max_elems = SYNC_THREAD_N_LEVELS;
1104 array->elems = (sync_level_t*) &array[1];
1106 thread_slot = sync_thread_level_arrays_find_free();
1108 thread_slot->levels = array;
1112 array = thread_slot->levels;
1124 case SYNC_NO_ORDER_CHECK:
1125 case SYNC_EXTERN_STORAGE:
1126 case SYNC_TREE_NODE_FROM_HASH:
1129 case SYNC_TRX_SYS_HEADER:
1139 case SYNC_FTS_BG_THREADS:
1140 case SYNC_WORK_QUEUE:
1141 case SYNC_FTS_OPTIMIZE:
1142 case SYNC_FTS_CACHE:
1143 case SYNC_FTS_CACHE_INIT:
1145 case SYNC_LOG_FLUSH_ORDER:
1146 case SYNC_ANY_LATCH:
1147 case SYNC_FILE_FORMAT_TAG:
1148 case SYNC_DOUBLEWRITE:
1149 case SYNC_SEARCH_SYS:
1152 case SYNC_LOCK_WAIT_SYS:
1154 case SYNC_IBUF_BITMAP_MUTEX:
1157 case SYNC_PURGE_LATCH:
1158 case SYNC_PURGE_QUEUE:
1159 case SYNC_DICT_AUTOINC_MUTEX:
1160 case SYNC_DICT_OPERATION:
1161 case SYNC_DICT_HEADER:
1162 case SYNC_TRX_I_S_RWLOCK:
1163 case SYNC_TRX_I_S_LAST_READ:
1164 case SYNC_IBUF_MUTEX:
1165 case SYNC_INDEX_ONLINE_LOG:
1166 case SYNC_STATS_AUTO_RECALC:
1167 if (!sync_thread_levels_g(array, level, TRUE)) {
1169 "InnoDB: sync_thread_levels_g(array, %lu)"
1170 " does not hold!\n", level);
1177 if (!sync_thread_levels_g(array, level, FALSE)) {
1178 ut_a(sync_thread_levels_g(array, level - 1, TRUE));
1179 ut_a(sync_thread_levels_contain(array, SYNC_LOCK_SYS));
1182 case SYNC_BUF_FLUSH_LIST:
1186 if (!sync_thread_levels_g(array, level-1, TRUE)) {
1188 "InnoDB: sync_thread_levels_g(array, %lu)"
1189 " does not hold!\n", level-1);
1195 case SYNC_BUF_PAGE_HASH:
1201 case SYNC_BUF_BLOCK:
1205 if (!sync_thread_levels_g(array, level, FALSE)) {
1206 ut_a(sync_thread_levels_g(array, level - 1, TRUE));
1207 ut_a(sync_thread_levels_contain(array, SYNC_BUF_POOL));
1211 if (sync_thread_levels_contain(array, SYNC_LOCK_SYS)) {
1212 ut_a(sync_thread_levels_g(array, SYNC_REC_LOCK - 1,
1215 ut_a(sync_thread_levels_g(array, SYNC_REC_LOCK, TRUE));
1218 case SYNC_IBUF_BITMAP:
1222 if (sync_thread_levels_contain(array,
1223 SYNC_IBUF_BITMAP_MUTEX)) {
1224 ut_a(sync_thread_levels_g(array, SYNC_IBUF_BITMAP - 1,
1231 || sync_thread_levels_g(array, SYNC_IBUF_BITMAP,
1236 ut_a(sync_thread_levels_contain(array, SYNC_FSP));
1239 ut_a(sync_thread_levels_contain(array, SYNC_FSP)
1240 || sync_thread_levels_g(array, SYNC_FSP, TRUE));
1242 case SYNC_TRX_UNDO_PAGE:
1250 ut_a(sync_thread_levels_contain(array, SYNC_TRX_UNDO)
1251 || sync_thread_levels_contain(array, SYNC_RSEG)
1252 || sync_thread_levels_g(array, level - 1, TRUE));
1254 case SYNC_RSEG_HEADER:
1255 ut_a(sync_thread_levels_contain(array, SYNC_RSEG));
1257 case SYNC_RSEG_HEADER_NEW:
1258 ut_a(sync_thread_levels_contain(array, SYNC_FSP_PAGE));
1260 case SYNC_TREE_NODE:
1261 ut_a(sync_thread_levels_contain(array, SYNC_INDEX_TREE)
1262 || sync_thread_levels_contain(array, SYNC_DICT_OPERATION)
1263 || sync_thread_levels_g(array, SYNC_TREE_NODE - 1, TRUE));
1265 case SYNC_TREE_NODE_NEW:
1266 ut_a(sync_thread_levels_contain(array, SYNC_FSP_PAGE));
1268 case SYNC_INDEX_TREE:
1269 ut_a(sync_thread_levels_g(array, SYNC_TREE_NODE - 1, TRUE));
1271 case SYNC_IBUF_TREE_NODE:
1272 ut_a(sync_thread_levels_contain(array, SYNC_IBUF_INDEX_TREE)
1273 || sync_thread_levels_g(array, SYNC_IBUF_TREE_NODE - 1,
1276 case SYNC_IBUF_TREE_NODE_NEW:
1282 ut_a(sync_thread_levels_contain(array, SYNC_IBUF_MUTEX)
1283 || sync_thread_levels_contain(array, SYNC_FSP));
1285 case SYNC_IBUF_INDEX_TREE:
1286 if (sync_thread_levels_contain(array, SYNC_FSP)) {
1287 ut_a(sync_thread_levels_g(array, level - 1, TRUE));
1289 ut_a(sync_thread_levels_g(
1290 array, SYNC_IBUF_TREE_NODE - 1, TRUE));
1293 case SYNC_IBUF_PESS_INSERT_MUTEX:
1294 ut_a(sync_thread_levels_g(array, SYNC_FSP - 1, TRUE));
1295 ut_a(!sync_thread_levels_contain(array, SYNC_IBUF_MUTEX));
1297 case SYNC_IBUF_HEADER:
1298 ut_a(sync_thread_levels_g(array, SYNC_FSP - 1, TRUE));
1299 ut_a(!sync_thread_levels_contain(array, SYNC_IBUF_MUTEX));
1300 ut_a(!sync_thread_levels_contain(array,
1301 SYNC_IBUF_PESS_INSERT_MUTEX));
1305 ut_a(buf_debug_prints
1306 || sync_thread_levels_g(array, SYNC_DICT, TRUE));
1308 ut_a(sync_thread_levels_g(array, SYNC_DICT, TRUE));
1316 if (array->next_free == ULINT_UNDEFINED) {
1317 ut_a(array->n_elems < array->max_elems);
1319 i = array->n_elems++;
1321 i = array->next_free;
1322 array->next_free = array->elems[
i].level;
1325 ut_a(i < array->n_elems);
1326 ut_a(i != ULINT_UNDEFINED);
1330 slot = &array->elems[
i];
1332 ut_a(slot->latch == NULL);
1334 slot->latch = latch;
1335 slot->level =
level;
1337 mutex_exit(&sync_thread_mutex);
1347 sync_thread_reset_level(
1352 sync_thread_t* thread_slot;
1355 if (!sync_order_checks_on) {
1360 if ((latch == (
void*) &sync_thread_mutex)
1362 || (latch == (
void*) &rw_lock_debug_mutex)
1363 || (latch == (
void*) &rw_lock_list_mutex)) {
1368 mutex_enter(&sync_thread_mutex);
1370 thread_slot = sync_thread_level_arrays_find_slot();
1372 if (thread_slot == NULL) {
1376 mutex_exit(&sync_thread_mutex);
1380 array = thread_slot->levels;
1382 for (i = 0; i < array->n_elems; i++) {
1385 slot = &array->elems[
i];
1387 if (slot->latch != latch) {
1395 slot->level = array->next_free;
1396 array->next_free =
i;
1398 ut_a(array->in_use >= 1);
1405 if (array->in_use == 0) {
1407 array->next_free = ULINT_UNDEFINED;
1410 mutex_exit(&sync_thread_mutex);
1415 if (((
ib_mutex_t*) latch)->magic_n != MUTEX_MAGIC_N) {
1420 if (rw_lock->level == SYNC_LEVEL_VARYING) {
1421 mutex_exit(&sync_thread_mutex);
1429 mutex_exit(&sync_thread_mutex);
1448 #ifdef UNIV_SYNC_DEBUG
1452 sync_thread_level_arrays =
static_cast<sync_thread_t*
>(
1453 calloc(
sizeof(sync_thread_t), OS_THREAD_MAX_N));
1455 ut_a(sync_thread_level_arrays != NULL);
1462 SYNC_NO_ORDER_CHECK);
1463 #ifdef UNIV_SYNC_DEBUG
1464 mutex_create(sync_thread_mutex_key, &sync_thread_mutex,
1465 SYNC_NO_ORDER_CHECK);
1471 mutex_create(rw_lock_list_mutex_key, &rw_lock_list_mutex,
1472 SYNC_NO_ORDER_CHECK);
1474 #ifdef UNIV_SYNC_DEBUG
1475 mutex_create(rw_lock_debug_mutex_key, &rw_lock_debug_mutex,
1476 SYNC_NO_ORDER_CHECK);
1479 rw_lock_debug_waiters = FALSE;
1483 #ifdef UNIV_SYNC_DEBUG
1488 sync_thread_level_arrays_free(
void)
1494 for (i = 0; i < OS_THREAD_MAX_N; i++) {
1495 sync_thread_t* slot;
1497 slot = &sync_thread_level_arrays[
i];
1500 if (slot->levels != NULL) {
1502 slot->levels = NULL;
1506 free(sync_thread_level_arrays);
1507 sync_thread_level_arrays = NULL;
1527 #ifdef UNIV_MEM_DEBUG
1528 if (mutex == &mem_hash_mutex) {
1540 #ifdef UNIV_SYNC_DEBUG
1541 mutex_free(&sync_thread_mutex);
1544 sync_order_checks_on = FALSE;
1546 sync_thread_level_arrays_free();
1561 "Mutex spin waits "UINT64PF
", rounds "UINT64PF
", "
1562 "OS waits "UINT64PF
"\n"
1563 "RW-shared spins "UINT64PF
", rounds "UINT64PF
", "
1564 "OS waits "UINT64PF
"\n"
1565 "RW-excl spins "UINT64PF
", rounds "UINT64PF
", "
1566 "OS waits "UINT64PF
"\n",
1567 (ib_uint64_t) mutex_spin_wait_count,
1568 (ib_uint64_t) mutex_spin_round_count,
1569 (ib_uint64_t) mutex_os_wait_count,
1578 "Spin rounds per wait: %.2f mutex, %.2f RW-shared, "
1580 (
double) mutex_spin_round_count /
1581 (mutex_spin_wait_count ? mutex_spin_wait_count : 1),
1598 #ifdef UNIV_SYNC_DEBUG
1599 mutex_list_print_info(file);
1601 rw_lock_list_print_info(file);