diff options
| author | nathanw <nathanw@NetBSD.org> | 2003-01-25 00:47:05 +0000 |
|---|---|---|
| committer | nathanw <nathanw@NetBSD.org> | 2003-01-25 00:47:05 +0000 |
| commit | 9ff1e2d38522b2004c0a5762192ce2bd3c73f4b6 (patch) | |
| tree | 6ef06743da9faf20400e3846465db4ed21499339 /lib/libpthread | |
| parent | fe8e8dad4a892f0dcca519bce3419e4ca080593f (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.c | 41 | ||||
| -rw-r--r-- | lib/libpthread/pthread_types.h | 3 |
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; }; |
