/***************************************************************************** Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT 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 Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ /**************************************************//** @file include/os0sync.ic The interface to the operating system synchronization primitives. Created 9/6/1995 Heikki Tuuri *******************************************************/ #ifdef __WIN__ #include #endif /**********************************************************//** Acquires ownership of a fast mutex. @return 0 if success, != 0 if was reserved by another thread */ UNIV_INLINE ulint os_fast_mutex_trylock( /*==================*/ os_fast_mutex_t* fast_mutex) /*!< in: mutex to acquire */ { fast_mutex_t* mutex = &fast_mutex->mutex; #ifdef __WIN__ return(!TryEnterCriticalSection(mutex)); #else /* NOTE that the MySQL my_pthread.h redefines pthread_mutex_trylock so that it returns 0 on success. In the operating system libraries, HP-UX-10.20 follows the old Posix 1003.4a Draft 4 and returns 1 on success (but MySQL remaps that to 0), while Linux, FreeBSD, Solaris, AIX, Tru64 Unix, HP-UX-11.0 return 0 on success. */ return((ulint) pthread_mutex_trylock(mutex)); #endif } #ifdef UNIV_PFS_MUTEX /*********************************************************//** NOTE! Please use the corresponding macro os_fast_mutex_init(), not directly this function! A wrapper function for os_fast_mutex_init_func(). Initializes an operating system fast mutex semaphore. */ UNIV_INLINE void pfs_os_fast_mutex_init( /*===================*/ PSI_mutex_key key, /*!< in: Performance Schema key */ os_fast_mutex_t* fast_mutex) /*!< out: fast mutex */ { #ifdef HAVE_PSI_MUTEX_INTERFACE fast_mutex->pfs_psi = PSI_MUTEX_CALL(init_mutex)(key, &fast_mutex->mutex); #else fast_mutex->pfs_psi = NULL; #endif os_fast_mutex_init_func(&fast_mutex->mutex); } /******************************************************************//** NOTE! Please use the corresponding macro os_fast_mutex_free(), not directly this function! Wrapper function for pfs_os_fast_mutex_free(). Also destroys the performance schema probes when freeing the mutex */ UNIV_INLINE void pfs_os_fast_mutex_free( /*===================*/ os_fast_mutex_t* fast_mutex) /*!< in/out: mutex */ { #ifdef HAVE_PSI_MUTEX_INTERFACE if (fast_mutex->pfs_psi != NULL) PSI_MUTEX_CALL(destroy_mutex)(fast_mutex->pfs_psi); #endif fast_mutex->pfs_psi = NULL; os_fast_mutex_free_func(&fast_mutex->mutex); } /**********************************************************//** NOTE! Please use the corresponding macro os_fast_mutex_lock, not directly this function! Wrapper function of os_fast_mutex_lock_func. Acquires ownership of a fast mutex. */ UNIV_INLINE void pfs_os_fast_mutex_lock( /*===================*/ os_fast_mutex_t* fast_mutex, /*!< in/out: mutex to acquire */ const char* file_name, /*!< in: file name where locked */ ulint line) /*!< in: line where locked */ { #ifdef HAVE_PSI_MUTEX_INTERFACE if (fast_mutex->pfs_psi != NULL) { PSI_mutex_locker* locker; PSI_mutex_locker_state state; locker = PSI_MUTEX_CALL(start_mutex_wait)( &state, fast_mutex->pfs_psi, PSI_MUTEX_LOCK, file_name, static_cast(line)); os_fast_mutex_lock_func(&fast_mutex->mutex); if (locker != NULL) PSI_MUTEX_CALL(end_mutex_wait)(locker, 0); } else #endif { os_fast_mutex_lock_func(&fast_mutex->mutex); } return; } /**********************************************************//** NOTE! Please use the corresponding macro os_fast_mutex_unlock, not directly this function! Wrapper function of os_fast_mutex_unlock_func. Releases ownership of a fast mutex. */ UNIV_INLINE void pfs_os_fast_mutex_unlock( /*=====================*/ os_fast_mutex_t* fast_mutex) /*!< in/out: mutex to release */ { #ifdef HAVE_PSI_MUTEX_INTERFACE if (fast_mutex->pfs_psi != NULL) PSI_MUTEX_CALL(unlock_mutex)(fast_mutex->pfs_psi); #endif os_fast_mutex_unlock_func(&fast_mutex->mutex); } #endif /* UNIV_PFS_MUTEX */ #ifdef HAVE_WINDOWS_ATOMICS /* Use inline functions to make 64 and 32 bit versions of windows atomic functions so that typecasts are evaluated at compile time. Take advantage that lint is either __int64 or long int and windows atomic functions work on __int64 and LONG */ /**********************************************************//** Atomic compare and exchange of unsigned integers. @return value found before the exchange. If it is not equal to old_value the exchange did not happen. */ UNIV_INLINE lint win_cmp_and_xchg_lint( /*==================*/ volatile lint* ptr, /*!< in/out: source/destination */ lint new_val, /*!< in: exchange value */ lint old_val) /*!< in: value to compare to */ { # ifdef _WIN64 return(InterlockedCompareExchange64(ptr, new_val, old_val)); # else return(InterlockedCompareExchange(ptr, new_val, old_val)); # endif } /**********************************************************//** Atomic addition of signed integers. @return Initial value of the variable pointed to by ptr */ UNIV_INLINE lint win_xchg_and_add( /*=============*/ volatile lint* ptr, /*!< in/out: address of destination */ lint val) /*!< in: number to be added */ { #ifdef _WIN64 return(InterlockedExchangeAdd64(ptr, val)); #else return(InterlockedExchangeAdd(ptr, val)); #endif } /**********************************************************//** Atomic compare and exchange of unsigned integers. @return value found before the exchange. If it is not equal to old_value the exchange did not happen. */ UNIV_INLINE ulint win_cmp_and_xchg_ulint( /*===================*/ volatile ulint* ptr, /*!< in/out: source/destination */ ulint new_val, /*!< in: exchange value */ ulint old_val) /*!< in: value to compare to */ { return((ulint) win_cmp_and_xchg_lint( (volatile lint*) ptr, (lint) new_val, (lint) old_val)); } /**********************************************************//** Atomic compare and exchange of 32-bit unsigned integers. @return value found before the exchange. If it is not equal to old_value the exchange did not happen. */ UNIV_INLINE DWORD win_cmp_and_xchg_dword( /*===================*/ volatile DWORD* ptr, /*!< in/out: source/destination */ DWORD new_val, /*!< in: exchange value */ DWORD old_val) /*!< in: value to compare to */ { ut_ad(sizeof(DWORD) == sizeof(LONG)); /* We assume this. */ return(InterlockedCompareExchange( (volatile LONG*) ptr, (LONG) new_val, (LONG) old_val)); } #endif /* HAVE_WINDOWS_ATOMICS */ /**********************************************************//** Acquires ownership of a fast mutex. Implies a full memory barrier even on platforms such as PowerPC where this is not normally required. @return 0 if success, != 0 if was reserved by another thread */ UNIV_INLINE ulint os_fast_mutex_trylock_full_barrier( /*==================*/ os_fast_mutex_t* fast_mutex) /*!< in: mutex to acquire */ { #ifdef __WIN__ if (TryEnterCriticalSection(&fast_mutex->mutex)) { return(0); } else { return(1); } #else /* NOTE that the MySQL my_pthread.h redefines pthread_mutex_trylock so that it returns 0 on success. In the operating system libraries, HP-UX-10.20 follows the old Posix 1003.4a Draft 4 and returns 1 on success (but MySQL remaps that to 0), while Linux, FreeBSD, Solaris, AIX, Tru64 Unix, HP-UX-11.0 return 0 on success. */ #ifdef __powerpc__ os_mb; #endif return((ulint) pthread_mutex_trylock(&fast_mutex->mutex)); #endif }