diff --git a/ha/ha0ha.c b/ha/ha0ha.c index 23ea2554f01..07dfb66afa8 100644 --- a/ha/ha0ha.c +++ b/ha/ha0ha.c @@ -18,16 +18,18 @@ Creates a hash table with >= n array cells. The actual number of cells is chosen to be a prime number slightly bigger than n. */ hash_table_t* -ha_create( -/*======*/ +ha_create_func( +/*===========*/ /* out, own: created table */ ibool in_btr_search, /* in: TRUE if the hash table is used in the btr_search module */ ulint n, /* in: number of array cells */ - ulint n_mutexes, /* in: number of mutexes to protect the - hash table: must be a power of 2, or 0 */ - ulint mutex_level) /* in: level of the mutexes in the latching +#ifdef UNIV_SYNC_DEBUG + ulint mutex_level, /* in: level of the mutexes in the latching order: this is used in the debug version */ +#endif /* UNIV_SYNC_DEBUG */ + ulint n_mutexes) /* in: number of mutexes to protect the + hash table: must be a power of 2, or 0 */ { hash_table_t* table; ulint i; diff --git a/ha/hash0hash.c b/ha/hash0hash.c index 6084a19fa27..4807015eee5 100644 --- a/ha/hash0hash.c +++ b/ha/hash0hash.c @@ -129,13 +129,15 @@ hash_table_free( Creates a mutex array to protect a hash table. */ void -hash_create_mutexes( -/*================*/ +hash_create_mutexes_func( +/*=====================*/ hash_table_t* table, /* in: hash table */ - ulint n_mutexes, /* in: number of mutexes, must be a - power of 2 */ - ulint sync_level) /* in: latching order level of the +#ifdef UNIV_SYNC_DEBUG + ulint sync_level, /* in: latching order level of the mutexes: used in the debug version */ +#endif /* UNIV_SYNC_DEBUG */ + ulint n_mutexes) /* in: number of mutexes, must be a + power of 2 */ { ulint i; diff --git a/handler/ha_innodb.cc b/handler/ha_innodb.cc index ea8676a60af..141b57733e8 100644 --- a/handler/ha_innodb.cc +++ b/handler/ha_innodb.cc @@ -6599,22 +6599,23 @@ innodb_mutex_show_status( { char buf1[IO_SIZE], buf2[IO_SIZE]; mutex_t* mutex; +#ifdef UNIV_DEBUG ulint rw_lock_count= 0; ulint rw_lock_count_spin_loop= 0; ulint rw_lock_count_spin_rounds= 0; ulint rw_lock_count_os_wait= 0; ulint rw_lock_count_os_yield= 0; ulonglong rw_lock_wait_time= 0; +#endif /* UNIV_DEBUG */ uint hton_name_len= strlen(innobase_hton_name), buf1len, buf2len; DBUG_ENTER("innodb_mutex_show_status"); -#ifdef MUTEX_PROTECT_TO_BE_ADDED_LATER - mutex_enter(&mutex_list_mutex); -#endif + mutex_enter_noninline(&mutex_list_mutex); mutex = UT_LIST_GET_FIRST(mutex_list); while (mutex != NULL) { +#ifdef UNIV_DEBUG if (mutex->mutex_type != 1) { if (mutex->count_using > 0) { buf1len= my_snprintf(buf1, sizeof(buf1), @@ -6635,9 +6636,8 @@ innodb_mutex_show_status( if (stat_print(thd, innobase_hton_name, hton_name_len, buf1, buf1len, buf2, buf2len)) { -#ifdef MUTEX_PROTECT_TO_BE_ADDED_LATER - mutex_exit(&mutex_list_mutex); -#endif + mutex_exit_noninline( + &mutex_list_mutex); DBUG_RETURN(1); } } @@ -6650,10 +6650,26 @@ innodb_mutex_show_status( rw_lock_count_os_yield += mutex->count_os_yield; rw_lock_wait_time += mutex->lspent_time; } +#else /* UNIV_DEBUG */ + buf1len= my_snprintf(buf1, sizeof(buf1), "%s:%lu", + mutex->cfile_name, (ulong) mutex->cline); + buf2len= my_snprintf(buf2, sizeof(buf2), "os_waits=%lu", + mutex->count_os_wait); + + if (stat_print(thd, innobase_hton_name, + hton_name_len, buf1, buf1len, + buf2, buf2len)) { + mutex_exit_noninline(&mutex_list_mutex); + DBUG_RETURN(1); + } +#endif /* UNIV_DEBUG */ mutex = UT_LIST_GET_NEXT(list, mutex); } + mutex_exit_noninline(&mutex_list_mutex); + +#ifdef UNIV_DEBUG buf2len= my_snprintf(buf2, sizeof(buf2), "count=%lu, spin_waits=%lu, spin_rounds=%lu, " "os_waits=%lu, os_yields=%lu, os_wait_times=%lu", @@ -6666,10 +6682,7 @@ innodb_mutex_show_status( STRING_WITH_LEN("rw_lock_mutexes"), buf2, buf2len)) { DBUG_RETURN(1); } - -#ifdef MUTEX_PROTECT_TO_BE_ADDED_LATER - mutex_exit(&mutex_list_mutex); -#endif +#endif /* UNIV_DEBUG */ DBUG_RETURN(FALSE); } diff --git a/include/ha0ha.h b/include/ha0ha.h index 9fc80ed301c..beaa06ae755 100644 --- a/include/ha0ha.h +++ b/include/ha0ha.h @@ -41,16 +41,23 @@ Creates a hash table with >= n array cells. The actual number of cells is chosen to be a prime number slightly bigger than n. */ hash_table_t* -ha_create( -/*======*/ +ha_create_func( +/*===========*/ /* out, own: created table */ ibool in_btr_search, /* in: TRUE if the hash table is used in the btr_search module */ ulint n, /* in: number of array cells */ - ulint n_mutexes, /* in: number of mutexes to protect the - hash table: must be a power of 2 */ - ulint mutex_level); /* in: level of the mutexes in the latching +#ifdef UNIV_SYNC_DEBUG + ulint mutex_level, /* in: level of the mutexes in the latching order: this is used in the debug version */ +#endif /* UNIV_SYNC_DEBUG */ + ulint n_mutexes); /* in: number of mutexes to protect the + hash table: must be a power of 2 */ +#ifdef UNIV_SYNC_DEBUG +# define ha_create(b,n_c,n_m,level) ha_create_func(b,n_c,level,n_m) +#else /* UNIV_SYNC_DEBUG */ +# define ha_create(b,n_c,n_m,level) ha_create_func(b,n_c,n_m) +#endif /* UNIV_SYNC_DEBUG */ /***************************************************************** Inserts an entry into a hash table. If an entry with the same fold number is found, its node is updated to point to the new data, and no new node diff --git a/include/hash0hash.h b/include/hash0hash.h index 31c5c57ae35..0ab02801fd1 100644 --- a/include/hash0hash.h +++ b/include/hash0hash.h @@ -31,12 +31,20 @@ hash_create( Creates a mutex array to protect a hash table. */ void -hash_create_mutexes( -/*================*/ +hash_create_mutexes_func( +/*=====================*/ hash_table_t* table, /* in: hash table */ - ulint n_mutexes, /* in: number of mutexes */ - ulint sync_level); /* in: latching order level of the +#ifdef UNIV_SYNC_DEBUG + ulint sync_level, /* in: latching order level of the mutexes: used in the debug version */ +#endif /* UNIV_SYNC_DEBUG */ + ulint n_mutexes); /* in: number of mutexes */ +#ifdef UNIV_SYNC_DEBUG +# define hash_create_mutexes(t,n,level) hash_create_mutexes_func(t,level,n) +#else /* UNIV_SYNC_DEBUG */ +# define hash_create_mutexes(t,n,level) hash_create_mutexes_func(t,n) +#endif /* UNIV_SYNC_DEBUG */ + /***************************************************************** Frees a hash table. */ diff --git a/include/sync0rw.h b/include/sync0rw.h index 7c0241f2e02..abf04253141 100644 --- a/include/sync0rw.h +++ b/include/sync0rw.h @@ -61,8 +61,18 @@ Creates, or rather, initializes an rw-lock object in a specified memory location (which must be appropriately aligned). The rw-lock is initialized to the non-locked state. Explicit freeing of the rw-lock with rw_lock_free is necessary only if the memory block containing it is freed. */ -#define rw_lock_create(L, level) \ - rw_lock_create_func((L), (level), __FILE__, __LINE__, #L) +#ifdef UNIV_DEBUG +# ifdef UNIV_SYNC_DEBUG +# define rw_lock_create(L, level) \ + rw_lock_create_func((L), (level), #L, __FILE__, __LINE__) +# else /* UNIV_SYNC_DEBUG */ +# define rw_lock_create(L, level) \ + rw_lock_create_func((L), #L, __FILE__, __LINE__) +# endif /* UNIV_SYNC_DEBUG */ +#else /* UNIV_DEBUG */ +# define rw_lock_create(L, level) \ + rw_lock_create_func((L), __FILE__, __LINE__) +#endif /* UNIV_DEBUG */ /********************************************************************** Creates, or rather, initializes an rw-lock object in a specified memory @@ -74,10 +84,14 @@ void rw_lock_create_func( /*================*/ rw_lock_t* lock, /* in: pointer to memory */ +#ifdef UNIV_DEBUG +# ifdef UNIV_SYNC_DEBUG ulint level, /* in: level */ +# endif /* UNIV_SYNC_DEBUG */ + const char* cmutex_name, /* in: mutex name */ +#endif /* UNIV_DEBUG */ const char* cfile_name, /* in: file name where created */ - ulint cline, /* in: file line where created */ - const char* cmutex_name); /* in: mutex name */ + ulint cline); /* in: file line where created */ /********************************************************************** Calling this function is obligatory only if the memory buffer containing the rw-lock is freed. Removes an rw-lock object from the global list. The diff --git a/include/sync0sync.h b/include/sync0sync.h index de2a336513a..5184ff24c8a 100644 --- a/include/sync0sync.h +++ b/include/sync0sync.h @@ -39,8 +39,18 @@ location (which must be appropriately aligned). The mutex is initialized in the reset state. Explicit freeing of the mutex with mutex_free is necessary only if the memory block containing it is freed. */ -#define mutex_create(M, level) \ - mutex_create_func((M), (level), __FILE__, __LINE__, #M) +#ifdef UNIV_DEBUG +# ifdef UNIV_SYNC_DEBUG +# define mutex_create(M, level) \ + mutex_create_func((M), #M, (level), __FILE__, __LINE__) +# else +# define mutex_create(M, level) \ + mutex_create_func((M), #M, __FILE__, __LINE__) +# endif +#else +# define mutex_create(M, level) \ + mutex_create_func((M), __FILE__, __LINE__) +#endif /********************************************************************** Creates, or rather, initializes a mutex object in a specified memory @@ -52,10 +62,14 @@ void mutex_create_func( /*==============*/ mutex_t* mutex, /* in: pointer to memory */ +#ifdef UNIV_DEBUG + const char* cmutex_name, /* in: mutex name */ +# ifdef UNIV_SYNC_DEBUG ulint level, /* in: level */ +# endif /* UNIV_SYNC_DEBUG */ +#endif /* UNIV_DEBUG */ const char* cfile_name, /* in: file name where created */ - ulint cline, /* in: file line where created */ - const char* cmutex_name); /* in: mutex name */ + ulint cline); /* in: file line where created */ /********************************************************************** Calling this function is obligatory only if the memory buffer containing the mutex is freed. Removes a mutex object from the mutex list. The mutex @@ -467,26 +481,29 @@ struct mutex_struct { ulint line; /* Line where the mutex was locked */ os_thread_id_t thread_id; /* Debug version: The thread id of the thread which locked the mutex. */ -#endif /* UNIV_SYNC_DEBUG */ ulint level; /* Level in the global latching order */ +#endif /* UNIV_SYNC_DEBUG */ const char* cfile_name;/* File name where mutex created */ - ulint cline; /* Line where created */ - ulint magic_n; + ulint cline; /* Line where created */ +#ifdef UNIV_DEBUG + ulint magic_n; +# define MUTEX_MAGIC_N (ulint)979585 +#endif /* UNIV_DEBUG */ #ifndef UNIV_HOTBACKUP - ulong count_using; /* count of times mutex used */ - ulong count_spin_loop; /* count of spin loops */ - ulong count_spin_rounds; /* count of spin rounds */ - ulong count_os_wait; /* count of os_wait */ - ulong count_os_yield; /* count of os_wait */ - ulonglong lspent_time; /* mutex os_wait timer msec */ - ulonglong lmax_spent_time; /* mutex os_wait timer msec */ - const char* cmutex_name;/* mutex name */ - ulint mutex_type;/* 0 - usual mutex 1 - rw_lock mutex */ + ulong count_os_wait; /* count of os_wait */ +# ifdef UNIV_DEBUG + ulong count_using; /* count of times mutex used */ + ulong count_spin_loop; /* count of spin loops */ + ulong count_spin_rounds; /* count of spin rounds */ + ulong count_os_yield; /* count of os_wait */ + ulonglong lspent_time; /* mutex os_wait timer msec */ + ulonglong lmax_spent_time; /* mutex os_wait timer msec */ + const char* cmutex_name;/* mutex name */ + ulint mutex_type;/* 0 - usual mutex 1 - rw_lock mutex */ +# endif /* UNIV_DEBUG */ #endif /* !UNIV_HOTBACKUP */ }; -#define MUTEX_MAGIC_N (ulint)979585 - /* The global array of wait cells for implementation of the databases own mutexes and read-write locks. Appears here for debugging purposes only! */ diff --git a/include/sync0sync.ic b/include/sync0sync.ic index bcecc3478b3..4b48a1469ff 100644 --- a/include/sync0sync.ic +++ b/include/sync0sync.ic @@ -254,9 +254,9 @@ mutex_enter_func( /* Note that we do not peek at the value of lock_word before trying the atomic test_and_set; we could peek, and possibly save time. */ -#ifndef UNIV_HOTBACKUP +#if defined UNIV_DEBUG && !defined UNIV_HOTBACKUP mutex->count_using++; -#endif /* UNIV_HOTBACKUP */ +#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */ if (!mutex_test_and_set(mutex)) { #ifdef UNIV_SYNC_DEBUG diff --git a/sync/sync0rw.c b/sync/sync0rw.c index 441933843d7..549ad36271b 100644 --- a/sync/sync0rw.c +++ b/sync/sync0rw.c @@ -89,11 +89,14 @@ void rw_lock_create_func( /*================*/ rw_lock_t* lock, /* in: pointer to memory */ - ulint level __attribute__((unused)), - /* in: level */ +#ifdef UNIV_DEBUG +# ifdef UNIV_SYNC_DEBUG + ulint level, /* in: level */ +# endif /* UNIV_SYNC_DEBUG */ + const char* cmutex_name, /* in: mutex name */ +#endif /* UNIV_DEBUG */ const char* cfile_name, /* in: file name where created */ - ulint cline, /* in: file line where created */ - const char* cmutex_name) /* in: mutex name */ + ulint cline) /* in: file line where created */ { /* If this is the very first time a synchronization object is created, then the following call initializes the sync system. */ @@ -103,10 +106,10 @@ rw_lock_create_func( lock->mutex.cfile_name = cfile_name; lock->mutex.cline = cline; -#ifndef UNIV_HOTBACKUP +#if defined UNIV_DEBUG && !defined UNIV_HOTBACKUP lock->mutex.cmutex_name = cmutex_name; lock->mutex.mutex_type = 1; -#endif /* !UNIV_HOTBACKUP */ +#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */ rw_lock_set_waiters(lock, 0); rw_lock_set_writer(lock, RW_LOCK_NOT_LOCKED); diff --git a/sync/sync0sync.c b/sync/sync0sync.c index eef1ee45b40..c0198469491 100644 --- a/sync/sync0sync.c +++ b/sync/sync0sync.c @@ -201,10 +201,14 @@ void mutex_create_func( /*==============*/ mutex_t* mutex, /* in: pointer to memory */ +#ifdef UNIV_DEBUG + const char* cmutex_name, /* in: mutex name */ +# ifdef UNIV_SYNC_DEBUG ulint level, /* in: level */ +# endif /* UNIV_SYNC_DEBUG */ +#endif /* UNIV_DEBUG */ const char* cfile_name, /* in: file name where created */ - ulint cline, /* in: file line where created */ - const char* cmutex_name) /* in: mutex name */ + ulint cline) /* in: file line where created */ { #if defined(_WIN32) && defined(UNIV_CAN_USE_X86_ASSEMBLER) mutex_reset_lock_word(mutex); @@ -213,15 +217,19 @@ mutex_create_func( mutex->lock_word = 0; #endif mutex_set_waiters(mutex, 0); +#ifdef UNIV_DEBUG mutex->magic_n = MUTEX_MAGIC_N; +#endif /* UNIV_DEBUG */ #ifdef UNIV_SYNC_DEBUG mutex->line = 0; mutex->file_name = "not yet reserved"; -#endif /* UNIV_SYNC_DEBUG */ mutex->level = level; +#endif /* UNIV_SYNC_DEBUG */ mutex->cfile_name = cfile_name; mutex->cline = cline; #ifndef UNIV_HOTBACKUP + mutex->count_os_wait = 0; +# ifdef UNIV_DEBUG mutex->cmutex_name= cmutex_name; mutex->count_using= 0; mutex->mutex_type= 0; @@ -229,8 +237,8 @@ mutex_create_func( 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; +# endif /* UNIV_DEBUG */ #endif /* !UNIV_HOTBACKUP */ /* Check that lock_word is aligned; this is important on Intel */ @@ -249,9 +257,8 @@ mutex_create_func( mutex_enter(&mutex_list_mutex); - if (UT_LIST_GET_LEN(mutex_list) > 0) { - ut_a(UT_LIST_GET_FIRST(mutex_list)->magic_n == MUTEX_MAGIC_N); - } + ut_ad(UT_LIST_GET_LEN(mutex_list) == 0 + || UT_LIST_GET_FIRST(mutex_list)->magic_n == MUTEX_MAGIC_N); UT_LIST_ADD_FIRST(list, mutex_list, mutex); @@ -280,14 +287,12 @@ mutex_free( mutex_enter(&mutex_list_mutex); - if (UT_LIST_GET_PREV(list, mutex)) { - ut_a(UT_LIST_GET_PREV(list, mutex)->magic_n - == MUTEX_MAGIC_N); - } - if (UT_LIST_GET_NEXT(list, mutex)) { - ut_a(UT_LIST_GET_NEXT(list, mutex)->magic_n - == MUTEX_MAGIC_N); - } + ut_ad(!UT_LIST_GET_PREV(list, mutex) + || UT_LIST_GET_PREV(list, mutex)->magic_n + == MUTEX_MAGIC_N); + ut_ad(!UT_LIST_GET_NEXT(list, mutex) + || UT_LIST_GET_NEXT(list, mutex)->magic_n + == MUTEX_MAGIC_N); UT_LIST_REMOVE(list, mutex_list, mutex); @@ -300,8 +305,9 @@ mutex_free( /* If we free the mutex protecting the mutex list (freeing is not necessary), we have to reset the magic number AFTER removing it from the list. */ - +#ifdef UNIV_DEBUG mutex->magic_n = 0; +#endif /* UNIV_DEBUG */ } /************************************************************************ @@ -333,6 +339,7 @@ mutex_enter_nowait( return(1); } +#ifdef UNIV_DEBUG /********************************************************************** Checks that the mutex has been initialized. */ @@ -346,6 +353,7 @@ mutex_validate( return(TRUE); } +#endif /* UNIV_DEBUG */ /********************************************************************** Sets the waiters field in a mutex. */ @@ -381,13 +389,13 @@ mutex_spin_wait( { ulint index; /* index of the reserved wait cell */ ulint i; /* spin round count */ -#ifndef UNIV_HOTBACKUP +#if defined UNIV_DEBUG && !defined UNIV_HOTBACKUP ib_longlong lstart_time = 0, lfinish_time; /* for timing os_wait */ ulint ltime_diff; ulint sec; ulint ms; uint timer_started = 0; -#endif /* !UNIV_HOTBACKUP */ +#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */ ut_ad(mutex); mutex_loop: @@ -401,10 +409,10 @@ mutex_loop: a memory word. */ spin_loop: -#ifndef UNIV_HOTBACKUP +#if defined UNIV_DEBUG && !defined UNIV_HOTBACKUP mutex_spin_wait_count++; mutex->count_spin_loop++; -#endif /* !UNIV_HOTBACKUP */ +#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */ while (mutex_get_lock_word(mutex) != 0 && i < SYNC_SPIN_ROUNDS) { if (srv_spin_wait_delay) { @@ -415,14 +423,14 @@ spin_loop: } if (i == SYNC_SPIN_ROUNDS) { -#ifndef UNIV_HOTBACKUP +#if defined UNIV_DEBUG && !defined UNIV_HOTBACKUP 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; } -#endif /* !UNIV_HOTBACKUP */ +#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */ os_thread_yield(); } @@ -436,9 +444,9 @@ spin_loop: mutex_spin_round_count += i; -#ifndef UNIV_HOTBACKUP +#if defined UNIV_DEBUG && !defined UNIV_HOTBACKUP mutex->count_spin_rounds += i; -#endif /* !UNIV_HOTBACKUP */ +#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */ if (mutex_test_and_set(mutex) == 0) { /* Succeeded! */ @@ -519,6 +527,7 @@ spin_loop: #ifndef UNIV_HOTBACKUP mutex->count_os_wait++; +# ifdef UNIV_DEBUG /* !!!!! Sometimes os_wait can be called without os_thread_yield */ if (timed_mutexes == 1 && timer_started==0) { @@ -526,13 +535,14 @@ spin_loop: lstart_time= (ib_longlong)sec * 1000000 + ms; timer_started = 1; } +# endif /* UNIV_DEBUG */ #endif /* !UNIV_HOTBACKUP */ sync_array_wait_event(sync_primary_wait_array, index); goto mutex_loop; finish_timing: -#ifndef UNIV_HOTBACKUP +#if defined UNIV_DEBUG && !defined UNIV_HOTBACKUP if (timed_mutexes == 1 && timer_started==1) { ut_usectime(&sec, &ms); lfinish_time= (ib_longlong)sec * 1000000 + ms; @@ -544,7 +554,7 @@ finish_timing: mutex->lmax_spent_time= ltime_diff; } } -#endif /* !UNIV_HOTBACKUP */ +#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */ return; }