diff options
Diffstat (limited to 'innobase/sync/sync0sync.c')
-rw-r--r-- | innobase/sync/sync0sync.c | 260 |
1 files changed, 156 insertions, 104 deletions
diff --git a/innobase/sync/sync0sync.c b/innobase/sync/sync0sync.c index 86306e49cac..fb46c692830 100644 --- a/innobase/sync/sync0sync.c +++ b/innobase/sync/sync0sync.c @@ -129,11 +129,6 @@ sync_array_t* sync_primary_wait_array; /* This variable is set to TRUE when sync_init is called */ ibool sync_initialized = FALSE; -/* Global list of database mutexes (not OS mutexes) created. */ -UT_LIST_BASE_NODE_T(mutex_t) mutex_list; - -/* Mutex protecting the mutex_list variable */ -mutex_t mutex_list_mutex; typedef struct sync_level_struct sync_level_t; typedef struct sync_thread_struct sync_thread_t; @@ -202,7 +197,8 @@ mutex_create_func( /*==============*/ mutex_t* mutex, /* in: pointer to memory */ const char* cfile_name, /* in: file name where created */ - ulint cline) /* in: file line where created */ + ulint cline, /* in: file line where created */ + const char* cmutex_name) /* in: mutex name */ { #if defined(_WIN32) && defined(UNIV_CAN_USE_X86_ASSEMBLER) mutex_reset_lock_word(mutex); @@ -219,6 +215,16 @@ mutex_create_func( mutex->level = SYNC_LEVEL_NONE; mutex->cfile_name = cfile_name; mutex->cline = cline; + mutex->cmutex_name= cmutex_name; + mutex->count_using= 0; + mutex->mutex_type= 0; + mutex->lspent_time= 0; + mutex->lmax_spent_time= 0; + mutex->count_spin_loop= 0; + mutex->count_spin_rounds= 0; + mutex->count_os_wait= 0; + mutex->count_os_yield= 0; + /* Check that lock_word is aligned; this is important on Intel */ ut_ad(((ulint)(&(mutex->lock_word))) % 4 == 0); @@ -355,135 +361,180 @@ for the mutex before suspending the thread. */ void mutex_spin_wait( /*============*/ - mutex_t* mutex, /* in: pointer to mutex */ - const char* file_name, /* in: file name where - mutex requested */ - ulint line) /* in: line where requested */ + mutex_t* mutex, /* in: pointer to mutex */ + const char* file_name, /* in: file name where + mutex requested */ + ulint line) /* in: line where requested */ { - ulint index; /* index of the reserved wait cell */ - ulint i; /* spin round count */ - - ut_ad(mutex); + ulint index; /* index of the reserved wait cell */ + ulint i; /* spin round count */ + ib_longlong lstart_time, lfinish_time; /* for timing os_wait */ + ulint ltime_diff; + ulint sec; + ulint ms; -mutex_loop: + uint timer_started = 0; - i = 0; + ut_ad(mutex); - /* Spin waiting for the lock word to become zero. Note that we do not - have to assume that the read access to the lock word is atomic, as the - actual locking is always committed with atomic test-and-set. In - reality, however, all processors probably have an atomic read of a - memory word. */ - -spin_loop: - mutex_spin_wait_count++; +mutex_loop: - while (mutex_get_lock_word(mutex) != 0 && i < SYNC_SPIN_ROUNDS) { + i = 0; - if (srv_spin_wait_delay) { - ut_delay(ut_rnd_interval(0, srv_spin_wait_delay)); - } - - i++; - } +/* Spin waiting for the lock word to become zero. Note that we do not + have to assume that the read access to the lock word is atomic, as the + actual locking is always committed with atomic test-and-set. In + reality, however, all processors probably have an atomic read of a + memory word. */ - if (i == SYNC_SPIN_ROUNDS) { - os_thread_yield(); - } +spin_loop: + mutex_spin_wait_count++; + mutex->count_spin_loop++; + + while (mutex_get_lock_word(mutex) != 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) + { + mutex->count_os_yield++; + if (timed_mutexes == 1 && timer_started==0) + { + ut_usectime(&sec, &ms); + lstart_time= (ib_longlong)sec * 1000000 + ms; + timer_started = 1; + } + os_thread_yield(); + } + +#ifdef UNIV_SRV_PRINT_LATCH_WAITS + fprintf(stderr, + "Thread %lu spin wait mutex at %p cfile %s cline %lu rnds %lu\n", + (ulong) os_thread_pf(os_thread_get_curr_id()), mutex, + mutex->cfile_name, (ulong) mutex->cline, (ulong) i); +#endif - if (srv_print_latch_waits) { - fprintf(stderr, - "Thread %lu spin wait mutex at %p cfile %s cline %lu rnds %lu\n", - (ulong) os_thread_pf(os_thread_get_curr_id()), mutex, - mutex->cfile_name, (ulong) mutex->cline, (ulong) i); - } + mutex_spin_round_count += i; - mutex_spin_round_count += i; + mutex->count_spin_rounds += i; - if (mutex_test_and_set(mutex) == 0) { - /* Succeeded! */ + if (mutex_test_and_set(mutex) == 0) + { + /* Succeeded! */ #ifdef UNIV_SYNC_DEBUG - mutex_set_debug_info(mutex, file_name, line); + mutex_set_debug_info(mutex, file_name, line); #endif - return; - } + goto finish_timing; + } - /* We may end up with a situation where lock_word is - 0 but the OS fast mutex is still reserved. On FreeBSD - the OS does not seem to schedule a thread which is constantly - calling pthread_mutex_trylock (in mutex_test_and_set - implementation). Then we could end up spinning here indefinitely. - The following 'i++' stops this infinite spin. */ + /* We may end up with a situation where lock_word is + 0 but the OS fast mutex is still reserved. On FreeBSD + the OS does not seem to schedule a thread which is constantly + calling pthread_mutex_trylock (in mutex_test_and_set + implementation). Then we could end up spinning here indefinitely. + The following 'i++' stops this infinite spin. */ - i++; - - if (i < SYNC_SPIN_ROUNDS) { + i++; - goto spin_loop; - } + if (i < SYNC_SPIN_ROUNDS) + { + goto spin_loop; + } - sync_array_reserve_cell(sync_primary_wait_array, mutex, - SYNC_MUTEX, - file_name, line, - &index); + sync_array_reserve_cell(sync_primary_wait_array, mutex, + SYNC_MUTEX, file_name, line, &index); - mutex_system_call_count++; + mutex_system_call_count++; - /* The memory order of the array reservation and the change in the - waiters field is important: when we suspend a thread, we first - reserve the cell and then set waiters field to 1. When threads are - released in mutex_exit, the waiters field is first set to zero and - then the event is set to the signaled state. */ - - mutex_set_waiters(mutex, 1); + /* The memory order of the array reservation and the change in the + waiters field is important: when we suspend a thread, we first + reserve the cell and then set waiters field to 1. When threads are + released in mutex_exit, the waiters field is first set to zero and + then the event is set to the signaled state. */ + + mutex_set_waiters(mutex, 1); - /* Try to reserve still a few times */ - for (i = 0; i < 4; i++) { - if (mutex_test_and_set(mutex) == 0) { + /* Try to reserve still a few times */ + for (i = 0; i < 4; i++) + { + if (mutex_test_and_set(mutex) == 0) + { + /* Succeeded! Free the reserved wait cell */ - /* Succeeded! Free the reserved wait cell */ + sync_array_free_cell(sync_primary_wait_array, index); - sync_array_free_cell(sync_primary_wait_array, index); - #ifdef UNIV_SYNC_DEBUG - mutex_set_debug_info(mutex, file_name, line); + mutex_set_debug_info(mutex, file_name, line); #endif - if (srv_print_latch_waits) { - fprintf(stderr, - "Thread %lu spin wait succeeds at 2:" - " mutex at %p\n", - (ulong) os_thread_pf(os_thread_get_curr_id()), - mutex); - } - - return; +#ifdef UNIV_SRV_PRINT_LATCH_WAITS + fprintf(stderr, "Thread %lu spin wait succeeds at 2:" + " mutex at %p\n", + (ulong) os_thread_pf(os_thread_get_curr_id()), + mutex); +#endif - /* Note that in this case we leave the waiters field - set to 1. We cannot reset it to zero, as we do not know - if there are other waiters. */ - } - } + goto finish_timing; - /* Now we know that there has been some thread holding the mutex - after the change in the wait array and the waiters field was made. - Now there is no risk of infinite wait on the event. */ + /* Note that in this case we leave the waiters field + set to 1. We cannot reset it to zero, as we do not know + if there are other waiters. */ + } + } - if (srv_print_latch_waits) { - fprintf(stderr, - "Thread %lu OS wait mutex at %p cfile %s cline %lu rnds %lu\n", - (ulong) os_thread_pf(os_thread_get_curr_id()), mutex, - mutex->cfile_name, (ulong) mutex->cline, (ulong) i); - } - - mutex_system_call_count++; - mutex_os_wait_count++; + /* Now we know that there has been some thread holding the mutex + after the change in the wait array and the waiters field was made. +Now there is no risk of infinite wait on the event. */ - sync_array_wait_event(sync_primary_wait_array, index); +#ifdef UNIV_SRV_PRINT_LATCH_WAITS + fprintf(stderr, + "Thread %lu OS wait mutex at %p cfile %s cline %lu rnds %lu\n", + (ulong) os_thread_pf(os_thread_get_curr_id()), mutex, + mutex->cfile_name, (ulong) mutex->cline, (ulong) i); +#endif - goto mutex_loop; + mutex_system_call_count++; + mutex_os_wait_count++; + + mutex->count_os_wait++; + + /* + !!!!! Sometimes os_wait can be called without os_thread_yield + */ + + if (timed_mutexes == 1 && timer_started==0) + { + ut_usectime(&sec, &ms); + lstart_time= (ib_longlong)sec * 1000000 + ms; + timer_started = 1; + } + + + sync_array_wait_event(sync_primary_wait_array, index); + goto mutex_loop; + +finish_timing: + if (timed_mutexes == 1 && timer_started==1) + { + ut_usectime(&sec, &ms); + lfinish_time= (ib_longlong)sec * 1000000 + ms; + + ltime_diff= lfinish_time - lstart_time; + mutex->lspent_time += ltime_diff; + if (mutex->lmax_spent_time < ltime_diff) + { + mutex->lmax_spent_time= ltime_diff; + } + } + return; } /********************************************************************** @@ -555,6 +606,7 @@ mutex_set_level( mutex->level = level; } + #ifdef UNIV_SYNC_DEBUG /********************************************************************** Checks that the current thread owns the mutex. Works only in the debug |