diff options
| author | ad <ad@NetBSD.org> | 2008-02-23 15:15:57 +0000 |
|---|---|---|
| committer | ad <ad@NetBSD.org> | 2008-02-23 15:15:57 +0000 |
| commit | 686921623977ec9bbb079b4cc7019a075d2f09e8 (patch) | |
| tree | b26856378cf59d3f38150c8b3c4713f4c35b67f0 /lib/libpthread | |
| parent | 6b959e1dfcae24005fea36728c8ed80ff36216cf (diff) | |
Fix pthread_mutex_trylock() for recursive mutexes. PR lib/38087.
Based on a patch provided by rafal@.
Diffstat (limited to 'lib/libpthread')
| -rw-r--r-- | lib/libpthread/pthread_mutex.c | 28 |
1 files changed, 20 insertions, 8 deletions
diff --git a/lib/libpthread/pthread_mutex.c b/lib/libpthread/pthread_mutex.c index c58bc548470..ed1c40c916b 100644 --- a/lib/libpthread/pthread_mutex.c +++ b/lib/libpthread/pthread_mutex.c @@ -1,4 +1,4 @@ -/* $NetBSD: pthread_mutex.c,v 1.45 2008/02/14 21:40:51 ad Exp $ */ +/* $NetBSD: pthread_mutex.c,v 1.46 2008/02/23 15:15:57 ad Exp $ */ /*- * Copyright (c) 2001, 2003, 2006, 2007, 2008 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: pthread_mutex.c,v 1.45 2008/02/14 21:40:51 ad Exp $"); +__RCSID("$NetBSD: pthread_mutex.c,v 1.46 2008/02/23 15:15:57 ad Exp $"); #include <sys/types.h> #include <sys/lwpctl.h> @@ -322,7 +322,7 @@ int pthread_mutex_trylock(pthread_mutex_t *ptm) { pthread_t self; - void *val; + void *val, *new, *next; self = pthread__self(); val = atomic_cas_ptr(&ptm->ptm_owner, NULL, self); @@ -333,11 +333,23 @@ pthread_mutex_trylock(pthread_mutex_t *ptm) return 0; } - if (MUTEX_OWNER(val) == (uintptr_t)self && MUTEX_RECURSIVE(val)) { - if (ptm->ptm_recursed == INT_MAX) - return EAGAIN; - ptm->ptm_recursed++; - return 0; + if (MUTEX_RECURSIVE(val)) { + if (MUTEX_OWNER(val) == 0) { + new = (void *)((uintptr_t)self | (uintptr_t)val); + next = atomic_cas_ptr(&ptm->ptm_owner, val, new); + if (__predict_true(next == val)) { +#ifndef PTHREAD__ATOMIC_IS_MEMBAR + membar_enter(); +#endif + return 0; + } + } + if (MUTEX_OWNER(val) == (uintptr_t)self) { + if (ptm->ptm_recursed == INT_MAX) + return EAGAIN; + ptm->ptm_recursed++; + return 0; + } } return EBUSY; |
