summaryrefslogtreecommitdiff
path: root/lib/libpthread
diff options
context:
space:
mode:
authornathanw <nathanw@NetBSD.org>2003-11-21 22:08:00 +0000
committernathanw <nathanw@NetBSD.org>2003-11-21 22:08:00 +0000
commit4e755ddba83082e84e98aad5400d749e604b7980 (patch)
tree893c09c9d7566219f492c7b7208e21c73f7d6660 /lib/libpthread
parente0cae3a80b4685b191a95ff5104bbc39051ae72f (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.c63
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;
}