#include "sync0sync.h"#include "sync0rw.h"#include "buf0buf.h"#include "srv0srv.h"#include "buf0types.h"Include dependency graph for sync0sync.c:

Go to the source code of this file.
| #define SYNC_THREAD_N_LEVELS 10000 |
Definition at line 163 of file sync0sync.c.
Referenced by sync_thread_add_level(), sync_thread_levels_contain(), sync_thread_levels_empty_gen(), sync_thread_levels_g(), sync_thread_levels_get_nth(), and sync_thread_reset_level().
| typedef struct sync_level_struct sync_level_t |
Definition at line 133 of file sync0sync.c.
| typedef struct sync_thread_struct sync_thread_t |
Definition at line 134 of file sync0sync.c.
| void mutex_create_func | ( | mutex_t * | mutex, | |
| ulint | level, | |||
| const char * | cfile_name, | |||
| ulint | cline, | |||
| const char * | cmutex_name | |||
| ) |
Definition at line 202 of file sync0sync.c.
References list(), mutex, mutex_enter, mutex_exit(), mutex_list, mutex_list_mutex, MUTEX_MAGIC_N, mutex_set_waiters(), os_fast_mutex_init(), sync_thread_mutex, ut_a, ut_ad, UT_LIST_ADD_FIRST, UT_LIST_GET_FIRST, and UT_LIST_GET_LEN.
00204 : pointer to memory */ 00205 ulint level, /* in: level */ 00206 const char* cfile_name, /* in: file name where created */ 00207 ulint cline, /* in: file line where created */ 00208 const char* cmutex_name) /* in: mutex name */ 00209 { 00210 #if defined(_WIN32) && defined(UNIV_CAN_USE_X86_ASSEMBLER) 00211 mutex_reset_lock_word(mutex); 00212 #else 00213 os_fast_mutex_init(&(mutex->os_fast_mutex)); 00214 mutex->lock_word = 0; 00215 #endif 00216 mutex_set_waiters(mutex, 0); 00217 mutex->magic_n = MUTEX_MAGIC_N; 00218 #ifdef UNIV_SYNC_DEBUG 00219 mutex->line = 0; 00220 mutex->file_name = "not yet reserved"; 00221 #endif /* UNIV_SYNC_DEBUG */ 00222 mutex->level = level; 00223 mutex->cfile_name = cfile_name; 00224 mutex->cline = cline; 00225 #ifndef UNIV_HOTBACKUP 00226 mutex->cmutex_name= cmutex_name; 00227 mutex->count_using= 0; 00228 mutex->mutex_type= 0; 00229 mutex->lspent_time= 0; 00230 mutex->lmax_spent_time= 0; 00231 mutex->count_spin_loop= 0; 00232 mutex->count_spin_rounds= 0; 00233 mutex->count_os_wait= 0; 00234 mutex->count_os_yield= 0; 00235 #endif /* !UNIV_HOTBACKUP */ 00236 00237 /* Check that lock_word is aligned; this is important on Intel */ 00238 ut_ad(((ulint)(&(mutex->lock_word))) % 4 == 0); 00239 00240 /* NOTE! The very first mutexes are not put to the mutex list */ 00241 00242 if ((mutex == &mutex_list_mutex) || (mutex == &sync_thread_mutex)) { 00243 00244 return; 00245 } 00246 00247 mutex_enter(&mutex_list_mutex); 00248 00249 if (UT_LIST_GET_LEN(mutex_list) > 0) { 00250 ut_a(UT_LIST_GET_FIRST(mutex_list)->magic_n == MUTEX_MAGIC_N); 00251 } 00252 00253 UT_LIST_ADD_FIRST(list, mutex_list, mutex); 00254 00255 mutex_exit(&mutex_list_mutex); 00256 }
Here is the call graph for this function:

| void mutex_enter_noninline | ( | mutex_t * | mutex | ) |
Definition at line 177 of file sync0sync.c.
References mutex, and mutex_enter.
00179 : mutex */ 00180 { 00181 mutex_enter(mutex); 00182 }
| ulint mutex_enter_nowait | ( | mutex_t * | mutex, | |
| const char *file_name | __attribute__((unused)), | |||
| ulint line | __attribute__((unused)) | |||
| ) |
Definition at line 307 of file sync0sync.c.
References line, mutex, mutex_validate(), and ut_ad.
00309 : 0 if succeed, 1 if not */ 00310 mutex_t* mutex, /* in: pointer to mutex */ 00311 const char* file_name __attribute__((unused)), 00312 /* in: file name where mutex 00313 requested */ 00314 ulint line __attribute__((unused))) 00315 /* in: line where requested */ 00316 { 00317 ut_ad(mutex_validate(mutex)); 00318 00319 if (!mutex_test_and_set(mutex)) { 00320 00321 #ifdef UNIV_SYNC_DEBUG 00322 mutex_set_debug_info(mutex, file_name, line); 00323 #endif 00324 00325 return(0); /* Succeeded! */ 00326 } 00327 00328 return(1); 00329 }
Here is the call graph for this function:

| void mutex_exit_noninline | ( | mutex_t * | mutex | ) |
Definition at line 188 of file sync0sync.c.
References mutex, and mutex_exit().
00190 : mutex */ 00191 { 00192 mutex_exit(mutex); 00193 }
Here is the call graph for this function:

| void mutex_free | ( | mutex_t * | mutex | ) |
Definition at line 264 of file sync0sync.c.
References list(), mutex, mutex_enter, mutex_exit(), mutex_get_lock_word(), mutex_list, mutex_list_mutex, MUTEX_MAGIC_N, mutex_validate(), os_fast_mutex_free(), sync_thread_mutex, ut_a, UT_LIST_GET_NEXT, UT_LIST_GET_PREV, and UT_LIST_REMOVE.
Referenced by dict_mem_table_free(), ib_wqueue_free(), innobase_shutdown_for_mysql(), rw_lock_free(), sync_array_free(), sync_close(), and trx_free().
00266 : mutex */ 00267 { 00268 #ifdef UNIV_DEBUG 00269 ut_a(mutex_validate(mutex)); 00270 #endif /* UNIV_DEBUG */ 00271 ut_a(mutex_get_lock_word(mutex) == 0); 00272 ut_a(mutex_get_waiters(mutex) == 0); 00273 00274 if (mutex != &mutex_list_mutex && mutex != &sync_thread_mutex) { 00275 00276 mutex_enter(&mutex_list_mutex); 00277 00278 if (UT_LIST_GET_PREV(list, mutex)) { 00279 ut_a(UT_LIST_GET_PREV(list, mutex)->magic_n 00280 == MUTEX_MAGIC_N); 00281 } 00282 if (UT_LIST_GET_NEXT(list, mutex)) { 00283 ut_a(UT_LIST_GET_NEXT(list, mutex)->magic_n 00284 == MUTEX_MAGIC_N); 00285 } 00286 00287 UT_LIST_REMOVE(list, mutex_list, mutex); 00288 00289 mutex_exit(&mutex_list_mutex); 00290 } 00291 00292 #if !defined(_WIN32) || !defined(UNIV_CAN_USE_X86_ASSEMBLER) 00293 os_fast_mutex_free(&(mutex->os_fast_mutex)); 00294 #endif 00295 /* If we free the mutex protecting the mutex list (freeing is 00296 not necessary), we have to reset the magic number AFTER removing 00297 it from the list. */ 00298 00299 mutex->magic_n = 0; 00300 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 349 of file sync0sync.c.
Referenced by mutex_create_func(), mutex_signal_object(), and mutex_spin_wait().
00351 : mutex */ 00352 ulint n) /* in: value to set */ 00353 { 00354 volatile ulint* ptr; /* declared volatile to ensure that 00355 the value is stored to memory */ 00356 ut_ad(mutex); 00357 00358 ptr = &(mutex->waiters); 00359 00360 *ptr = n; /* Here we assume that the write of a single 00361 word in memory is atomic */ 00362 }
Here is the caller graph for this function:

| void mutex_signal_object | ( | mutex_t * | mutex | ) |
Definition at line 549 of file sync0sync.c.
References mutex, mutex_set_waiters(), sync_array_signal_object(), and sync_primary_wait_array.
00551 : mutex */ 00552 { 00553 mutex_set_waiters(mutex, 0); 00554 00555 /* The memory order of resetting the waiters field and 00556 signaling the object is important. See LEMMA 1 above. */ 00557 00558 sync_array_signal_object(sync_primary_wait_array, mutex); 00559 }
Here is the call graph for this function:

Definition at line 370 of file sync0sync.c.
References index(), mutex, mutex_get_lock_word(), mutex_os_wait_count, mutex_set_waiters(), mutex_spin_round_count, mutex_spin_wait_count, mutex_system_call_count, os_thread_get_curr_id(), os_thread_pf(), os_thread_yield(), sec, srv_spin_wait_delay, sync_array_free_cell_protected(), sync_array_reserve_cell(), sync_array_wait_event(), SYNC_MUTEX, sync_primary_wait_array, SYNC_SPIN_ROUNDS, timed_mutexes, ut_ad, ut_delay(), ut_rnd_interval(), and ut_usectime().
00372 : pointer to mutex */ 00373 const char* file_name, /* in: file name where mutex 00374 requested */ 00375 ulint line) /* in: line where requested */ 00376 { 00377 ulint index; /* index of the reserved wait cell */ 00378 ulint i; /* spin round count */ 00379 #ifndef UNIV_HOTBACKUP 00380 ib_longlong lstart_time = 0, lfinish_time; /* for timing os_wait */ 00381 ulint ltime_diff; 00382 ulint sec; 00383 ulint ms; 00384 uint timer_started = 0; 00385 #endif /* !UNIV_HOTBACKUP */ 00386 ut_ad(mutex); 00387 00388 mutex_loop: 00389 00390 i = 0; 00391 00392 /* Spin waiting for the lock word to become zero. Note that we do 00393 not have to assume that the read access to the lock word is atomic, 00394 as the actual locking is always committed with atomic test-and-set. 00395 In reality, however, all processors probably have an atomic read of 00396 a memory word. */ 00397 00398 spin_loop: 00399 #ifndef UNIV_HOTBACKUP 00400 mutex_spin_wait_count++; 00401 mutex->count_spin_loop++; 00402 #endif /* !UNIV_HOTBACKUP */ 00403 00404 while (mutex_get_lock_word(mutex) != 0 && i < SYNC_SPIN_ROUNDS) { 00405 if (srv_spin_wait_delay) { 00406 ut_delay(ut_rnd_interval(0, srv_spin_wait_delay)); 00407 } 00408 00409 i++; 00410 } 00411 00412 if (i == SYNC_SPIN_ROUNDS) { 00413 #ifndef UNIV_HOTBACKUP 00414 mutex->count_os_yield++; 00415 if (timed_mutexes == 1 && timer_started==0) { 00416 ut_usectime(&sec, &ms); 00417 lstart_time= (ib_longlong)sec * 1000000 + ms; 00418 timer_started = 1; 00419 } 00420 #endif /* !UNIV_HOTBACKUP */ 00421 os_thread_yield(); 00422 } 00423 00424 #ifdef UNIV_SRV_PRINT_LATCH_WAITS 00425 fprintf(stderr, 00426 "Thread %lu spin wait mutex at %p cfile %s cline %lu rnds %lu\n", 00427 (ulong) os_thread_pf(os_thread_get_curr_id()), (void*) mutex, 00428 mutex->cfile_name, (ulong) mutex->cline, (ulong) i); 00429 #endif 00430 00431 mutex_spin_round_count += i; 00432 00433 #ifndef UNIV_HOTBACKUP 00434 mutex->count_spin_rounds += i; 00435 #endif /* !UNIV_HOTBACKUP */ 00436 00437 if (mutex_test_and_set(mutex) == 0) { 00438 /* Succeeded! */ 00439 00440 #ifdef UNIV_SYNC_DEBUG 00441 mutex_set_debug_info(mutex, file_name, line); 00442 #endif 00443 00444 goto finish_timing; 00445 } 00446 00447 /* We may end up with a situation where lock_word is 0 but the OS 00448 fast mutex is still reserved. On FreeBSD the OS does not seem to 00449 schedule a thread which is constantly calling pthread_mutex_trylock 00450 (in mutex_test_and_set implementation). Then we could end up 00451 spinning here indefinitely. The following 'i++' stops this infinite 00452 spin. */ 00453 00454 i++; 00455 00456 if (i < SYNC_SPIN_ROUNDS) { 00457 goto spin_loop; 00458 } 00459 00460 sync_array_reserve_cell(sync_primary_wait_array, mutex, 00461 SYNC_MUTEX, file_name, line, &index); 00462 00463 mutex_system_call_count++; 00464 00465 /* The memory order of the array reservation and the change in the 00466 waiters field is important: when we suspend a thread, we first 00467 reserve the cell and then set waiters field to 1. When threads are 00468 released in mutex_exit, the waiters field is first set to zero and 00469 then the event is set to the signaled state. */ 00470 00471 mutex_set_waiters(mutex, 1); 00472 00473 /* Try to reserve still a few times */ 00474 for (i = 0; i < 4; i++) { 00475 if (mutex_test_and_set(mutex) == 0) { 00476 /* Succeeded! Free the reserved wait cell */ 00477 00478 sync_array_free_cell_protected(sync_primary_wait_array, 00479 index); 00480 00481 #ifdef UNIV_SYNC_DEBUG 00482 mutex_set_debug_info(mutex, file_name, line); 00483 #endif 00484 00485 #ifdef UNIV_SRV_PRINT_LATCH_WAITS 00486 fprintf(stderr, "Thread %lu spin wait succeeds at 2:" 00487 " mutex at %p\n", 00488 (ulong) os_thread_pf(os_thread_get_curr_id()), 00489 (void*) mutex); 00490 #endif 00491 00492 goto finish_timing; 00493 00494 /* Note that in this case we leave the waiters field 00495 set to 1. We cannot reset it to zero, as we do not 00496 know if there are other waiters. */ 00497 } 00498 } 00499 00500 /* Now we know that there has been some thread holding the mutex 00501 after the change in the wait array and the waiters field was made. 00502 Now there is no risk of infinite wait on the event. */ 00503 00504 #ifdef UNIV_SRV_PRINT_LATCH_WAITS 00505 fprintf(stderr, 00506 "Thread %lu OS wait mutex at %p cfile %s cline %lu rnds %lu\n", 00507 (ulong) os_thread_pf(os_thread_get_curr_id()), (void*) mutex, 00508 mutex->cfile_name, (ulong) mutex->cline, (ulong) i); 00509 #endif 00510 00511 mutex_system_call_count++; 00512 mutex_os_wait_count++; 00513 00514 #ifndef UNIV_HOTBACKUP 00515 mutex->count_os_wait++; 00516 /* !!!!! Sometimes os_wait can be called without os_thread_yield */ 00517 00518 if (timed_mutexes == 1 && timer_started==0) { 00519 ut_usectime(&sec, &ms); 00520 lstart_time= (ib_longlong)sec * 1000000 + ms; 00521 timer_started = 1; 00522 } 00523 #endif /* !UNIV_HOTBACKUP */ 00524 00525 sync_array_wait_event(sync_primary_wait_array, index); 00526 goto mutex_loop; 00527 00528 finish_timing: 00529 #ifndef UNIV_HOTBACKUP 00530 if (timed_mutexes == 1 && timer_started==1) { 00531 ut_usectime(&sec, &ms); 00532 lfinish_time= (ib_longlong)sec * 1000000 + ms; 00533 00534 ltime_diff= (ulint) (lfinish_time - lstart_time); 00535 mutex->lspent_time += ltime_diff; 00536 00537 if (mutex->lmax_spent_time < ltime_diff) { 00538 mutex->lmax_spent_time= ltime_diff; 00539 } 00540 } 00541 #endif /* !UNIV_HOTBACKUP */ 00542 return; 00543 }
Here is the call graph for this function:

| ibool mutex_validate | ( | mutex_t * | mutex | ) |
Definition at line 335 of file sync0sync.c.
References mutex, MUTEX_MAGIC_N, TRUE, and ut_a.
Referenced by mutex_enter_nowait(), and mutex_free().
00338 { 00339 ut_a(mutex); 00340 ut_a(mutex->magic_n == MUTEX_MAGIC_N); 00341 00342 return(TRUE); 00343 }
Here is the caller graph for this function:

| void sync_close | ( | void | ) |
Definition at line 1306 of file sync0sync.c.
References mutex, mutex_free(), mutex_list, mutex_list_mutex, sync_array_free(), sync_primary_wait_array, sync_thread_mutex, and UT_LIST_GET_FIRST.
Referenced by innobase_shutdown_for_mysql().
01308 { 01309 mutex_t* mutex; 01310 01311 sync_array_free(sync_primary_wait_array); 01312 01313 mutex = UT_LIST_GET_FIRST(mutex_list); 01314 01315 while (mutex) { 01316 mutex_free(mutex); 01317 mutex = UT_LIST_GET_FIRST(mutex_list); 01318 } 01319 01320 mutex_free(&mutex_list_mutex); 01321 mutex_free(&sync_thread_mutex); 01322 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void sync_init | ( | void | ) |
Definition at line 1254 of file sync0sync.c.
References FALSE, sync_thread_struct::levels, mutex_create, mutex_list, mutex_list_mutex, NULL, os_event_create(), OS_THREAD_MAX_N, rw_lock_list, rw_lock_list_mutex, sync_array_create(), SYNC_ARRAY_OS_MUTEX, sync_initialized, SYNC_NO_ORDER_CHECK, sync_primary_wait_array, sync_thread_level_arrays, sync_thread_level_arrays_get_nth(), sync_thread_mutex, TRUE, ut_a, UT_LIST_INIT, and ut_malloc().
Referenced by srv_general_init().
01256 { 01257 sync_thread_t* thread_slot; 01258 ulint i; 01259 01260 ut_a(sync_initialized == FALSE); 01261 01262 sync_initialized = TRUE; 01263 01264 /* Create the primary system wait array which is protected by an OS 01265 mutex */ 01266 01267 sync_primary_wait_array = sync_array_create(OS_THREAD_MAX_N, 01268 SYNC_ARRAY_OS_MUTEX); 01269 01270 /* Create the thread latch level array where the latch levels 01271 are stored for each OS thread */ 01272 01273 sync_thread_level_arrays = ut_malloc(OS_THREAD_MAX_N 01274 * sizeof(sync_thread_t)); 01275 for (i = 0; i < OS_THREAD_MAX_N; i++) { 01276 01277 thread_slot = sync_thread_level_arrays_get_nth(i); 01278 thread_slot->levels = NULL; 01279 } 01280 01281 /* Init the mutex list and create the mutex to protect it. */ 01282 01283 UT_LIST_INIT(mutex_list); 01284 mutex_create(&mutex_list_mutex, SYNC_NO_ORDER_CHECK); 01285 01286 mutex_create(&sync_thread_mutex, SYNC_NO_ORDER_CHECK); 01287 01288 /* Init the rw-lock list and create the mutex to protect it. */ 01289 01290 UT_LIST_INIT(rw_lock_list); 01291 mutex_create(&rw_lock_list_mutex, SYNC_NO_ORDER_CHECK); 01292 01293 #ifdef UNIV_SYNC_DEBUG 01294 mutex_create(&rw_lock_debug_mutex, SYNC_NO_ORDER_CHECK); 01295 01296 rw_lock_debug_event = os_event_create(NULL); 01297 rw_lock_debug_waiters = FALSE; 01298 #endif /* UNIV_SYNC_DEBUG */ 01299 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void sync_print | ( | FILE * | file | ) |
Definition at line 1353 of file sync0sync.c.
References sync_array_print_info(), sync_primary_wait_array, and sync_print_wait_info().
Referenced by srv_printf_innodb_monitor().
01355 : file where to print */ 01356 { 01357 #ifdef UNIV_SYNC_DEBUG 01358 mutex_list_print_info(); 01359 01360 rw_lock_list_print_info(); 01361 #endif /* UNIV_SYNC_DEBUG */ 01362 01363 sync_array_print_info(file, sync_primary_wait_array); 01364 01365 sync_print_wait_info(file); 01366 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void sync_print_wait_info | ( | FILE * | file | ) |
Definition at line 1328 of file sync0sync.c.
References mutex_exit_count, mutex_os_wait_count, mutex_spin_round_count, mutex_spin_wait_count, rw_s_exit_count, rw_s_os_wait_count, rw_s_spin_wait_count, rw_x_exit_count, rw_x_os_wait_count, and rw_x_spin_wait_count.
Referenced by sync_print().
01330 : file where to print */ 01331 { 01332 #ifdef UNIV_SYNC_DEBUG 01333 fprintf(stderr, "Mutex exits %lu, rws exits %lu, rwx exits %lu\n", 01334 mutex_exit_count, rw_s_exit_count, rw_x_exit_count); 01335 #endif 01336 01337 fprintf(file, 01338 "Mutex spin waits %lu, rounds %lu, OS waits %lu\n" 01339 "RW-shared spins %lu, OS waits %lu; RW-excl spins %lu, OS waits %lu\n", 01340 (ulong) mutex_spin_wait_count, 01341 (ulong) mutex_spin_round_count, 01342 (ulong) mutex_os_wait_count, 01343 (ulong) rw_s_spin_wait_count, 01344 (ulong) rw_s_os_wait_count, 01345 (ulong) rw_x_spin_wait_count, 01346 (ulong) rw_x_os_wait_count); 01347 }
Here is the caller graph for this function:

| void sync_thread_add_level | ( | void * | latch, | |
| ulint | level | |||
| ) |
Definition at line 967 of file sync0sync.c.
References sync_thread_struct::id, sync_level_struct::latch, sync_level_struct::level, sync_thread_struct::levels, mutex_enter, mutex_list_mutex, NULL, os_thread_get_curr_id(), rw_lock_list_mutex, SYNC_ANY_LATCH, SYNC_BUF_BLOCK, SYNC_BUF_POOL, SYNC_DICT, SYNC_DICT_AUTOINC_MUTEX, SYNC_DICT_HEADER, SYNC_DICT_OPERATION, SYNC_DOUBLEWRITE, SYNC_EXTERN_STORAGE, SYNC_FSP, SYNC_FSP_PAGE, SYNC_IBUF_BITMAP, SYNC_IBUF_BITMAP_MUTEX, SYNC_IBUF_HEADER, SYNC_IBUF_MUTEX, SYNC_IBUF_PESS_INSERT_MUTEX, SYNC_INDEX_TREE, SYNC_KERNEL, SYNC_LEVEL_VARYING, SYNC_LOG, SYNC_MEM_HASH, SYNC_MEM_POOL, SYNC_NO_ORDER_CHECK, sync_order_checks_on, SYNC_PURGE_LATCH, SYNC_PURGE_SYS, SYNC_REC_LOCK, SYNC_RECV, SYNC_RSEG, SYNC_RSEG_HEADER, SYNC_RSEG_HEADER_NEW, SYNC_SEARCH_SYS, SYNC_THR_LOCAL, sync_thread_level_arrays_find_free(), sync_thread_level_arrays_find_slot(), sync_thread_levels_contain(), sync_thread_levels_g(), sync_thread_levels_get_nth(), sync_thread_mutex, SYNC_THREAD_N_LEVELS, SYNC_TREE_NODE, SYNC_TREE_NODE_FROM_HASH, SYNC_TREE_NODE_NEW, SYNC_TRX_LOCK_HEAP, SYNC_TRX_SYS_HEADER, SYNC_TRX_UNDO, SYNC_TRX_UNDO_PAGE, SYNC_WORK_QUEUE, ut_a, ut_error, and ut_malloc().
00969 : pointer to a mutex or an rw-lock */ 00970 ulint level) /* in: level in the latching order; if 00971 SYNC_LEVEL_VARYING, nothing is done */ 00972 { 00973 sync_level_t* array; 00974 sync_level_t* slot; 00975 sync_thread_t* thread_slot; 00976 ulint i; 00977 00978 if (!sync_order_checks_on) { 00979 00980 return; 00981 } 00982 00983 if ((latch == (void*)&sync_thread_mutex) 00984 || (latch == (void*)&mutex_list_mutex) 00985 #ifdef UNIV_SYNC_DEBUG 00986 || (latch == (void*)&rw_lock_debug_mutex) 00987 #endif /* UNIV_SYNC_DEBUG */ 00988 || (latch == (void*)&rw_lock_list_mutex)) { 00989 00990 return; 00991 } 00992 00993 if (level == SYNC_LEVEL_VARYING) { 00994 00995 return; 00996 } 00997 00998 mutex_enter(&sync_thread_mutex); 00999 01000 thread_slot = sync_thread_level_arrays_find_slot(); 01001 01002 if (thread_slot == NULL) { 01003 /* We have to allocate the level array for a new thread */ 01004 array = ut_malloc(sizeof(sync_level_t) * SYNC_THREAD_N_LEVELS); 01005 01006 thread_slot = sync_thread_level_arrays_find_free(); 01007 01008 thread_slot->id = os_thread_get_curr_id(); 01009 thread_slot->levels = array; 01010 01011 for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) { 01012 01013 slot = sync_thread_levels_get_nth(array, i); 01014 01015 slot->latch = NULL; 01016 } 01017 } 01018 01019 array = thread_slot->levels; 01020 01021 /* NOTE that there is a problem with _NODE and _LEAF levels: if the 01022 B-tree height changes, then a leaf can change to an internal node 01023 or the other way around. We do not know at present if this can cause 01024 unnecessary assertion failures below. */ 01025 01026 switch (level) { 01027 case SYNC_NO_ORDER_CHECK: 01028 case SYNC_EXTERN_STORAGE: 01029 case SYNC_TREE_NODE_FROM_HASH: 01030 /* Do no order checking */ 01031 break; 01032 case SYNC_MEM_POOL: 01033 ut_a(sync_thread_levels_g(array, SYNC_MEM_POOL)); 01034 break; 01035 case SYNC_MEM_HASH: 01036 ut_a(sync_thread_levels_g(array, SYNC_MEM_HASH)); 01037 break; 01038 case SYNC_RECV: 01039 ut_a(sync_thread_levels_g(array, SYNC_RECV)); 01040 break; 01041 case SYNC_WORK_QUEUE: 01042 ut_a(sync_thread_levels_g(array, SYNC_WORK_QUEUE)); 01043 break; 01044 case SYNC_LOG: 01045 ut_a(sync_thread_levels_g(array, SYNC_LOG)); 01046 break; 01047 case SYNC_THR_LOCAL: 01048 ut_a(sync_thread_levels_g(array, SYNC_THR_LOCAL)); 01049 break; 01050 case SYNC_ANY_LATCH: 01051 ut_a(sync_thread_levels_g(array, SYNC_ANY_LATCH)); 01052 break; 01053 case SYNC_TRX_SYS_HEADER: 01054 ut_a(sync_thread_levels_g(array, SYNC_TRX_SYS_HEADER)); 01055 break; 01056 case SYNC_DOUBLEWRITE: 01057 ut_a(sync_thread_levels_g(array, SYNC_DOUBLEWRITE)); 01058 break; 01059 case SYNC_BUF_BLOCK: 01060 ut_a((sync_thread_levels_contain(array, SYNC_BUF_POOL) 01061 && sync_thread_levels_g(array, SYNC_BUF_BLOCK - 1)) 01062 || sync_thread_levels_g(array, SYNC_BUF_BLOCK)); 01063 break; 01064 case SYNC_BUF_POOL: 01065 ut_a(sync_thread_levels_g(array, SYNC_BUF_POOL)); 01066 break; 01067 case SYNC_SEARCH_SYS: 01068 ut_a(sync_thread_levels_g(array, SYNC_SEARCH_SYS)); 01069 break; 01070 case SYNC_TRX_LOCK_HEAP: 01071 ut_a(sync_thread_levels_g(array, SYNC_TRX_LOCK_HEAP)); 01072 break; 01073 case SYNC_REC_LOCK: 01074 ut_a((sync_thread_levels_contain(array, SYNC_KERNEL) 01075 && sync_thread_levels_g(array, SYNC_REC_LOCK - 1)) 01076 || sync_thread_levels_g(array, SYNC_REC_LOCK)); 01077 break; 01078 case SYNC_KERNEL: 01079 ut_a(sync_thread_levels_g(array, SYNC_KERNEL)); 01080 break; 01081 case SYNC_IBUF_BITMAP: 01082 ut_a((sync_thread_levels_contain(array, SYNC_IBUF_BITMAP_MUTEX) 01083 && sync_thread_levels_g(array, SYNC_IBUF_BITMAP - 1)) 01084 || sync_thread_levels_g(array, SYNC_IBUF_BITMAP)); 01085 break; 01086 case SYNC_IBUF_BITMAP_MUTEX: 01087 ut_a(sync_thread_levels_g(array, SYNC_IBUF_BITMAP_MUTEX)); 01088 break; 01089 case SYNC_FSP_PAGE: 01090 ut_a(sync_thread_levels_contain(array, SYNC_FSP)); 01091 break; 01092 case SYNC_FSP: 01093 ut_a(sync_thread_levels_contain(array, SYNC_FSP) 01094 || sync_thread_levels_g(array, SYNC_FSP)); 01095 break; 01096 case SYNC_TRX_UNDO_PAGE: 01097 ut_a(sync_thread_levels_contain(array, SYNC_TRX_UNDO) 01098 || sync_thread_levels_contain(array, SYNC_RSEG) 01099 || sync_thread_levels_contain(array, SYNC_PURGE_SYS) 01100 || sync_thread_levels_g(array, SYNC_TRX_UNDO_PAGE)); 01101 break; 01102 case SYNC_RSEG_HEADER: 01103 ut_a(sync_thread_levels_contain(array, SYNC_RSEG)); 01104 break; 01105 case SYNC_RSEG_HEADER_NEW: 01106 ut_a(sync_thread_levels_contain(array, SYNC_KERNEL) 01107 && sync_thread_levels_contain(array, SYNC_FSP_PAGE)); 01108 break; 01109 case SYNC_RSEG: 01110 ut_a(sync_thread_levels_g(array, SYNC_RSEG)); 01111 break; 01112 case SYNC_TRX_UNDO: 01113 ut_a(sync_thread_levels_g(array, SYNC_TRX_UNDO)); 01114 break; 01115 case SYNC_PURGE_LATCH: 01116 ut_a(sync_thread_levels_g(array, SYNC_PURGE_LATCH)); 01117 break; 01118 case SYNC_PURGE_SYS: 01119 ut_a(sync_thread_levels_g(array, SYNC_PURGE_SYS)); 01120 break; 01121 case SYNC_TREE_NODE: 01122 ut_a(sync_thread_levels_contain(array, SYNC_INDEX_TREE) 01123 || sync_thread_levels_g(array, SYNC_TREE_NODE - 1)); 01124 break; 01125 case SYNC_TREE_NODE_NEW: 01126 ut_a(sync_thread_levels_contain(array, SYNC_FSP_PAGE) 01127 || sync_thread_levels_contain(array, SYNC_IBUF_MUTEX)); 01128 break; 01129 case SYNC_INDEX_TREE: 01130 ut_a((sync_thread_levels_contain(array, SYNC_IBUF_MUTEX) 01131 && sync_thread_levels_contain(array, SYNC_FSP) 01132 && sync_thread_levels_g(array, SYNC_FSP_PAGE - 1)) 01133 || sync_thread_levels_g(array, SYNC_TREE_NODE - 1)); 01134 break; 01135 case SYNC_IBUF_MUTEX: 01136 ut_a(sync_thread_levels_g(array, SYNC_FSP_PAGE - 1)); 01137 break; 01138 case SYNC_IBUF_PESS_INSERT_MUTEX: 01139 ut_a(sync_thread_levels_g(array, SYNC_FSP - 1) 01140 && !sync_thread_levels_contain(array, SYNC_IBUF_MUTEX)); 01141 break; 01142 case SYNC_IBUF_HEADER: 01143 ut_a(sync_thread_levels_g(array, SYNC_FSP - 1) 01144 && !sync_thread_levels_contain(array, SYNC_IBUF_MUTEX) 01145 && !sync_thread_levels_contain(array, 01146 SYNC_IBUF_PESS_INSERT_MUTEX)); 01147 break; 01148 case SYNC_DICT_AUTOINC_MUTEX: 01149 ut_a(sync_thread_levels_g(array, SYNC_DICT_AUTOINC_MUTEX)); 01150 break; 01151 case SYNC_DICT_OPERATION: 01152 ut_a(sync_thread_levels_g(array, SYNC_DICT_OPERATION)); 01153 break; 01154 case SYNC_DICT_HEADER: 01155 ut_a(sync_thread_levels_g(array, SYNC_DICT_HEADER)); 01156 break; 01157 case SYNC_DICT: 01158 #ifdef UNIV_DEBUG 01159 ut_a(buf_debug_prints 01160 || sync_thread_levels_g(array, SYNC_DICT)); 01161 #else /* UNIV_DEBUG */ 01162 ut_a(sync_thread_levels_g(array, SYNC_DICT)); 01163 #endif /* UNIV_DEBUG */ 01164 break; 01165 default: 01166 ut_error; 01167 } 01168 01169 for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) { 01170 01171 slot = sync_thread_levels_get_nth(array, i); 01172 01173 if (slot->latch == NULL) { 01174 slot->latch = latch; 01175 slot->level = level; 01176 01177 break; 01178 } 01179 } 01180 01181 ut_a(i < SYNC_THREAD_N_LEVELS); 01182 01183 mutex_exit(&sync_thread_mutex); 01184 }
Here is the call graph for this function:

| static sync_thread_t* sync_thread_level_arrays_find_free | ( | void | ) | [static] |
Definition at line 758 of file sync0sync.c.
References sync_thread_struct::levels, NULL, OS_THREAD_MAX_N, and sync_thread_level_arrays_get_nth().
Referenced by sync_thread_add_level().
00760 : pointer to thread slot */ 00761 00762 { 00763 sync_thread_t* slot; 00764 ulint i; 00765 00766 for (i = 0; i < OS_THREAD_MAX_N; i++) { 00767 00768 slot = sync_thread_level_arrays_get_nth(i); 00769 00770 if (slot->levels == NULL) { 00771 00772 return(slot); 00773 } 00774 } 00775 00776 return(NULL); 00777 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static sync_thread_t* sync_thread_level_arrays_find_slot | ( | void | ) | [static] |
Definition at line 730 of file sync0sync.c.
References sync_thread_struct::id, id, sync_thread_struct::levels, os_thread_eq(), os_thread_get_curr_id(), OS_THREAD_MAX_N, and sync_thread_level_arrays_get_nth().
Referenced by sync_thread_add_level(), sync_thread_levels_empty_gen(), and sync_thread_reset_level().
00732 : pointer to thread slot, NULL if not found */ 00733 00734 { 00735 sync_thread_t* slot; 00736 os_thread_id_t id; 00737 ulint i; 00738 00739 id = os_thread_get_curr_id(); 00740 00741 for (i = 0; i < OS_THREAD_MAX_N; i++) { 00742 00743 slot = sync_thread_level_arrays_get_nth(i); 00744 00745 if (slot->levels && os_thread_eq(slot->id, id)) { 00746 00747 return(slot); 00748 } 00749 } 00750 00751 return(NULL); 00752 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static sync_thread_t* sync_thread_level_arrays_get_nth | ( | ulint | n | ) | [static] |
Definition at line 716 of file sync0sync.c.
References OS_THREAD_MAX_N, sync_thread_level_arrays, and ut_ad.
Referenced by sync_init(), sync_thread_level_arrays_find_free(), and sync_thread_level_arrays_find_slot().
00718 : pointer to thread slot */ 00719 ulint n) /* in: slot number */ 00720 { 00721 ut_ad(n < OS_THREAD_MAX_N); 00722 00723 return(sync_thread_level_arrays + n); 00724 }
Here is the caller graph for this function:

| static ibool sync_thread_levels_contain | ( | sync_level_t * | arr, | |
| ulint | level | |||
| ) | [static] |
Definition at line 869 of file sync0sync.c.
References sync_level_struct::latch, sync_level_struct::level, NULL, sync_thread_levels_get_nth(), SYNC_THREAD_N_LEVELS, and TRUE.
Referenced by sync_thread_add_level().
00871 : TRUE if stored */ 00872 sync_level_t* arr, /* in: pointer to level array for an OS 00873 thread */ 00874 ulint level) /* in: level */ 00875 { 00876 sync_level_t* slot; 00877 ulint i; 00878 00879 for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) { 00880 00881 slot = sync_thread_levels_get_nth(arr, i); 00882 00883 if (slot->latch != NULL) { 00884 if (slot->level == level) { 00885 00886 return(TRUE); 00887 } 00888 } 00889 } 00890 00891 return(FALSE); 00892 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ibool sync_thread_levels_empty | ( | void | ) |
Definition at line 954 of file sync0sync.c.
References FALSE, and sync_thread_levels_empty_gen().
00956 : TRUE if empty */ 00957 { 00958 return(sync_thread_levels_empty_gen(FALSE)); 00959 }
Here is the call graph for this function:

| ibool sync_thread_levels_empty_gen | ( | ibool | dict_mutex_allowed | ) |
Definition at line 898 of file sync0sync.c.
References FALSE, sync_level_struct::latch, sync_level_struct::level, sync_thread_struct::levels, mutex_enter, mutex_exit(), NULL, SYNC_DICT, SYNC_DICT_OPERATION, sync_order_checks_on, sync_thread_level_arrays_find_slot(), sync_thread_levels_get_nth(), sync_thread_mutex, SYNC_THREAD_N_LEVELS, TRUE, and ut_error.
Referenced by buf_flush_batch(), row_sel(), and sync_thread_levels_empty().
00900 : TRUE if empty except the 00901 exceptions specified below */ 00902 ibool dict_mutex_allowed) /* in: TRUE if dictionary mutex is 00903 allowed to be owned by the thread, 00904 also purge_is_running mutex is 00905 allowed */ 00906 { 00907 sync_level_t* arr; 00908 sync_thread_t* thread_slot; 00909 sync_level_t* slot; 00910 ulint i; 00911 00912 if (!sync_order_checks_on) { 00913 00914 return(TRUE); 00915 } 00916 00917 mutex_enter(&sync_thread_mutex); 00918 00919 thread_slot = sync_thread_level_arrays_find_slot(); 00920 00921 if (thread_slot == NULL) { 00922 00923 mutex_exit(&sync_thread_mutex); 00924 00925 return(TRUE); 00926 } 00927 00928 arr = thread_slot->levels; 00929 00930 for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) { 00931 00932 slot = sync_thread_levels_get_nth(arr, i); 00933 00934 if (slot->latch != NULL && (!dict_mutex_allowed || 00935 (slot->level != SYNC_DICT 00936 && slot->level != SYNC_DICT_OPERATION))) { 00937 00938 mutex_exit(&sync_thread_mutex); 00939 ut_error; 00940 00941 return(FALSE); 00942 } 00943 } 00944 00945 mutex_exit(&sync_thread_mutex); 00946 00947 return(TRUE); 00948 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static ibool sync_thread_levels_g | ( | sync_level_t * | arr, | |
| ulint | limit | |||
| ) | [static] |
Definition at line 800 of file sync0sync.c.
References FALSE, sync_level_struct::latch, sync_level_struct::level, lock, mutex, mutex_get_lock_word(), MUTEX_MAGIC_N, NULL, os_thread_pf(), sync_thread_levels_get_nth(), and SYNC_THREAD_N_LEVELS.
Referenced by sync_thread_add_level().
00802 : TRUE if all greater */ 00803 sync_level_t* arr, /* in: pointer to level array for an OS 00804 thread */ 00805 ulint limit) /* in: level limit */ 00806 { 00807 sync_level_t* slot; 00808 rw_lock_t* lock; 00809 mutex_t* mutex; 00810 ulint i; 00811 00812 for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) { 00813 00814 slot = sync_thread_levels_get_nth(arr, i); 00815 00816 if (slot->latch != NULL) { 00817 if (slot->level <= limit) { 00818 00819 lock = slot->latch; 00820 mutex = slot->latch; 00821 00822 fprintf(stderr, 00823 "InnoDB error: sync levels should be > %lu but a level is %lu\n", 00824 (ulong) limit, (ulong) slot->level); 00825 00826 if (mutex->magic_n == MUTEX_MAGIC_N) { 00827 fprintf(stderr, 00828 "Mutex created at %s %lu\n", 00829 mutex->cfile_name, 00830 (ulong) mutex->cline); 00831 00832 if (mutex_get_lock_word(mutex) != 0) { 00833 #ifdef UNIV_SYNC_DEBUG 00834 const char* file_name; 00835 ulint line; 00836 os_thread_id_t thread_id; 00837 00838 mutex_get_debug_info(mutex, 00839 &file_name, &line, &thread_id); 00840 00841 fprintf(stderr, 00842 "InnoDB: Locked mutex: addr %p thread %ld file %s line %ld\n", 00843 (void*) mutex, os_thread_pf(thread_id), file_name, (ulong) line); 00844 #else /* UNIV_SYNC_DEBUG */ 00845 fprintf(stderr, 00846 "InnoDB: Locked mutex: addr %p\n", (void*) mutex); 00847 #endif /* UNIV_SYNC_DEBUG */ 00848 } else { 00849 fputs("Not locked\n", stderr); 00850 } 00851 } else { 00852 #ifdef UNIV_SYNC_DEBUG 00853 rw_lock_print(lock); 00854 #endif /* UNIV_SYNC_DEBUG */ 00855 } 00856 00857 return(FALSE); 00858 } 00859 } 00860 } 00861 00862 return(TRUE); 00863 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static sync_level_t* sync_thread_levels_get_nth | ( | sync_level_t * | arr, | |
| ulint | n | |||
| ) | [static] |
Definition at line 783 of file sync0sync.c.
References SYNC_THREAD_N_LEVELS, and ut_ad.
Referenced by sync_thread_add_level(), sync_thread_levels_contain(), sync_thread_levels_empty_gen(), sync_thread_levels_g(), and sync_thread_reset_level().
00785 : pointer to level slot */ 00786 sync_level_t* arr, /* in: pointer to level array for an OS 00787 thread */ 00788 ulint n) /* in: slot number */ 00789 { 00790 ut_ad(n < SYNC_THREAD_N_LEVELS); 00791 00792 return(arr + n); 00793 }
Here is the caller graph for this function:

| ibool sync_thread_reset_level | ( | void * | latch | ) |
Definition at line 1190 of file sync0sync.c.
References FALSE, sync_level_struct::latch, sync_thread_struct::levels, mutex_enter, mutex_exit(), mutex_list_mutex, NULL, rw_lock_list_mutex, sync_order_checks_on, sync_thread_level_arrays_find_slot(), sync_thread_levels_get_nth(), sync_thread_mutex, SYNC_THREAD_N_LEVELS, TRUE, and ut_error.
01192 : TRUE if found from the array; it is an error 01193 if the latch is not found */ 01194 void* latch) /* in: pointer to a mutex or an rw-lock */ 01195 { 01196 sync_level_t* array; 01197 sync_level_t* slot; 01198 sync_thread_t* thread_slot; 01199 ulint i; 01200 01201 if (!sync_order_checks_on) { 01202 01203 return(FALSE); 01204 } 01205 01206 if ((latch == (void*)&sync_thread_mutex) 01207 || (latch == (void*)&mutex_list_mutex) 01208 #ifdef UNIV_SYNC_DEBUG 01209 || (latch == (void*)&rw_lock_debug_mutex) 01210 #endif /* UNIV_SYNC_DEBUG */ 01211 || (latch == (void*)&rw_lock_list_mutex)) { 01212 01213 return(FALSE); 01214 } 01215 01216 mutex_enter(&sync_thread_mutex); 01217 01218 thread_slot = sync_thread_level_arrays_find_slot(); 01219 01220 if (thread_slot == NULL) { 01221 01222 ut_error; 01223 01224 mutex_exit(&sync_thread_mutex); 01225 return(FALSE); 01226 } 01227 01228 array = thread_slot->levels; 01229 01230 for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) { 01231 01232 slot = sync_thread_levels_get_nth(array, i); 01233 01234 if (slot->latch == latch) { 01235 slot->latch = NULL; 01236 01237 mutex_exit(&sync_thread_mutex); 01238 01239 return(TRUE); 01240 } 01241 } 01242 01243 ut_error; 01244 01245 mutex_exit(&sync_thread_mutex); 01246 01247 return(FALSE); 01248 }
Here is the call graph for this function:

Definition at line 154 of file sync0sync.c.
| ut_list_base_node_t mutex_list |
Definition at line 145 of file sync0sync.c.
Referenced by mutex_create_func(), mutex_free(), sync_close(), and sync_init().
Definition at line 148 of file sync0sync.c.
Referenced by mutex_create_func(), mutex_free(), sync_close(), sync_init(), sync_thread_add_level(), and sync_thread_reset_level().
Definition at line 122 of file sync0sync.c.
Referenced by mutex_spin_wait(), and sync_print_wait_info().
Definition at line 120 of file sync0sync.c.
Referenced by mutex_spin_wait(), and sync_print_wait_info().
Definition at line 121 of file sync0sync.c.
Referenced by mutex_spin_wait(), and sync_print_wait_info().
| ulint sync_dummy = 0 |
Definition at line 111 of file sync0sync.c.
| ibool sync_initialized = FALSE |
| ibool sync_order_checks_on = FALSE |
Definition at line 151 of file sync0sync.c.
Referenced by innobase_start_or_create_for_mysql(), sync_thread_add_level(), sync_thread_levels_empty_gen(), and sync_thread_reset_level().
Definition at line 127 of file sync0sync.c.
Referenced by mutex_signal_object(), mutex_spin_wait(), rw_lock_s_lock_spin(), rw_lock_x_lock_func(), sync_arr_wake_threads_if_sema_free(), sync_array_print_long_waits(), sync_close(), sync_init(), and sync_print().
Definition at line 139 of file sync0sync.c.
Referenced by sync_init(), and sync_thread_level_arrays_get_nth().
Definition at line 142 of file sync0sync.c.
Referenced by mutex_create_func(), mutex_free(), sync_close(), sync_init(), sync_thread_add_level(), sync_thread_levels_empty_gen(), and sync_thread_reset_level().
1.4.7

