From 1fa05210100caefc8546746e08358d81739f4b41 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 26 Sep 2011 12:54:28 -0400 Subject: fix lost signals in cond vars due to moving waiters from the cond var to the mutex in bcast, these waiters upon wakeup would steal slots in the count from newer waiters that had not yet been signaled, preventing the signal function from taking any action. to solve the problem, we simply use two separate waiter counts, and so that the original "total" waiters count is undisturbed by broadcast and still available for signal. --- src/thread/pthread_cond_broadcast.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src/thread/pthread_cond_broadcast.c') diff --git a/src/thread/pthread_cond_broadcast.c b/src/thread/pthread_cond_broadcast.c index bf6de048..9c6a462b 100644 --- a/src/thread/pthread_cond_broadcast.c +++ b/src/thread/pthread_cond_broadcast.c @@ -22,8 +22,12 @@ int pthread_cond_broadcast(pthread_cond_t *c) m = c->_c_mutex; /* Move waiter count to the mutex */ - a_fetch_add(&m->_m_waiters, c->_c_waiters); - a_store(&c->_c_waiters, 0); + for (;;) { + int w = c->_c_waiters2; + a_fetch_add(&m->_m_waiters, w); + if (a_cas(&c->_c_waiters2, w, 0) == w) break; + a_fetch_add(&m->_m_waiters, -w); + } /* Perform the futex requeue, waking one waiter unless we know * that the calling thread holds the mutex. */ -- cgit v1.2.1