summaryrefslogtreecommitdiff
path: root/storage/innobase/include/sync0rw.ic
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/include/sync0rw.ic')
-rw-r--r--storage/innobase/include/sync0rw.ic559
1 files changed, 0 insertions, 559 deletions
diff --git a/storage/innobase/include/sync0rw.ic b/storage/innobase/include/sync0rw.ic
deleted file mode 100644
index e3f1d881cb4..00000000000
--- a/storage/innobase/include/sync0rw.ic
+++ /dev/null
@@ -1,559 +0,0 @@
-/******************************************************
-The read-write lock (for threads)
-
-(c) 1995 Innobase Oy
-
-Created 9/11/1995 Heikki Tuuri
-*******************************************************/
-
-/**********************************************************************
-Lock an rw-lock in shared mode for the current thread. If the rw-lock is
-locked in exclusive mode, or there is an exclusive lock request waiting,
-the function spins a preset time (controlled by SYNC_SPIN_ROUNDS),
-waiting for the lock before suspending the thread. */
-
-void
-rw_lock_s_lock_spin(
-/*================*/
- rw_lock_t* lock, /* in: pointer to rw-lock */
- ulint pass, /* in: pass value; != 0, if the lock will
- be passed to another thread to unlock */
- const char* file_name,/* in: file name where lock requested */
- ulint line); /* in: line where requested */
-#ifdef UNIV_SYNC_DEBUG
-/**********************************************************************
-Inserts the debug information for an rw-lock. */
-
-void
-rw_lock_add_debug_info(
-/*===================*/
- rw_lock_t* lock, /* in: rw-lock */
- ulint pass, /* in: pass value */
- ulint lock_type, /* in: lock type */
- const char* file_name, /* in: file where requested */
- ulint line); /* in: line where requested */
-/**********************************************************************
-Removes a debug information struct for an rw-lock. */
-
-void
-rw_lock_remove_debug_info(
-/*======================*/
- rw_lock_t* lock, /* in: rw-lock */
- ulint pass, /* in: pass value */
- ulint lock_type); /* in: lock type */
-#endif /* UNIV_SYNC_DEBUG */
-
-/************************************************************************
-Accessor functions for rw lock. */
-UNIV_INLINE
-ulint
-rw_lock_get_waiters(
-/*================*/
- rw_lock_t* lock)
-{
- return(lock->waiters);
-}
-UNIV_INLINE
-void
-rw_lock_set_waiters(
-/*================*/
- rw_lock_t* lock)
-{
-#ifdef UNIV_SYNC_ATOMIC
- os_compare_and_swap(&(lock->waiters), 0, 1);
-#else /* UNIV_SYNC_ATOMIC */
- lock->waiters = 1;
-#endif /* UNIV_SYNC_ATOMIC */
-}
-UNIV_INLINE
-void
-rw_lock_reset_waiters(
-/*================*/
- rw_lock_t* lock)
-{
-#ifdef UNIV_SYNC_ATOMIC
- os_compare_and_swap(&(lock->waiters), 1, 0);
-#else /* UNIV_SYNC_ATOMIC */
- lock->waiters = 0;
-#endif /* UNIV_SYNC_ATOMIC */
-}
-
-/**********************************************************************
-Returns the write-status of the lock - this function made more sense
-with the old rw_lock implementation.
- */
-UNIV_INLINE
-ulint
-rw_lock_get_writer(
-/*===============*/
- rw_lock_t* lock)
-{
- lint lock_word = lock->lock_word;
- if(lock_word > 0) {
- /* return NOT_LOCKED in s-lock state, like the writer
- member of the old lock implementation. */
- return RW_LOCK_NOT_LOCKED;
- } else if (((-lock_word) % X_LOCK_DECR) == 0) {
- return RW_LOCK_EX;
- } else {
- ut_ad(lock_word > -X_LOCK_DECR);
- return RW_LOCK_WAIT_EX;
- }
-}
-
-UNIV_INLINE
-ulint
-rw_lock_get_reader_count(
-/*=====================*/
- rw_lock_t* lock)
-{
- lint lock_word = lock->lock_word;
- if(lock_word > 0) {
- /* s-locked, no x-waiters */
- return(X_LOCK_DECR - lock_word);
- } else if (lock_word < 0 && lock_word > -X_LOCK_DECR) {
- /* s-locked, with x-waiters */
- return (ulint)(-lock_word);
- }
- return 0;
-}
-
-#ifndef UNIV_SYNC_ATOMIC
-UNIV_INLINE
-mutex_t*
-rw_lock_get_mutex(
-/*==============*/
- rw_lock_t* lock)
-{
- return(&(lock->mutex));
-}
-#endif
-
-/**********************************************************************
-Returns the value of writer_count for the lock. Does not reserve the lock
-mutex, so the caller must be sure it is not changed during the call. */
-UNIV_INLINE
-ulint
-rw_lock_get_x_lock_count(
-/*=====================*/
- /* out: value of writer_count */
- rw_lock_t* lock) /* in: rw-lock */
-{
- lint lock_copy = lock->lock_word;
- /* If there is a reader, lock_word is not divisible by X_LOCK_DECR */
- if(lock_copy > 0 || (-lock_copy) % X_LOCK_DECR != 0) {
- return 0;
- }
- return ((-lock_copy) / X_LOCK_DECR) + 1;
-}
-
-/**********************************************************************
-Two different implementations for decrementing the lock_word of a rw_lock:
-one for systems supporting atomic operations, one for others. This does
-does not support recusive x-locks: they should be handled by the caller and
-need not be atomic since they are performed by the current lock holder.
-Returns true if the decrement was made, false if not. */
-UNIV_INLINE
-ibool
-rw_lock_lock_word_decr(
- /* out: TRUE if decr occurs */
- rw_lock_t* lock, /* in: rw-lock */
- ulint amount) /* in: amount of decrement */
-{
-
-#ifdef UNIV_SYNC_ATOMIC
-
- lint local_lock_word = lock->lock_word;
- while (local_lock_word > 0) {
- if(os_compare_and_swap(&(lock->lock_word),
- local_lock_word,
- local_lock_word - amount)) {
- return TRUE;
- }
- local_lock_word = lock->lock_word;
- }
- return(FALSE);
-
-#else /* UNIV_SYNC_ATOMIC */
-
- ibool success = FALSE;
- mutex_enter(&(lock->mutex));
- if(lock->lock_word > 0) {
- lock->lock_word -= amount;
- success = TRUE;
- }
- mutex_exit(&(lock->mutex));
- return success;
-
-#endif /* UNIV_SYNC_ATOMIC */
-
-}
-
-/**********************************************************************
-Two different implementations for incrementing the lock_word of a rw_lock:
-one for systems supporting atomic operations, one for others.
-Returns the value of lock_word after increment. */
-UNIV_INLINE
-lint
-rw_lock_lock_word_incr(
- /* out: lock->lock_word after increment */
- rw_lock_t* lock, /* in: rw-lock */
- ulint amount) /* in: amount of increment */
-{
-
-#ifdef UNIV_SYNC_ATOMIC
-
- return(os_atomic_increment(&(lock->lock_word), amount));
-
-#else /* UNIV_SYNC_ATOMIC */
-
- lint local_lock_word;
-
- mutex_enter(&(lock->mutex));
-
- lock->lock_word += amount;
- local_lock_word = lock->lock_word;
-
- mutex_exit(&(lock->mutex));
-
- return local_lock_word;
-
-#endif /* UNIV_SYNC_ATOMIC */
-
-}
-
-/**********************************************************************
-Low-level function which tries to lock an rw-lock in s-mode. Performs no
-spinning. */
-UNIV_INLINE
-ibool
-rw_lock_s_lock_low(
-/*===============*/
- /* out: TRUE if success */
- rw_lock_t* lock, /* in: pointer to rw-lock */
- ulint pass __attribute__((unused)),
- /* in: pass value; != 0, if the lock will be
- passed to another thread to unlock */
- const char* file_name, /* in: file name where lock requested */
- ulint line) /* in: line where requested */
-{
- /* TODO: study performance of UNIV_LIKELY branch prediction hints. */
- if (!rw_lock_lock_word_decr(lock, 1)) {
- /* Locking did not succeed */
- return(FALSE);
- }
-
-#ifdef UNIV_SYNC_DEBUG
- rw_lock_add_debug_info(lock, pass, RW_LOCK_SHARED, file_name, line);
-#endif
- /* These debugging values are not set safely: they may be incorrect
- or even refer to a line that is invalid for the file name. */
- lock->last_s_file_name = file_name;
- lock->last_s_line = line;
-
- return(TRUE); /* locking succeeded */
-}
-
-/* TODO: The "direct" functions are not used. Remove them? */
-/**********************************************************************
-Low-level function which locks an rw-lock in s-mode when we know that it
-is possible and none else is currently accessing the rw-lock structure.
-Then we can do the locking without reserving the mutex. */
-UNIV_INLINE
-void
-rw_lock_s_lock_direct(
-/*==================*/
- rw_lock_t* lock, /* in: pointer to rw-lock */
- const char* file_name, /* in: file name where requested */
- ulint line) /* in: line where lock requested */
-{
- ut_ad(lock->lock_word == X_LOCK_DECR);
-
- /* Indicate there is a new reader by decrementing lock_word */
- lock->lock_word--;
-
- lock->last_s_file_name = file_name;
- lock->last_s_line = line;
-
-#ifdef UNIV_SYNC_DEBUG
- rw_lock_add_debug_info(lock, 0, RW_LOCK_SHARED, file_name, line);
-#endif
-}
-
-/* TODO: The "direct" functions are not used. Remove them? */
-/**********************************************************************
-Low-level function which locks an rw-lock in x-mode when we know that it
-is not locked and none else is currently accessing the rw-lock structure.
-Then we can do the locking without reserving the mutex. */
-UNIV_INLINE
-void
-rw_lock_x_lock_direct(
-/*==================*/
- rw_lock_t* lock, /* in: pointer to rw-lock */
- const char* file_name, /* in: file name where requested */
- ulint line) /* in: line where lock requested */
-{
- ut_ad(rw_lock_validate(lock));
- ut_ad(lock->lock_word == X_LOCK_DECR);
-
- lock->lock_word -= X_LOCK_DECR;
- lock->writer_thread = os_thread_get_curr_id();
- lock->pass = 0;
-
- lock->last_x_file_name = file_name;
- lock->last_x_line = line;
-
-#ifdef UNIV_SYNC_DEBUG
- rw_lock_add_debug_info(lock, 0, RW_LOCK_EX, file_name, line);
-#endif
-}
-
-/**********************************************************************
-NOTE! Use the corresponding macro, not directly this function! Lock an
-rw-lock in shared mode for the current thread. If the rw-lock is locked
-in exclusive mode, or there is an exclusive lock request waiting, the
-function spins a preset time (controlled by SYNC_SPIN_ROUNDS), waiting for
-the lock, before suspending the thread. */
-UNIV_INLINE
-void
-rw_lock_s_lock_func(
-/*================*/
- rw_lock_t* lock, /* in: pointer to rw-lock */
- ulint pass, /* in: pass value; != 0, if the lock will
- be passed to another thread to unlock */
- const char* file_name,/* in: file name where lock requested */
- ulint line) /* in: line where requested */
-{
- /* NOTE: As we do not know the thread ids for threads which have
- s-locked a latch, and s-lockers will be served only after waiting
- x-lock requests have been fulfilled, then if this thread already
- owns an s-lock here, it may end up in a deadlock with another thread
- which requests an x-lock here. Therefore, we will forbid recursive
- s-locking of a latch: the following assert will warn the programmer
- of the possibility of this kind of a deadlock. If we want to implement
- safe recursive s-locking, we should keep in a list the thread ids of
- the threads which have s-locked a latch. This would use some CPU
- time. */
-
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(!rw_lock_own(lock, RW_LOCK_SHARED)); /* see NOTE above */
-#endif /* UNIV_SYNC_DEBUG */
-
- /* TODO: study performance of UNIV_LIKELY branch prediction hints. */
- if (rw_lock_s_lock_low(lock, pass, file_name, line)) {
-
- return; /* Success */
- } else {
- /* Did not succeed, try spin wait */
-
- rw_lock_s_lock_spin(lock, pass, file_name, line);
-
- return;
- }
-}
-
-/**********************************************************************
-NOTE! Use the corresponding macro, not directly this function! Lock an
-rw-lock in exclusive mode for the current thread if the lock can be
-obtained immediately. */
-UNIV_INLINE
-ibool
-rw_lock_x_lock_func_nowait(
-/*=======================*/
- /* out: TRUE if success */
- rw_lock_t* lock, /* in: pointer to rw-lock */
- const char* file_name,/* in: file name where lock requested */
- ulint line) /* in: line where requested */
-{
- os_thread_id_t curr_thread = os_thread_get_curr_id();
-
- ibool success;
-
-#ifdef UNIV_SYNC_ATOMIC
- success = os_compare_and_swap(&(lock->lock_word), X_LOCK_DECR, 0);
-#else
-
- success = FALSE;
- mutex_enter(&(lock->mutex));
- if(lock->lock_word == X_LOCK_DECR) {
- lock->lock_word = 0;
- success = TRUE;
- }
- mutex_exit(&(lock->mutex));
-
-#endif
- if(success) {
- lock->writer_thread = curr_thread;
- lock->pass = 0;
-
- } else if (!(lock->pass) &&
- os_thread_eq(lock->writer_thread, curr_thread)) {
- /* Must verify pass first: otherwise another thread can
- call move_ownership suddenly allowing recursive locks.
- and after we have verified our thread_id matches
- (though move_ownership has since changed it).*/
-
- /* Relock: this lock_word modification is safe since no other
- threads can modify (lock, unlock, or reserve) lock_word while
- there is an exclusive writer and this is the writer thread. */
- lock->lock_word -= X_LOCK_DECR;
-
- ut_ad(((-lock->lock_word) % X_LOCK_DECR) == 0);
-
- } else {
- /* Failure */
- return(FALSE);
- }
-#ifdef UNIV_SYNC_DEBUG
- rw_lock_add_debug_info(lock, 0, RW_LOCK_EX, file_name, line);
-#endif
-
- lock->last_x_file_name = file_name;
- lock->last_x_line = line;
-
- ut_ad(rw_lock_validate(lock));
-
- return(TRUE);
-}
-
-/**********************************************************************
-Releases a shared mode lock. */
-UNIV_INLINE
-void
-rw_lock_s_unlock_func(
-/*==================*/
- rw_lock_t* lock /* in: rw-lock */
-#ifdef UNIV_SYNC_DEBUG
- ,ulint pass /* in: pass value; != 0, if the lock may have
- been passed to another thread to unlock */
-#endif
- )
-{
- ut_ad((lock->lock_word % X_LOCK_DECR) != 0);
-
-#ifdef UNIV_SYNC_DEBUG
- rw_lock_remove_debug_info(lock, pass, RW_LOCK_SHARED);
-#endif
-
- /* Increment lock_word to indicate 1 less reader */
- if(rw_lock_lock_word_incr(lock, 1) == 0) {
-
- /* wait_ex waiter exists. It may not be asleep, but we signal
- anyway. We do not wake other waiters, because they can't
- exist without wait_ex waiter and wait_ex waiter goes first.*/
- os_event_set(lock->wait_ex_event);
- sync_array_object_signalled(sync_primary_wait_array);
-
- }
-
- ut_ad(rw_lock_validate(lock));
-
-#ifdef UNIV_SYNC_PERF_STAT
- rw_s_exit_count++;
-#endif
-}
-
-/* TODO: The "direct" functions are not used. Remove them? */
-/**********************************************************************
-Releases a shared mode lock when we know there are no waiters and none
-else will access the lock during the time this function is executed. */
-UNIV_INLINE
-void
-rw_lock_s_unlock_direct(
-/*====================*/
- rw_lock_t* lock) /* in: rw-lock */
-{
- ut_ad(lock->lock_word < X_LOCK_DECR);
-
-#ifdef UNIV_SYNC_DEBUG
- rw_lock_remove_debug_info(lock, 0, RW_LOCK_SHARED);
-#endif
-
- /* Decrease reader count by incrementing lock_word */
- lock->lock_word++;
-
- ut_ad(!rw_lock_get_waiters(lock));
- ut_ad(rw_lock_validate(lock));
-#ifdef UNIV_SYNC_PERF_STAT
- rw_s_exit_count++;
-#endif
-}
-
-/**********************************************************************
-Releases an exclusive mode lock. */
-UNIV_INLINE
-void
-rw_lock_x_unlock_func(
-/*==================*/
- rw_lock_t* lock /* in: rw-lock */
-#ifdef UNIV_SYNC_DEBUG
- ,ulint pass /* in: pass value; != 0, if the lock may have
- been passed to another thread to unlock */
-#endif
- )
-{
- uint local_pass;
- ut_ad((lock->lock_word % X_LOCK_DECR) == 0);
-
- /*
- Must reset pass while we still have the lock.
- If we are not the last unlocker, we correct it later in the function,
- which is harmless since we still hold the lock.
- */
- local_pass = lock->pass;
- lock->pass = 1;
-
-#ifdef UNIV_SYNC_DEBUG
- rw_lock_remove_debug_info(lock, pass, RW_LOCK_EX);
-#endif
-
- if(rw_lock_lock_word_incr(lock, X_LOCK_DECR) == X_LOCK_DECR) {
- /* Lock is now free. May have to signal read/write waiters.
- We do not need to signal wait_ex waiters, since they cannot
- exist when there is a writer. */
- if(rw_lock_get_waiters(lock)) {
- rw_lock_reset_waiters(lock);
- os_event_set(lock->event);
- sync_array_object_signalled(sync_primary_wait_array);
- }
-
- } else {
- /* We still hold x-lock, so we correct pass. */
- lock->pass = local_pass;
- }
-
- ut_ad(rw_lock_validate(lock));
-
-#ifdef UNIV_SYNC_PERF_STAT
- rw_x_exit_count++;
-#endif
-}
-
-/* TODO: The "direct" functions are not used. Remove them? */
-/**********************************************************************
-Releases an exclusive mode lock when we know there are no waiters, and
-none else will access the lock durint the time this function is executed. */
-UNIV_INLINE
-void
-rw_lock_x_unlock_direct(
-/*====================*/
- rw_lock_t* lock) /* in: rw-lock */
-{
- /* Reset the exclusive lock if this thread no longer has an x-mode
- lock */
-
- ut_ad((lock->lock_word % X_LOCK_DECR) == 0);
-
-#ifdef UNIV_SYNC_DEBUG
- rw_lock_remove_debug_info(lock, 0, RW_LOCK_EX);
-#endif
- lock->pass = 1;
- lock->lock_word += X_LOCK_DECR;
-
- ut_ad(!rw_lock_get_waiters(lock));
- ut_ad(rw_lock_validate(lock));
-
-#ifdef UNIV_SYNC_PERF_STAT
- rw_x_exit_count++;
-#endif
-}