X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fruntime%2Fpthread-lutex.c;h=636521403598b1ab534ce9064383c38afb140bd0;hb=1439811447104b32d986bab40d6e2ed431247004;hp=285891b6595f0283a4218ac917f5965c12a2a5e6;hpb=402958f92506b9d3de852601b8c1ccb99b5ee558;p=sbcl.git diff --git a/src/runtime/pthread-lutex.c b/src/runtime/pthread-lutex.c index 285891b..6365214 100644 --- a/src/runtime/pthread-lutex.c +++ b/src/runtime/pthread-lutex.c @@ -15,17 +15,18 @@ #if defined(LISP_FEATURE_SB_THREAD) && defined(LISP_FEATURE_SB_LUTEX) +#include #include #include "runtime.h" #include "arch.h" #include "target-arch-os.h" #include "os.h" +#include "pthread-lutex.h" +#include "gencgc.h" #include "genesis/lutex.h" -typedef unsigned long tagged_lutex_t; - #if 1 # define lutex_assert(ex) \ do { \ @@ -55,10 +56,25 @@ lutex_init (tagged_lutex_t tagged_lutex) int ret; struct lutex *lutex = (struct lutex*) native_pointer(tagged_lutex); + lutex->mutexattr = malloc(sizeof(pthread_mutexattr_t)); + lutex_assert(lutex->mutexattr != 0); + + ret = pthread_mutexattr_init(lutex->mutexattr); + lutex_assert(ret == 0); + + /* The default type of mutex is implementation dependent. + * We use PTHREAD_MUTEX_ERRORCHECK so that locking on mutexes + * locked by the same thread does not cause deadlocks. */ + /* FIXME: pthread_mutexattr_settype is available on SUSv2 level + * implementations. Can be used without checking? */ + ret = pthread_mutexattr_settype(lutex->mutexattr, + PTHREAD_MUTEX_ERRORCHECK); + lutex_assert(ret == 0); + lutex->mutex = malloc(sizeof(pthread_mutex_t)); lutex_assert(lutex->mutex != 0); - ret = pthread_mutex_init(lutex->mutex, NULL); + ret = pthread_mutex_init(lutex->mutex, lutex->mutexattr); lutex_assert(ret == 0); lutex->condition_variable = malloc(sizeof(pthread_cond_t)); @@ -122,6 +138,28 @@ lutex_lock (tagged_lutex_t tagged_lutex) struct lutex *lutex = (struct lutex*) native_pointer(tagged_lutex); ret = thread_mutex_lock(lutex->mutex); + /* The mutex is locked by the same thread. + * + * FIXME: Usually when POSIX says that "an error value is returned" + * it actually refers to errno... + */ + if (ret == EDEADLK) + return ret; + lutex_assert(ret == 0); + + return ret; +} + +int +lutex_trylock (tagged_lutex_t tagged_lutex) +{ + int ret = 0; + struct lutex *lutex = (struct lutex*) native_pointer(tagged_lutex); + + ret = pthread_mutex_trylock(lutex->mutex); + /* The mutex is locked */ + if (ret == EDEADLK || ret == EBUSY) + return ret; lutex_assert(ret == 0); return ret; @@ -134,6 +172,10 @@ lutex_unlock (tagged_lutex_t tagged_lutex) struct lutex *lutex = (struct lutex*) native_pointer(tagged_lutex); ret = thread_mutex_unlock(lutex->mutex); + /* Unlocking unlocked mutex would occur as: + * (with-mutex (mutex) (cond-wait cond mutex)) */ + if (ret == EPERM) + return ret; lutex_assert(ret == 0); return ret; @@ -156,6 +198,12 @@ lutex_destroy (tagged_lutex_t tagged_lutex) lutex->mutex = NULL; } + if (lutex->mutexattr) { + pthread_mutexattr_destroy(lutex->mutexattr); + free(lutex->mutexattr); + lutex->mutexattr = NULL; + } + return 0; } #endif