summaryrefslogtreecommitdiff
path: root/lib/librthread/rthread_sync.c
diff options
context:
space:
mode:
authorPhilip Guenthe <guenther@cvs.openbsd.org>2012-02-23 07:58:26 +0000
committerPhilip Guenthe <guenther@cvs.openbsd.org>2012-02-23 07:58:26 +0000
commiteff9bd0e41513bde9cd4376a12739e5459a597ca (patch)
tree7ef125132e5373d11a13269ed66e618644b710f1 /lib/librthread/rthread_sync.c
parent2a5f43742e93eb615632ad6898d6c20ac2ba36ee (diff)
PTHREAD_MUTEX_NORMAL mutexes are supposed to self-deadlock, not abort.
That deadlock can be exited via a timeout for pthread_mutex_timedlock(). Unwind all the state when pthread_mutex_timedlock() times out
Diffstat (limited to 'lib/librthread/rthread_sync.c')
-rw-r--r--lib/librthread/rthread_sync.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/lib/librthread/rthread_sync.c b/lib/librthread/rthread_sync.c
index 9d412bd5a5b..2d5b5afe587 100644
--- a/lib/librthread/rthread_sync.c
+++ b/lib/librthread/rthread_sync.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rthread_sync.c,v 1.31 2012/02/23 04:43:06 guenther Exp $ */
+/* $OpenBSD: rthread_sync.c,v 1.32 2012/02/23 07:58:25 guenther Exp $ */
/*
* Copyright (c) 2004,2005 Ted Unangst <tedu@openbsd.org>
* Copyright (c) 2012 Philip Guenther <guenther@openbsd.org>
@@ -120,7 +120,13 @@ _rthread_mutex_lock(pthread_mutex_t *mutexp, int trywait,
_spinunlock(&mutex->lock);
return (trywait ? EBUSY : EDEADLK);
}
- abort();
+
+ /* self-deadlock, possibly until timeout */
+ assert(mutex->type == PTHREAD_MUTEX_NORMAL);
+ while (__thrsleep(self, CLOCK_REALTIME, abstime,
+ &mutex->lock, NULL) != EWOULDBLOCK)
+ _spinlock(&mutex->lock);
+ return (ETIMEDOUT);
}
} else if (trywait) {
/* try failed */
@@ -130,10 +136,17 @@ _rthread_mutex_lock(pthread_mutex_t *mutexp, int trywait,
/* add to the wait queue and block until at the head */
TAILQ_INSERT_TAIL(&mutex->lockers, self, waiting);
while (mutex->owner != self) {
- __thrsleep(self, CLOCK_REALTIME, abstime,
+ ret = __thrsleep(self, CLOCK_REALTIME, abstime,
&mutex->lock, NULL);
_spinlock(&mutex->lock);
assert(mutex->owner != NULL);
+ if (ret == EWOULDBLOCK) {
+ if (mutex->owner == self)
+ break;
+ TAILQ_REMOVE(&mutex->lockers, self, waiting);
+ _spinunlock(&mutex->lock);
+ return (ETIMEDOUT);
+ }
}
}