diff options
author | Vladislav Vaintroub <wlad@montyprogram.com> | 2011-06-12 16:09:28 +0200 |
---|---|---|
committer | Vladislav Vaintroub <wlad@montyprogram.com> | 2011-06-12 16:09:28 +0200 |
commit | fe054adfcaecbd891da802517826a951bb4ca377 (patch) | |
tree | e70229f726e1111ee3e03d914c8847bf249ac0e2 /mysys/thr_rwlock.c | |
parent | 824ce5f3eae52ee418665211c24218a5772c43f2 (diff) | |
download | mariadb-git-fe054adfcaecbd891da802517826a951bb4ca377.tar.gz |
Backport fix for MySQL bug #56405 :
use native windows condition variables and rwlocks in mysys, if Windows supports it.
Diffstat (limited to 'mysys/thr_rwlock.c')
-rw-r--r-- | mysys/thr_rwlock.c | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/mysys/thr_rwlock.c b/mysys/thr_rwlock.c index ea98a854a4d..2978d91090d 100644 --- a/mysys/thr_rwlock.c +++ b/mysys/thr_rwlock.c @@ -19,6 +19,119 @@ #if defined(THREAD) && !defined(HAVE_PTHREAD_RWLOCK_RDLOCK) && !defined(HAVE_RWLOCK_INIT) #include <errno.h> +#ifdef _WIN32 + +static BOOL have_srwlock= FALSE; +/* Prototypes and function pointers for windows functions */ +typedef VOID (WINAPI* srw_func) (PSRWLOCK SRWLock); +typedef BOOL (WINAPI* srw_bool_func) (PSRWLOCK SRWLock); + +static srw_func my_InitializeSRWLock; +static srw_func my_AcquireSRWLockExclusive; +static srw_func my_ReleaseSRWLockExclusive; +static srw_func my_AcquireSRWLockShared; +static srw_func my_ReleaseSRWLockShared; + +static srw_bool_func my_TryAcquireSRWLockExclusive; +static srw_bool_func my_TryAcquireSRWLockShared; + +/** + Check for presence of Windows slim reader writer lock function. + Load function pointers. +*/ + +static void check_srwlock_availability(void) +{ + HMODULE module= GetModuleHandle("kernel32"); + + my_InitializeSRWLock= (srw_func) GetProcAddress(module, + "InitializeSRWLock"); + my_AcquireSRWLockExclusive= (srw_func) GetProcAddress(module, + "AcquireSRWLockExclusive"); + my_AcquireSRWLockShared= (srw_func) GetProcAddress(module, + "AcquireSRWLockShared"); + my_ReleaseSRWLockExclusive= (srw_func) GetProcAddress(module, + "ReleaseSRWLockExclusive"); + my_ReleaseSRWLockShared= (srw_func) GetProcAddress(module, + "ReleaseSRWLockShared"); + my_TryAcquireSRWLockExclusive= (srw_bool_func) GetProcAddress(module, + "TryAcquireSRWLockExclusive"); + my_TryAcquireSRWLockShared= (srw_bool_func) GetProcAddress(module, + "TryAcquireSRWLockShared"); + + /* + We currently require TryAcquireSRWLockExclusive. This API is missing on + Vista, this means SRWLock are only used starting with Win7. + + If "trylock" usage for rwlocks is eliminated from server codebase (it is used + in a single place currently, in query cache), then SRWLock can be enabled on + Vista too. In this case condition below needs to be changed to e.g check + for my_InitializeSRWLock. + */ + + if (my_TryAcquireSRWLockExclusive) + have_srwlock= TRUE; + +} + + +static int srw_init(my_rw_lock_t *rwp) +{ + my_InitializeSRWLock(&rwp->srwlock); + rwp->have_exclusive_srwlock = FALSE; + return 0; +} + + +static int srw_rdlock(my_rw_lock_t *rwp) +{ + my_AcquireSRWLockShared(&rwp->srwlock); + return 0; +} + + +static int srw_tryrdlock(my_rw_lock_t *rwp) +{ + + if (!my_TryAcquireSRWLockShared(&rwp->srwlock)) + return EBUSY; + return 0; +} + + +static int srw_wrlock(my_rw_lock_t *rwp) +{ + my_AcquireSRWLockExclusive(&rwp->srwlock); + rwp->have_exclusive_srwlock= TRUE; + return 0; +} + + +static int srw_trywrlock(my_rw_lock_t *rwp) +{ + if (!my_TryAcquireSRWLockExclusive(&rwp->srwlock)) + return EBUSY; + rwp->have_exclusive_srwlock= TRUE; + return 0; +} + + +static int srw_unlock(my_rw_lock_t *rwp) +{ + if (rwp->have_exclusive_srwlock) + { + rwp->have_exclusive_srwlock= FALSE; + my_ReleaseSRWLockExclusive(&rwp->srwlock); + } + else + { + my_ReleaseSRWLockShared(&rwp->srwlock); + } + return 0; +} + +#endif /*_WIN32 */ + /* Source base from Sun Microsystems SPILT, simplified for MySQL use -- Joshua Chamas @@ -62,6 +175,22 @@ int my_rwlock_init(rw_lock_t *rwp, void *arg __attribute__((unused))) { pthread_condattr_t cond_attr; +#ifdef _WIN32 + /* + Once initialization is used here rather than in my_init(), in order to + - avoid my_init() pitfalls- (undefined order in which initialization should + run) + - be potentially useful C++ (static constructors) + - just to simplify the API. + Also, the overhead is of my_pthread_once is very small. + */ + static my_pthread_once_t once_control= MY_PTHREAD_ONCE_INIT; + my_pthread_once(&once_control, check_srwlock_availability); + + if (have_srwlock) + return srw_init(rwp); +#endif + pthread_mutex_init( &rwp->lock, MY_MUTEX_INIT_FAST); pthread_condattr_init( &cond_attr ); pthread_cond_init( &rwp->readers, &cond_attr ); @@ -77,6 +206,10 @@ int my_rwlock_init(rw_lock_t *rwp, void *arg __attribute__((unused))) int my_rwlock_destroy(rw_lock_t *rwp) { +#ifdef _WIN32 + if (have_srwlock) + return 0; /* no destroy function */ +#endif pthread_mutex_destroy( &rwp->lock ); pthread_cond_destroy( &rwp->readers ); pthread_cond_destroy( &rwp->writers ); @@ -86,6 +219,11 @@ int my_rwlock_destroy(rw_lock_t *rwp) int my_rw_rdlock(rw_lock_t *rwp) { +#ifdef _WIN32 + if (have_srwlock) + return srw_rdlock(rwp); +#endif + pthread_mutex_lock(&rwp->lock); /* active or queued writers */ @@ -100,6 +238,12 @@ int my_rw_rdlock(rw_lock_t *rwp) int my_rw_tryrdlock(rw_lock_t *rwp) { int res; + +#ifdef _WIN32 + if (have_srwlock) + return srw_tryrdlock(rwp); +#endif + pthread_mutex_lock(&rwp->lock); if ((rwp->state < 0 ) || rwp->waiters) res= EBUSY; /* Can't get lock */ @@ -115,6 +259,11 @@ int my_rw_tryrdlock(rw_lock_t *rwp) int my_rw_wrlock(rw_lock_t *rwp) { +#ifdef _WIN32 + if (have_srwlock) + return srw_wrlock(rwp); +#endif + pthread_mutex_lock(&rwp->lock); rwp->waiters++; /* another writer queued */ @@ -130,6 +279,12 @@ int my_rw_wrlock(rw_lock_t *rwp) int my_rw_trywrlock(rw_lock_t *rwp) { int res; + +#ifdef _WIN32 + if (have_srwlock) + return srw_trywrlock(rwp); +#endif + pthread_mutex_lock(&rwp->lock); if (rwp->state) res= EBUSY; /* Can't get lock */ @@ -145,6 +300,11 @@ int my_rw_trywrlock(rw_lock_t *rwp) int my_rw_unlock(rw_lock_t *rwp) { +#ifdef _WIN32 + if (have_srwlock) + return srw_unlock(rwp); +#endif + DBUG_PRINT("rw_unlock", ("state: %d waiters: %d", rwp->state, rwp->waiters)); pthread_mutex_lock(&rwp->lock); |