diff options
author | unknown <mats@kindahl-laptop.dnsalias.net> | 2007-10-01 15:11:15 +0200 |
---|---|---|
committer | unknown <mats@kindahl-laptop.dnsalias.net> | 2007-10-01 15:11:15 +0200 |
commit | 2b9b71d0e3044572bc289701ae2a4055640a2bbb (patch) | |
tree | 8145f55af895335622aacc139487da26095a18a8 /mysys | |
parent | c6e88899460bd3478761f37a873a822f379a170d (diff) | |
download | mariadb-git-2b9b71d0e3044572bc289701ae2a4055640a2bbb.tar.gz |
BUG#30992 (Wrong implementation of pthread_mutex_trylock()):
Adding support for correct handling of pthread_mutex_trylock() on Win32
systems as well as when using the safe mutexes.
include/my_pthread.h:
Adding win_pthread_mutex_trylock() function as wrapper function for
Windows implementation of pthread_mutex_trylock().
Adding flag to safe_mutex_lock() that is shall not abort if the mutex
is already locked and instead return EBUSY since this is the POSIX
behaviour.
mysys/my_winthread.c:
Added Win32 wrappper function to handle pthread_mutex_trylock().
mysys/thr_mutex.c:
Added parameter 'try_lock' to safe_mutex_lock() to allow it to do double-
duty as a pthread_mutex_trylock() in addition to working as
pthread_mutex_lock().
The code needs to return EBUSY instead of throwing an error in the event
that the mutex is re-locked (we do not have recursive mutexes), but it
also requires some special handling to avoid race conditions when
calling the real pthread_mutex_{lock,trylock}().
Diffstat (limited to 'mysys')
-rw-r--r-- | mysys/my_winthread.c | 25 | ||||
-rw-r--r-- | mysys/thr_mutex.c | 49 |
2 files changed, 67 insertions, 7 deletions
diff --git a/mysys/my_winthread.c b/mysys/my_winthread.c index 27ccaef4f23..e9fface0521 100644 --- a/mysys/my_winthread.c +++ b/mysys/my_winthread.c @@ -40,6 +40,31 @@ void win_pthread_init(void) pthread_mutex_init(&THR_LOCK_thread,MY_MUTEX_INIT_FAST); } +/** + Adapter to @c pthread_mutex_trylock() + + @retval 0 Mutex was acquired + @retval EBUSY Mutex was already locked by a thread + @retval EINVAL Mutex could not be acquired due to other error + */ +int +win_pthread_mutex_trylock(pthread_mutex_t *mutex) +{ + switch (WaitForSingleObject(mutex, 0)) { + case WAIT_TIMEOUT: + return EBUSY; + + default: + case WAIT_FAILURE: + return EINVAL; + + case WAIT_OBJECT_0: + case WAIT_ABANDONED: /* The mutex was acquired because it was + * abandoned */ + return 0; + } +} + /* ** We have tried to use '_beginthreadex' instead of '_beginthread' here ** but in this case the program leaks about 512 characters for each diff --git a/mysys/thr_mutex.c b/mysys/thr_mutex.c index 425e5fce459..53ee907e0a3 100644 --- a/mysys/thr_mutex.c +++ b/mysys/thr_mutex.c @@ -91,7 +91,7 @@ int safe_mutex_init(safe_mutex_t *mp, } -int safe_mutex_lock(safe_mutex_t *mp,const char *file, uint line) +int safe_mutex_lock(safe_mutex_t *mp, my_bool try_lock, const char *file, uint line) { int error; if (!mp->file) @@ -104,15 +104,50 @@ int safe_mutex_lock(safe_mutex_t *mp,const char *file, uint line) } pthread_mutex_lock(&mp->global); - if (mp->count > 0 && pthread_equal(pthread_self(),mp->thread)) + if (mp->count > 0) { - fprintf(stderr,"safe_mutex: Trying to lock mutex at %s, line %d, when the mutex was already locked at %s, line %d in thread %s\n", - file,line,mp->file, mp->line, my_thread_name()); - fflush(stderr); - abort(); + if (try_lock) + { + pthread_mutex_unlock(&mp->global); + return EBUSY; + } + else if (pthread_equal(pthread_self(),mp->thread)) + { + fprintf(stderr, + "safe_mutex: Trying to lock mutex at %s, line %d, when the" + " mutex was already locked at %s, line %d in thread %s\n", + file,line,mp->file, mp->line, my_thread_name()); + fflush(stderr); + abort(); + } } pthread_mutex_unlock(&mp->global); - error=pthread_mutex_lock(&mp->mutex); + + /* + If we are imitating trylock(), we need to take special + precautions. + + - We cannot use pthread_mutex_lock() only since another thread can + overtake this thread and take the lock before this thread + causing pthread_mutex_trylock() to hang. In this case, we should + just return EBUSY. Hence, we use pthread_mutex_trylock() to be + able to return immediately. + + - We cannot just use trylock() and continue execution below, since + this would generate an error and abort execution if the thread + was overtaken and trylock() returned EBUSY . In this case, we + instead just return EBUSY, since this is the expected behaviour + of trylock(). + */ + if (try_lock) + { + error= pthread_mutex_trylock(&mp->mutex); + if (error == EBUSY) + return error; + } + else + error= pthread_mutex_lock(&mp->mutex); + if (error || (error=pthread_mutex_lock(&mp->global))) { fprintf(stderr,"Got error %d when trying to lock mutex at %s, line %d\n", |