diff options
| author | nathanw <nathanw@NetBSD.org> | 2003-11-21 22:08:00 +0000 |
|---|---|---|
| committer | nathanw <nathanw@NetBSD.org> | 2003-11-21 22:08:00 +0000 |
| commit | 4e755ddba83082e84e98aad5400d749e604b7980 (patch) | |
| tree | 893c09c9d7566219f492c7b7208e21c73f7d6660 /lib/libpthread | |
| parent | e0cae3a80b4685b191a95ff5104bbc39051ae72f (diff) | |
Prevent ptc_mutex from remaining set if a CV sleep is woken by
cancellation:
* Arrange to not set ptc_mutex until after the pre-sleep cancellation
test.
* In the post-sleep cancellation test, check if there are no more
sleepers and clear ptc_mutex if so.
While here, sprinkle some __predict_false() around the cancellation
tests.
Diffstat (limited to 'lib/libpthread')
| -rw-r--r-- | lib/libpthread/pthread_cond.c | 63 |
1 files changed, 39 insertions, 24 deletions
diff --git a/lib/libpthread/pthread_cond.c b/lib/libpthread/pthread_cond.c index 28cf687a3f9..e2ff7ec9eaf 100644 --- a/lib/libpthread/pthread_cond.c +++ b/lib/libpthread/pthread_cond.c @@ -1,4 +1,4 @@ -/* $NetBSD: pthread_cond.c,v 1.11 2003/04/23 19:36:12 nathanw Exp $ */ +/* $NetBSD: pthread_cond.c,v 1.12 2003/11/21 22:08:00 nathanw Exp $ */ /*- * Copyright (c) 2001 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: pthread_cond.c,v 1.11 2003/04/23 19:36:12 nathanw Exp $"); +__RCSID("$NetBSD: pthread_cond.c,v 1.12 2003/11/21 22:08:00 nathanw Exp $"); #include <errno.h> #include <sys/time.h> @@ -118,6 +118,14 @@ pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) return pthread_cond_wait_nothread(self, mutex, NULL); pthread_spinlock(self, &cond->ptc_lock); + SDPRINTF(("(cond wait %p) Waiting on %p, mutex %p\n", + self, cond, mutex)); + pthread_spinlock(self, &self->pt_statelock); + if (__predict_false(self->pt_cancel)) { + pthread_spinunlock(self, &self->pt_statelock); + pthread_spinunlock(self, &cond->ptc_lock); + pthread_exit(PTHREAD_CANCELED); + } #ifdef ERRORCHECK if (cond->ptc_mutex == NULL) cond->ptc_mutex = mutex; @@ -126,28 +134,27 @@ pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) "Multiple mutexes used for condition wait", cond->ptc_mutex == mutex); #endif - - SDPRINTF(("(cond wait %p) Waiting on %p, mutex %p\n", - self, cond, mutex)); - pthread_spinlock(self, &self->pt_statelock); - if (self->pt_cancel) { - pthread_spinunlock(self, &self->pt_statelock); - pthread_spinunlock(self, &cond->ptc_lock); - pthread_exit(PTHREAD_CANCELED); - } self->pt_state = PT_STATE_BLOCKED_QUEUE; self->pt_sleepobj = cond; self->pt_sleepq = &cond->ptc_waiters; self->pt_sleeplock = &cond->ptc_lock; pthread_spinunlock(self, &self->pt_statelock); - PTQ_INSERT_HEAD(&cond->ptc_waiters, self, pt_sleep); pthread_mutex_unlock(mutex); pthread__block(self, &cond->ptc_lock); /* Spinlock is unlocked on return */ pthread_mutex_lock(mutex); - pthread__testcancel(self); + if (__predict_false(self->pt_cancel)) { +#ifdef ERRORCHECK + pthread_spinlock(self, &cond->ptc_lock); + if (PTQ_EMPTY(&cond->ptc_waiters)) + cond->ptc_mutex = NULL; + pthread_spinunlock(self, &cond->ptc_lock); +#endif + pthread_exit(PTHREAD_CANCELED); + } + SDPRINTF(("(cond wait %p) Woke up on %p, mutex %p\n", self, cond, mutex)); @@ -187,15 +194,6 @@ pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, return pthread_cond_wait_nothread(self, mutex, abstime); pthread_spinlock(self, &cond->ptc_lock); -#ifdef ERRORCHECK - if (cond->ptc_mutex == NULL) - cond->ptc_mutex = mutex; - else - pthread__error(EINVAL, - "Multiple mutexes used for condition wait", - cond->ptc_mutex == mutex); -#endif - wait.ptw_thread = self; wait.ptw_cond = cond; retval = 0; @@ -203,11 +201,20 @@ pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, self, cond, abstime->tv_sec, abstime->tv_nsec/1000)); pthread_spinlock(self, &self->pt_statelock); - if (self->pt_cancel) { + if (__predict_false(self->pt_cancel)) { pthread_spinunlock(self, &self->pt_statelock); pthread_spinunlock(self, &cond->ptc_lock); pthread_exit(PTHREAD_CANCELED); } +#ifdef ERRORCHECK + if (cond->ptc_mutex == NULL) + cond->ptc_mutex = mutex; + else + pthread__error(EINVAL, + "Multiple mutexes used for condition wait", + cond->ptc_mutex == mutex); +#endif + pthread__alarm_add(self, &alarm, abstime, pthread_cond_wait__callback, &wait); self->pt_state = PT_STATE_BLOCKED_QUEUE; @@ -229,7 +236,15 @@ pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, SDPRINTF(("(cond timed wait %p) %s\n", self, (retval == ETIMEDOUT) ? "(timed out)" : "")); pthread_mutex_lock(mutex); - pthread__testcancel(self); + if (__predict_false(self->pt_cancel)) { +#ifdef ERRORCHECK + pthread_spinlock(self, &cond->ptc_lock); + if (PTQ_EMPTY(&cond->ptc_waiters)) + cond->ptc_mutex = NULL; + pthread_spinunlock(self, &cond->ptc_lock); +#endif + pthread_exit(PTHREAD_CANCELED); + } return retval; } |
