diff options
Diffstat (limited to 'storage/innobase/include/sync0rw.ic')
-rw-r--r-- | storage/innobase/include/sync0rw.ic | 559 |
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 -} |