diff options
Diffstat (limited to 'innobase/include/sync0sync.ic')
-rw-r--r-- | innobase/include/sync0sync.ic | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/innobase/include/sync0sync.ic b/innobase/include/sync0sync.ic new file mode 100644 index 00000000000..a937ac5d579 --- /dev/null +++ b/innobase/include/sync0sync.ic @@ -0,0 +1,226 @@ +/****************************************************** +Mutex, the basic synchronization primitive + +(c) 1995 Innobase Oy + +Created 9/5/1995 Heikki Tuuri +*******************************************************/ + +/********************************************************************** +Sets the waiters field in a mutex. */ + +void +mutex_set_waiters( +/*==============*/ + 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. */ + +void +mutex_spin_wait( +/*============*/ + mutex_t* mutex /* in: pointer to mutex */ + + #ifdef UNIV_SYNC_DEBUG + ,char* file_name, /* in: file name where mutex requested */ + ulint line /* in: line where requested */ + #endif +); +/********************************************************************** +Sets the debug information for a reserved mutex. */ + +void +mutex_set_debug_info( +/*=================*/ + mutex_t* mutex, /* in: mutex */ + char* file_name, /* in: file where requested */ + ulint line); /* in: line where requested */ +/********************************************************************** +Releases the threads waiting in the primary wait array for this mutex. */ + +void +mutex_signal_object( +/*================*/ + mutex_t* mutex); /* in: mutex */ + +/********************************************************************** +Performs an atomic test-and-set instruction to the lock_word field of a +mutex. */ +UNIV_INLINE +ulint +mutex_test_and_set( +/*===============*/ + /* out: the previous value of lock_word: 0 or + 1 */ + mutex_t* mutex) /* in: mutex */ +{ +#ifdef _WIN32 + ulint res; + ulint* lw; /* assembler code is used to ensure that + lock_word is loaded from memory */ + ut_ad(mutex); + ut_ad(sizeof(ulint) == 4); + + lw = &(mutex->lock_word); + + __asm MOV ECX, lw + __asm MOV EDX, 1 + __asm XCHG EDX, DWORD PTR [ECX] + __asm MOV res, EDX + + /* The fence below would prevent this thread from reading the data + structure protected by the mutex before the test-and-set operation is + committed, but the fence is apparently not needed: + + In a posting to comp.arch newsgroup (August 10, 1997) Andy Glew said + that in P6 a LOCKed instruction like XCHG establishes a fence with + respect to memory reads and writes and thus an explicit fence is not + needed. In P5 he seemed to agree with a previous newsgroup poster that + LOCKed instructions serialize all instruction execution, and, + consequently, also memory operations. This is confirmed in Intel + Software Dev. Manual, Vol. 3. */ + + /* mutex_fence(); */ + + return(res); +#else + ibool ret; + + ret = os_fast_mutex_trylock(&(mutex->os_fast_mutex)); + + if (ret == 0) { + mutex->lock_word = 1; + } + + return(ret); +#endif +} + +/********************************************************************** +Performs a reset instruction to the lock_word field of a mutex. This +instruction also serializes memory operations to the program order. */ +UNIV_INLINE +void +mutex_reset_lock_word( +/*==================*/ + mutex_t* mutex) /* in: mutex */ +{ +#ifdef _WIN32 + ulint* lw; /* assembler code is used to ensure that + lock_word is loaded from memory */ + ut_ad(mutex); + + lw = &(mutex->lock_word); + + __asm MOV EDX, 0 + __asm MOV ECX, lw + __asm XCHG EDX, DWORD PTR [ECX] +#else + mutex->lock_word = 0; + + os_fast_mutex_unlock(&(mutex->os_fast_mutex)); +#endif +} + +/********************************************************************** +Gets the value of the lock word. */ +UNIV_INLINE +ulint +mutex_get_lock_word( +/*================*/ + mutex_t* mutex) /* in: mutex */ +{ +volatile ulint* ptr; /* declared volatile to ensure that + lock_word is loaded from memory */ + ut_ad(mutex); + + ptr = &(mutex->lock_word); + + return(*ptr); +} + +/********************************************************************** +Gets the waiters field in a mutex. */ +UNIV_INLINE +ulint +mutex_get_waiters( +/*==============*/ + /* out: value to set */ + mutex_t* mutex) /* in: mutex */ +{ +volatile ulint* ptr; /* declared volatile to ensure that + the value is read from memory */ + ut_ad(mutex); + + ptr = &(mutex->waiters); + + return(*ptr); /* Here we assume that the read of a single + word from memory is atomic */ +} + +/********************************************************************** +Unlocks a mutex owned by the current thread. */ +UNIV_INLINE +void +mutex_exit( +/*=======*/ + mutex_t* mutex) /* in: pointer to mutex */ +{ + ut_ad(mutex_own(mutex)); + +#ifdef UNIV_SYNC_DEBUG + mutex->thread_id = ULINT_UNDEFINED; + + sync_thread_reset_level(mutex); +#endif + mutex_reset_lock_word(mutex); + + if (mutex_get_waiters(mutex) != 0) { + + mutex_signal_object(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. */ +UNIV_INLINE +void +mutex_enter_func( +/*=============*/ + mutex_t* mutex /* in: pointer to mutex */ + #ifdef UNIV_SYNC_DEBUG + ,char* file_name, /* in: file name where locked */ + ulint line /* in: line where locked */ + #endif + ) +{ + ut_ad(mutex_validate(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 (!mutex_test_and_set(mutex)) { + + #ifdef UNIV_SYNC_DEBUG + mutex_set_debug_info(mutex, file_name, line); + #endif + + return; /* Succeeded! */ + } + + mutex_spin_wait(mutex + #ifdef UNIV_SYNC_DEBUG + ,file_name, + line + #endif + ); +} |