summaryrefslogtreecommitdiff
path: root/mysys
diff options
context:
space:
mode:
authorunknown <mats@kindahl-laptop.dnsalias.net>2007-10-01 15:11:15 +0200
committerunknown <mats@kindahl-laptop.dnsalias.net>2007-10-01 15:11:15 +0200
commit2b9b71d0e3044572bc289701ae2a4055640a2bbb (patch)
tree8145f55af895335622aacc139487da26095a18a8 /mysys
parentc6e88899460bd3478761f37a873a822f379a170d (diff)
downloadmariadb-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.c25
-rw-r--r--mysys/thr_mutex.c49
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",