summaryrefslogtreecommitdiff
path: root/lib/libpthread
diff options
context:
space:
mode:
authornathanw <nathanw@NetBSD.org>2003-01-25 00:47:05 +0000
committernathanw <nathanw@NetBSD.org>2003-01-25 00:47:05 +0000
commit9ff1e2d38522b2004c0a5762192ce2bd3c73f4b6 (patch)
tree6ef06743da9faf20400e3846465db4ed21499339 /lib/libpthread
parentfe8e8dad4a892f0dcca519bce3419e4ca080593f (diff)
Make pthread_barrier_wait() handle spurious wakeups from pthread__block()
by adding a generation number to the barrier structure and incrementing it when the barrier fires. XXX this is an ABI change for anything using barriers, but the library is new enough and nothing in the tree uses barriers so I'm going to let it slide. Using the private data pointer for a field that will always be present would be excessive.
Diffstat (limited to 'lib/libpthread')
-rw-r--r--lib/libpthread/pthread_barrier.c41
-rw-r--r--lib/libpthread/pthread_types.h3
2 files changed, 27 insertions, 17 deletions
diff --git a/lib/libpthread/pthread_barrier.c b/lib/libpthread/pthread_barrier.c
index 5ebf6fb28b8..78704b09341 100644
--- a/lib/libpthread/pthread_barrier.c
+++ b/lib/libpthread/pthread_barrier.c
@@ -1,4 +1,4 @@
-/* $NetBSD: pthread_barrier.c,v 1.2 2003/01/18 10:34:15 thorpej Exp $ */
+/* $NetBSD: pthread_barrier.c,v 1.3 2003/01/25 00:47:06 nathanw Exp $ */
/*-
* Copyright (c) 2001, 2003 The NetBSD Foundation, Inc.
@@ -87,6 +87,7 @@ pthread_barrier_init(pthread_barrier_t *barrier,
barrier->ptb_initcount = count;
barrier->ptb_curcount = 0;
+ barrier->ptb_generation = 0;
pthread_spinunlock(self, &barrier->ptb_lock);
@@ -98,6 +99,7 @@ pthread_barrier_init(pthread_barrier_t *barrier,
PTQ_INIT(&barrier->ptb_waiters);
barrier->ptb_initcount = count;
barrier->ptb_curcount = 0;
+ barrier->ptb_generation = 0;
return 0;
}
@@ -139,6 +141,7 @@ int
pthread_barrier_wait(pthread_barrier_t *barrier)
{
pthread_t self;
+ unsigned int gen;
#ifdef ERRORCHECK
if ((barrier == NULL) || (barrier->ptb_magic != _PT_BARRIER_MAGIC))
@@ -168,6 +171,7 @@ pthread_barrier_wait(pthread_barrier_t *barrier)
blockedq = barrier->ptb_waiters;
PTQ_INIT(&barrier->ptb_waiters);
barrier->ptb_curcount = 0;
+ barrier->ptb_generation++;
PTQ_FOREACH(signaled, &blockedq, pt_sleep)
pthread__sched(self, signaled);
@@ -177,25 +181,30 @@ pthread_barrier_wait(pthread_barrier_t *barrier)
return PTHREAD_BARRIER_SERIAL_THREAD;
}
- SDPRINTF(("(barrier wait %p) Waiting on %p\n", self, barrier));
-
- pthread_spinlock(self, &self->pt_statelock);
-
- self->pt_state = PT_STATE_BLOCKED_QUEUE;
- self->pt_sleepobj = barrier;
- self->pt_sleepq = &barrier->ptb_waiters;
- self->pt_sleeplock = &barrier->ptb_lock;
+ barrier->ptb_curcount++;
+ gen = barrier->ptb_generation;
+ while (gen == barrier->ptb_generation) {
+ SDPRINTF(("(barrier wait %p) Waiting on %p\n",
+ self, barrier));
- pthread_spinunlock(self, &self->pt_statelock);
+ pthread_spinlock(self, &self->pt_statelock);
- PTQ_INSERT_TAIL(&barrier->ptb_waiters, self, pt_sleep);
- barrier->ptb_curcount++;
+ self->pt_state = PT_STATE_BLOCKED_QUEUE;
+ self->pt_sleepobj = barrier;
+ self->pt_sleepq = &barrier->ptb_waiters;
+ self->pt_sleeplock = &barrier->ptb_lock;
+
+ pthread_spinunlock(self, &self->pt_statelock);
- pthread__block(self, &barrier->ptb_lock);
- /* Spinlock is unlocked on return */
+ PTQ_INSERT_TAIL(&barrier->ptb_waiters, self, pt_sleep);
- SDPRINTF(("(barrier wait %p) Woke up on %p\n",
- self, barrier));
+ pthread__block(self, &barrier->ptb_lock);
+ SDPRINTF(("(barrier wait %p) Woke up on %p\n",
+ self, barrier));
+ /* Spinlock is unlocked on return */
+ pthread_spinlock(self, &barrier->ptb_lock);
+ }
+ pthread_spinunlock(self, &barrier->ptb_lock);
return 0;
}
diff --git a/lib/libpthread/pthread_types.h b/lib/libpthread/pthread_types.h
index fd9a42b33bb..e25eb69d757 100644
--- a/lib/libpthread/pthread_types.h
+++ b/lib/libpthread/pthread_types.h
@@ -1,4 +1,4 @@
-/* $NetBSD: pthread_types.h,v 1.2 2003/01/18 10:34:17 thorpej Exp $ */
+/* $NetBSD: pthread_types.h,v 1.3 2003/01/25 00:47:05 nathanw Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -224,6 +224,7 @@ struct pthread_barrier_st {
struct pthread_queue_t ptb_waiters;
unsigned int ptb_initcount;
unsigned int ptb_curcount;
+ unsigned int ptb_generation;
void *ptb_private;
};