NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
lib/38087: pthread_mutex_trylock on an unlocked recursive mutex fails with EBUSY
>Number: 38087
>Category: lib
>Synopsis: pthread_mutex_trylock fails w/unlocked recursive mutex
>Confidential: no
>Severity: serious
>Priority: high
>Responsible: lib-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Fri Feb 22 23:10:00 +0000 2008
>Originator: rafal%netbsd.org@localhost
>Release: NetBSD 4.99.54
>Organization:
Rafal's House of Hackable Hardware
>Environment:
System: NetBSD fearless-vampire-killer 4.99.54 NetBSD 4.99.54 (FVK) #6: Wed Feb
20 23:42:11 EST 2008
rafal@fearless-vampire-killer:/extra/sparc64/obj/sys/arch/sparc64/compile/FVK
sparc64
Architecture: sparc64
Machine: sparc64
>Description:
Calling pthread_mutex_trylock() on a newly created, recursive mutex
should succeed and lock the mutex. However, the latest changes to
libpthread broke this; now pthread_mutex_trylock() returns EBUSY
if any of the ancillary bits in the ptm_owner field are set (which
is how mutexes are marked as recursive).
>How-To-Repeat:
#include <stdio.h>
#include <pthread.h>
#include <errno.h>
main()
{
int rc;
pthread_mutex_t my_mtx;
pthread_mutexattr_t attr;
printf("pthread_self = %08x\n", pthread_self());
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
rc = pthread_mutex_init(&my_mtx, &attr);
pthread_mutexattr_destroy(&attr);
printf("mutex init returned %d (errno %d)\n", rc, errno);
rc = pthread_mutex_trylock(&my_mtx);
printf("trylock returned %d (errno %d)\n", rc, errno);
rc = pthread_mutex_lock(&my_mtx);
printf("lock returned %d (errno %d)\n", rc, errno);
}
Compile, run, and note that you get the following output:
pthread_self = ffe00000
mutex init returned 0 (errno 0)
trylock returned 16 (errno 0) <<< Note this
lock returned 0 (errno 0) <<< and this (lock does succeed)
On another (sparc64) machine running a -current from 1/11/2008, I get:
pthread_self = ffe00000
mutex init returned 0 (errno 0)
trylock returned 0 (errno 0) <<< Note this
lock returned 0 (errno 0)
>Fix:
Here's a quick hack I came up with that fixes the mis-feature, but it's
probably not the optimal fix.
Index: pthread_mutex.c
===================================================================
RCS file: /cvsroot/src/lib/libpthread/pthread_mutex.c,v
retrieving revision 1.45
diff -u -p -u -p -r1.45 pthread_mutex.c
--- pthread_mutex.c 14 Feb 2008 21:40:51 -0000 1.45
+++ pthread_mutex.c 22 Feb 2008 22:37:40 -0000
@@ -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,6 +333,18 @@ pthread_mutex_trylock(pthread_mutex_t *p
return 0;
}
+ 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 && MUTEX_RECURSIVE(val)) {
if (ptm->ptm_recursed == INT_MAX)
return EAGAIN;
>Unformatted:
Sources from ~ 2/19 1600 UTC.
Home |
Main Index |
Thread Index |
Old Index