diff options
author | Sergei Golubchik <sergii@pisem.net> | 2013-12-22 17:06:50 +0100 |
---|---|---|
committer | Sergei Golubchik <sergii@pisem.net> | 2013-12-22 17:06:50 +0100 |
commit | ffa8c4cfcc41d4f160e3bdfca5cfd4b01a7d6e63 (patch) | |
tree | 728585c36f22a5db3cea796430883d0ebc5c05eb /storage/xtradb/include/sync0sync.ic | |
parent | e27c34f9e4ca15c797fcd3191ee5679c2f237a09 (diff) | |
parent | 52c26f7a1f675185d2ef1a28aca7f9bcc67c6414 (diff) | |
download | mariadb-git-ffa8c4cfcc41d4f160e3bdfca5cfd4b01a7d6e63.tar.gz |
Percona-Server-5.6.14-rel62.0 merge
support ha_innodb.so as a dynamic plugin.
* remove obsolete *,innodb_plugin.rdiff files
* s/--plugin-load=/--plugin-load-add=/
* MYSQL_PLUGIN_IMPORT glob_hostname[]
* use my_error instead of push_warning_printf(ER_DEFAULT)
* don't use tdc_size and tc_size in a module
update test cases (XtraDB is 5.6.14, InnoDB is 5.6.10)
* copy new tests over
* disable some tests for (old) InnoDB
* delete XtraDB tests that no longer apply
small compatibility changes:
* s/HTON_EXTENDED_KEYS/HTON_SUPPORTS_EXTENDED_KEYS/
* revert unnecessary InnoDB changes to make it a bit closer to the upstream
fix XtraDB to compile on Windows (both as a static and a dynamic plugin)
disable XtraDB on Windows (deadlocks) and where no atomic ops are available (e.g. CentOS 5)
storage/innobase/handler/ha_innodb.cc:
revert few unnecessary changes to make it a bit closer to the original InnoDB
storage/innobase/include/univ.i:
correct the version to match what it was merged from
Diffstat (limited to 'storage/xtradb/include/sync0sync.ic')
-rw-r--r-- | storage/xtradb/include/sync0sync.ic | 388 |
1 files changed, 328 insertions, 60 deletions
diff --git a/storage/xtradb/include/sync0sync.ic b/storage/xtradb/include/sync0sync.ic index 73e7379cac1..396005ec83a 100644 --- a/storage/xtradb/include/sync0sync.ic +++ b/storage/xtradb/include/sync0sync.ic @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 1995, 2009, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. Portions of this file contain modifications contributed and copyrighted by @@ -18,8 +18,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., -51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -36,17 +36,20 @@ UNIV_INTERN void mutex_set_waiters( /*==============*/ - mutex_t* mutex, /*!< in: mutex */ + ib_mutex_t* mutex, /*!< in: mutex */ ulint n); /*!< in: value to set */ /******************************************************************//** -Reserves a mutex for the current thread. If the mutex is reserved, the -function spins a preset time (controlled by SYNC_SPIN_ROUNDS) waiting -for the mutex before suspending the thread. */ +Reserves a mutex or a priority mutex for the current thread. If the mutex is +reserved, the function spins a preset time (controlled by SYNC_SPIN_ROUNDS) +waiting for the mutex before suspending the thread. */ UNIV_INTERN void mutex_spin_wait( /*============*/ - mutex_t* mutex, /*!< in: pointer to mutex */ + void* _mutex, /*!< in: pointer to mutex */ + bool high_priority, /*!< in: whether the mutex is a + priority mutex with high priority + specified */ const char* file_name, /*!< in: file name where mutex requested */ ulint line); /*!< in: line where requested */ @@ -57,7 +60,7 @@ UNIV_INTERN void mutex_set_debug_info( /*=================*/ - mutex_t* mutex, /*!< in: mutex */ + ib_mutex_t* mutex, /*!< in: mutex */ const char* file_name, /*!< in: file where requested */ ulint line); /*!< in: line where requested */ #endif /* UNIV_SYNC_DEBUG */ @@ -67,7 +70,7 @@ UNIV_INTERN void mutex_signal_object( /*================*/ - mutex_t* mutex); /*!< in: mutex */ + ib_mutex_t* mutex); /*!< in: mutex */ /******************************************************************//** Performs an atomic test-and-set instruction to the lock_word field of a @@ -75,9 +78,9 @@ mutex. @return the previous value of lock_word: 0 or 1 */ UNIV_INLINE byte -mutex_test_and_set( +ib_mutex_test_and_set( /*===============*/ - mutex_t* mutex) /*!< in: mutex */ + ib_mutex_t* mutex) /*!< in: mutex */ { #if defined(HAVE_ATOMIC_BUILTINS) return(os_atomic_test_and_set_byte(&mutex->lock_word, 1)); @@ -94,7 +97,7 @@ mutex_test_and_set( mutex->lock_word = 1; } - return((byte)ret); + return((byte) ret); #endif } @@ -105,7 +108,7 @@ UNIV_INLINE void mutex_reset_lock_word( /*==================*/ - mutex_t* mutex) /*!< in: mutex */ + ib_mutex_t* mutex) /*!< in: mutex */ { #if defined(HAVE_ATOMIC_BUILTINS) /* In theory __sync_lock_release should be used to release the lock. @@ -125,7 +128,7 @@ UNIV_INLINE lock_word_t mutex_get_lock_word( /*================*/ - const mutex_t* mutex) /*!< in: mutex */ + const ib_mutex_t* mutex) /*!< in: mutex */ { ut_ad(mutex); @@ -139,7 +142,7 @@ UNIV_INLINE ulint mutex_get_waiters( /*==============*/ - const mutex_t* mutex) /*!< in: mutex */ + const ib_mutex_t* mutex) /*!< in: mutex */ { const volatile ulint* ptr; /*!< declared volatile to ensure that the value is read from memory */ @@ -158,7 +161,7 @@ UNIV_INLINE void mutex_exit_func( /*============*/ - mutex_t* mutex) /*!< in: pointer to mutex */ + ib_mutex_t* mutex) /*!< in: pointer to mutex */ { ut_ad(mutex_own(mutex)); @@ -192,6 +195,55 @@ mutex_exit_func( } /******************************************************************//** +NOTE! Use the corresponding macro mutex_exit(), not directly this function! +Unlocks a priority mutex owned by the current thread. */ +UNIV_INLINE +void +mutex_exit_func( +/*============*/ + ib_prio_mutex_t* mutex) /*!< in: pointer to mutex */ +{ + ut_ad(mutex_own(mutex)); + + ut_d(mutex->base_mutex.thread_id = (os_thread_id_t) ULINT_UNDEFINED); + +#ifdef UNIV_SYNC_DEBUG + sync_thread_reset_level(&mutex->base_mutex); +#endif + mutex_reset_lock_word(&mutex->base_mutex); + + /* A problem: we assume that mutex_reset_lock word + is a memory barrier, that is when we read the waiters + field next, the read must be serialized in memory + after the reset. A speculative processor might + perform the read first, which could leave a waiting + thread hanging indefinitely. + + Our current solution call every second + sync_arr_wake_threads_if_sema_free() + to wake up possible hanging threads if + they are missed in mutex_signal_object. */ + + /* Wake up any high priority waiters first. */ + if (mutex->high_priority_waiters != 0) { + + mutex->high_priority_waiters = 0; + os_event_set(mutex->high_priority_event); + sync_array_object_signalled(); + + } else if (mutex_get_waiters(&mutex->base_mutex) != 0) { + + mutex_signal_object(&mutex->base_mutex); + } + +#ifdef UNIV_SYNC_PERF_STAT + mutex_exit_count++; +#endif + +} + + +/******************************************************************//** Locks a mutex for the current thread. If the mutex is reserved, the function spins a preset time (controlled by SYNC_SPIN_ROUNDS), waiting for the mutex before suspending the thread. */ @@ -199,7 +251,7 @@ UNIV_INLINE void mutex_enter_func( /*=============*/ - mutex_t* mutex, /*!< in: pointer to mutex */ + ib_mutex_t* mutex, /*!< in: pointer to mutex */ const char* file_name, /*!< in: file name where locked */ ulint line) /*!< in: line where locked */ { @@ -209,9 +261,7 @@ 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. */ - ut_d(mutex->count_using++); - - if (!mutex_test_and_set(mutex)) { + if (!ib_mutex_test_and_set(mutex)) { ut_d(mutex->thread_id = os_thread_get_curr_id()); #ifdef UNIV_SYNC_DEBUG mutex_set_debug_info(mutex, file_name, line); @@ -219,9 +269,55 @@ mutex_enter_func( return; /* Succeeded! */ } - mutex_spin_wait(mutex, file_name, line); + mutex_spin_wait(mutex, false, file_name, line); } +/******************************************************************//** +NOTE! Use the corresponding macro in the header file, not this function +directly. Locks a priority mutex for the current thread. If the mutex is +reserved the function spins a preset time (controlled by SYNC_SPIN_ROUNDS) +waiting for the mutex before suspending the thread. If the thread is suspended, +the priority argument value determines the relative order for its wake up. Any +HIGH_PRIO waiters will be woken up before any LOW_PRIO waiters. In case of +DEFAULT_PRIO, the relative priority will be set according to +srv_current_thread_priority. */ +UNIV_INLINE +void +mutex_enter_func( +/*=============*/ + ib_prio_mutex_t* mutex, /*!< in: pointer to mutex */ + const char* file_name, /*!< in: file name where + locked */ + ulint line, /*!< in: line where locked */ + enum ib_sync_priority priority) + /*!<in: mutex acquisition + priority */ +{ + bool high_priority; + + ut_ad(mutex_validate(&mutex->base_mutex)); + ut_ad(!mutex_own(mutex)); + + /* 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. */ + + if (!ib_mutex_test_and_set(&mutex->base_mutex)) { + ut_d(mutex->base_mutex.thread_id = os_thread_get_curr_id()); +#ifdef UNIV_SYNC_DEBUG + mutex_set_debug_info(&mutex->base_mutex, file_name, line); +#endif + return; /* Succeeded! */ + } + + if (UNIV_LIKELY(priority == DEFAULT_PRIO)) { + high_priority = srv_current_thread_priority; + } else { + high_priority = (priority == HIGH_PRIO); + } + mutex_spin_wait(mutex, high_priority, file_name, line); +} + + #ifdef UNIV_PFS_MUTEX /******************************************************************//** NOTE! Please use the corresponding macro mutex_enter(), not directly @@ -232,28 +328,62 @@ UNIV_INLINE void pfs_mutex_enter_func( /*=================*/ - mutex_t* mutex, /*!< in: pointer to mutex */ + ib_mutex_t* mutex, /*!< in: pointer to mutex */ const char* file_name, /*!< in: file name where locked */ ulint line) /*!< in: line where locked */ { - struct PSI_mutex_locker* locker = NULL; - PSI_mutex_locker_state state; - int result = 0; - - if (UNIV_LIKELY(PSI_server && mutex->pfs_psi)) { - locker = PSI_server->get_thread_mutex_locker( - &state, mutex->pfs_psi, PSI_MUTEX_LOCK); - if (locker) { - PSI_server->start_mutex_wait(locker, file_name, line); + if (mutex->pfs_psi != NULL) { + PSI_mutex_locker* locker; + PSI_mutex_locker_state state; + + locker = PSI_MUTEX_CALL(start_mutex_wait)( + &state, mutex->pfs_psi, + PSI_MUTEX_LOCK, file_name, line); + + mutex_enter_func(mutex, file_name, line); + + if (locker != NULL) { + PSI_MUTEX_CALL(end_mutex_wait)(locker, 0); } + } else { + mutex_enter_func(mutex, file_name, line); } +} - mutex_enter_func(mutex, file_name, line); +/******************************************************************//** +NOTE! Please use the corresponding macro mutex_enter(), not directly +this function! +This is a performance schema instrumented wrapper function for +mutex_enter_func(). */ +UNIV_INLINE +void +pfs_mutex_enter_func( +/*=================*/ + ib_prio_mutex_t* mutex, /*!< in: pointer to mutex */ + const char* file_name, /*!< in: file name where + locked */ + ulint line, /*!< in: line where locked */ + enum ib_sync_priority priority) /*!<in: mutex acquisition + priority */ +{ + if (mutex->base_mutex.pfs_psi != NULL) { + PSI_mutex_locker* locker; + PSI_mutex_locker_state state; - if (locker) { - PSI_server->end_mutex_wait(locker, result); + locker = PSI_MUTEX_CALL(start_mutex_wait)( + &state, mutex->base_mutex.pfs_psi, + PSI_MUTEX_LOCK, file_name, line); + + mutex_enter_func(mutex, file_name, line, priority); + + if (locker != NULL) { + PSI_MUTEX_CALL(end_mutex_wait)(locker, 0); + } + } else { + mutex_enter_func(mutex, file_name, line, priority); } } + /********************************************************************//** NOTE! Please use the corresponding macro mutex_enter_nowait(), not directly this function! @@ -264,31 +394,53 @@ UNIV_INLINE ulint pfs_mutex_enter_nowait_func( /*========================*/ - mutex_t* mutex, /*!< in: pointer to mutex */ + ib_mutex_t* mutex, /*!< in: pointer to mutex */ const char* file_name, /*!< in: file name where mutex requested */ ulint line) /*!< in: line where requested */ { - ulint ret; - struct PSI_mutex_locker* locker = NULL; - PSI_mutex_locker_state state; - - if (UNIV_LIKELY(PSI_server && mutex->pfs_psi)) { - locker = PSI_server->get_thread_mutex_locker( - &state, mutex->pfs_psi, PSI_MUTEX_TRYLOCK); - if (locker) { - PSI_server->start_mutex_wait(locker, file_name, line); - } - } + ulint ret; + + if (mutex->pfs_psi != NULL) { + PSI_mutex_locker* locker; + PSI_mutex_locker_state state; + + locker = PSI_MUTEX_CALL(start_mutex_wait)( + &state, mutex->pfs_psi, + PSI_MUTEX_TRYLOCK, file_name, line); - ret = mutex_enter_nowait_func(mutex, file_name, line); + ret = mutex_enter_nowait_func(mutex, file_name, line); - if (locker) { - PSI_server->end_mutex_wait(locker, ret); + if (locker != NULL) { + PSI_MUTEX_CALL(end_mutex_wait)(locker, (int) ret); + } + } else { + ret = mutex_enter_nowait_func(mutex, file_name, line); } return(ret); } + +/********************************************************************//** +NOTE! Please use the corresponding macro mutex_enter_nowait(), not directly +this function! +This is a performance schema instrumented wrapper function for +mutex_enter_nowait_func. +@return 0 if succeed, 1 if not */ +UNIV_INLINE +ulint +pfs_mutex_enter_nowait_func( +/*========================*/ + ib_prio_mutex_t* mutex, /*!< in: pointer to mutex */ + const char* file_name, /*!< in: file name where mutex + requested */ + ulint line) /*!< in: line where + requested */ +{ + return pfs_mutex_enter_nowait_func(&mutex->base_mutex, file_name, + line); +} + /******************************************************************//** NOTE! Please use the corresponding macro mutex_exit(), not directly this function! @@ -298,15 +450,34 @@ UNIV_INLINE void pfs_mutex_exit_func( /*================*/ - mutex_t* mutex) /*!< in: pointer to mutex */ + ib_mutex_t* mutex) /*!< in: pointer to mutex */ +{ + if (mutex->pfs_psi != NULL) { + PSI_MUTEX_CALL(unlock_mutex)(mutex->pfs_psi); + } + + mutex_exit_func(mutex); +} + +/******************************************************************//** +NOTE! Please use the corresponding macro mutex_exit(), not directly +this function! +A wrap function of mutex_exit_func() with peformance schema instrumentation. +Unlocks a priority mutex owned by the current thread. */ +UNIV_INLINE +void +pfs_mutex_exit_func( +/*================*/ + ib_prio_mutex_t* mutex) /*!< in: pointer to mutex */ { - if (UNIV_LIKELY(PSI_server && mutex->pfs_psi)) { - PSI_server->unlock_mutex(mutex->pfs_psi); + if (mutex->base_mutex.pfs_psi != NULL) { + PSI_MUTEX_CALL(unlock_mutex)(mutex->base_mutex.pfs_psi); } mutex_exit_func(mutex); } + /******************************************************************//** NOTE! Please use the corresponding macro mutex_create(), not directly this function! @@ -318,7 +489,7 @@ void pfs_mutex_create_func( /*==================*/ mysql_pfs_key_t key, /*!< in: Performance Schema key */ - mutex_t* mutex, /*!< in: pointer to memory */ + ib_mutex_t* mutex, /*!< in: pointer to memory */ # ifdef UNIV_DEBUG # ifdef UNIV_SYNC_DEBUG ulint level, /*!< in: level */ @@ -328,9 +499,7 @@ pfs_mutex_create_func( # endif /* UNIV_DEBUG */ const char* cmutex_name) /*!< in: mutex name */ { - mutex->pfs_psi = (PSI_server && PFS_IS_INSTRUMENTED(key)) - ? PSI_server->init_mutex(key, mutex) - : NULL; + mutex->pfs_psi = PSI_MUTEX_CALL(init_mutex)(key, mutex); mutex_create_func(mutex, # ifdef UNIV_DEBUG @@ -342,6 +511,45 @@ pfs_mutex_create_func( # endif /* UNIV_DEBUG */ cmutex_name); } + +/******************************************************************//** +NOTE! Please use the corresponding macro mutex_create(), not directly +this function! +A wrapper function for mutex_create_func(), registers the mutex +with peformance schema if "UNIV_PFS_MUTEX" is defined when +creating the performance mutex */ +UNIV_INLINE +void +pfs_mutex_create_func( +/*==================*/ + PSI_mutex_key key, /*!< in: Performance Schema + key */ + ib_prio_mutex_t* mutex, /*!< in: pointer to memory */ +# ifdef UNIV_DEBUG +# ifdef UNIV_SYNC_DEBUG + ulint level, /*!< in: level */ +# endif /* UNIV_SYNC_DEBUG */ + const char* cfile_name, /*!< in: file name where + created */ + ulint cline, /*!< in: file line where + created */ +# endif /* UNIV_DEBUG */ + const char* cmutex_name) +{ + mutex->base_mutex.pfs_psi = PSI_MUTEX_CALL(init_mutex)(key, mutex); + + mutex_create_func(mutex, +# ifdef UNIV_DEBUG +# ifdef UNIV_SYNC_DEBUG + level, +# endif /* UNIV_SYNC_DEBUG */ + cfile_name, + cline, +# endif /* UNIV_DEBUG */ + cmutex_name); +} + + /******************************************************************//** NOTE! Please use the corresponding macro mutex_free(), not directly this function! @@ -351,14 +559,74 @@ UNIV_INLINE void pfs_mutex_free_func( /*================*/ - mutex_t* mutex) /*!< in: mutex */ + ib_mutex_t* mutex) /*!< in: mutex */ { - if (UNIV_LIKELY(PSI_server && mutex->pfs_psi)) { - PSI_server->destroy_mutex(mutex->pfs_psi); + if (mutex->pfs_psi != NULL) { + PSI_MUTEX_CALL(destroy_mutex)(mutex->pfs_psi); mutex->pfs_psi = NULL; } mutex_free_func(mutex); } +/******************************************************************//** +NOTE! Please use the corresponding macro mutex_free(), not directly +this function! +Wrapper function for mutex_free_func(). Also destroys the performance +schema probes when freeing the priority mutex */ +UNIV_INLINE +void +pfs_mutex_free_func( +/*================*/ + ib_prio_mutex_t* mutex) /*!< in: mutex */ +{ + if (mutex->base_mutex.pfs_psi != NULL) { + PSI_MUTEX_CALL(destroy_mutex)(mutex->base_mutex.pfs_psi); + mutex->base_mutex.pfs_psi = NULL; + } + + mutex_free_func(mutex); +} + + #endif /* UNIV_PFS_MUTEX */ + +#ifndef HAVE_ATOMIC_BUILTINS +/**********************************************************//** +Function that uses a mutex to decrement a variable atomically */ +UNIV_INLINE +void +os_atomic_dec_ulint_func( +/*=====================*/ + ib_mutex_t* mutex, /*!< in: mutex guarding the dec */ + volatile ulint* var, /*!< in/out: variable to decrement */ + ulint delta) /*!< in: delta to decrement */ +{ + mutex_enter(mutex); + + /* I don't think we will encounter a situation where + this check will not be required. */ + ut_ad(*var >= delta); + + *var -= delta; + + mutex_exit(mutex); +} + +/**********************************************************//** +Function that uses a mutex to increment a variable atomically */ +UNIV_INLINE +void +os_atomic_inc_ulint_func( +/*=====================*/ + ib_mutex_t* mutex, /*!< in: mutex guarding the increment */ + volatile ulint* var, /*!< in/out: variable to increment */ + ulint delta) /*!< in: delta to increment */ +{ + mutex_enter(mutex); + + *var += delta; + + mutex_exit(mutex); +} +#endif /* !HAVE_ATOMIC_BUILTINS */ |