diff options
author | Philip Guenthe <guenther@cvs.openbsd.org> | 2012-02-23 07:58:26 +0000 |
---|---|---|
committer | Philip Guenthe <guenther@cvs.openbsd.org> | 2012-02-23 07:58:26 +0000 |
commit | eff9bd0e41513bde9cd4376a12739e5459a597ca (patch) | |
tree | 7ef125132e5373d11a13269ed66e618644b710f1 /lib/librthread/rthread_sync.c | |
parent | 2a5f43742e93eb615632ad6898d6c20ac2ba36ee (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.c | 19 |
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); + } } } |