diff options
author | vtkachenko@intelp4d.mysql.com <> | 2004-12-24 12:13:32 +0100 |
---|---|---|
committer | vtkachenko@intelp4d.mysql.com <> | 2004-12-24 12:13:32 +0100 |
commit | 78846b292369cbf6175baac768edd77183c0809e (patch) | |
tree | c26b31d028fae331ef7cf148ca410771f43ef0ef /innobase/sync/sync0sync.c | |
parent | 4ba850cab089b7d625bc4fa4fec63c07b35f0692 (diff) | |
download | mariadb-git-78846b292369cbf6175baac768edd77183c0809e.tar.gz |
logging_ok:
Logging to logging@openlogging.org accepted
sql_yacc.yy, sql_parse.cc, sql_lex.h, lex.h:
Implements the SHOW MUTEX STATUS command
set_var.cc, mysqld.cc, mysql_priv.h:
Added new GLOBAL variable timed_mutexes
ha_innodb.h:
New function innodb_mutex_show_status
ha_innodb.cc:
Added new innodb variables in SHOW STATUS
Implements the SHOW MUTEX STATUS command
innodb.test, innodb.result:
Added new row_lock_waits status variables tests.
variables.test, variables.result:
test new variable timed_mutexes
ut0ut.c:
New function ut_usectime.
sync0sync.c:
Mutex counting.
sync0rw.c:
New mutex parameters initialization.
srv0srv.c:
Counting row lock waits
row0sel.c, row0mysql.c:
Setting row_lock or table_lock state to thd.
que0que.c:
Added default no_lock_state to thd.
univ.i:
Added UNIV_SRV_PRINT_LATCH_WAITS debug define
sync0sync.ic:
Count mutex using.
sync0sync.h:
Added new parameters to mutex structure for counting.
sync0rw.h:
Added new parameters to rw_create_func.
srv0srv.h:
Added new innodb varuables to SHOW STATUS.
que0que.h:
Added thread lock states.
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 |