summaryrefslogtreecommitdiff
path: root/storage/xtradb/include/sync0sync.ic
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2013-12-22 17:06:50 +0100
committerSergei Golubchik <sergii@pisem.net>2013-12-22 17:06:50 +0100
commitffa8c4cfcc41d4f160e3bdfca5cfd4b01a7d6e63 (patch)
tree728585c36f22a5db3cea796430883d0ebc5c05eb /storage/xtradb/include/sync0sync.ic
parente27c34f9e4ca15c797fcd3191ee5679c2f237a09 (diff)
parent52c26f7a1f675185d2ef1a28aca7f9bcc67c6414 (diff)
downloadmariadb-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.ic388
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 */