Mesa (master): os: Check for spurious wakeups in pipe_barrier_wait.

Vinson Lee vlee at kemper.freedesktop.org
Mon Apr 26 07:31:41 UTC 2010


Module: Mesa
Branch: master
Commit: 31db310be489e1fc83fa3f72366e2e5fdd2a00e7
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=31db310be489e1fc83fa3f72366e2e5fdd2a00e7

Author: Vinson Lee <vlee at vmware.com>
Date:   Mon Apr 26 00:25:30 2010 -0700

os: Check for spurious wakeups in pipe_barrier_wait.

The POSIX function pthread_cond_wait can have spurious wakeups when
waiting on a condition variable.

Add a 64-bit counter that is incremented whenever the barrier becomes
full. A woken thread checks the counter. If the counter has not changed
then it has been spuriously woken and goes back to sleep. If the counter
has changed then it was properly signaled and exits the barrier.

Tested on Mac OS X.

This patch was based on ideas from Luca Barbieri.

---

 src/gallium/auxiliary/os/os_thread.h |    9 ++++++++-
 1 files changed, 8 insertions(+), 1 deletions(-)

diff --git a/src/gallium/auxiliary/os/os_thread.h b/src/gallium/auxiliary/os/os_thread.h
index 07a4268..c09e8a7 100644
--- a/src/gallium/auxiliary/os/os_thread.h
+++ b/src/gallium/auxiliary/os/os_thread.h
@@ -302,6 +302,7 @@ static INLINE void pipe_barrier_wait(pipe_barrier *barrier)
 typedef struct {
    unsigned count;
    unsigned waiters;
+   uint64_t sequence;
    pipe_mutex mutex;
    pipe_condvar condvar;
 } pipe_barrier;
@@ -310,6 +311,7 @@ static INLINE void pipe_barrier_init(pipe_barrier *barrier, unsigned count)
 {
    barrier->count = count;
    barrier->waiters = 0;
+   barrier->sequence = 0;
    pipe_mutex_init(barrier->mutex);
    pipe_condvar_init(barrier->condvar);
 }
@@ -329,9 +331,14 @@ static INLINE void pipe_barrier_wait(pipe_barrier *barrier)
    barrier->waiters++;
 
    if (barrier->waiters < barrier->count) {
-      pipe_condvar_wait(barrier->condvar, barrier->mutex);
+      uint64_t sequence = barrier->sequence;
+
+      do {
+         pipe_condvar_wait(barrier->condvar, barrier->mutex);
+      } while (sequence == barrier->sequence);
    } else {
       barrier->waiters = 0;
+      barrier->sequence++;
       pipe_condvar_broadcast(barrier->condvar);
    }
 




More information about the mesa-commit mailing list