fix deadlock in condition wait whenever there are multiple waiters

it's amazing none of the conformance tests i've run even bothered to
check whether something so basic works...
This commit is contained in:
Rich Felker 2011-09-22 21:08:55 -04:00
commit 4b153ac424
4 changed files with 18 additions and 5 deletions

View file

@ -2,7 +2,8 @@
int pthread_cond_broadcast(pthread_cond_t *c)
{
if (a_swap(&c->_c_block, 0))
int w = c->_c_waiters;
if (a_swap(&c->_c_block, 0) || w)
__wake(&c->_c_block, -1, 0);
return 0;
}

View file

@ -2,7 +2,8 @@
int pthread_cond_signal(pthread_cond_t *c)
{
if (a_swap(&c->_c_block, 0));
int w = c->_c_waiters;
if (a_swap(&c->_c_block, 0) || w)
__wake(&c->_c_block, 1, 0);
return 0;
}

View file

@ -1,12 +1,20 @@
#include "pthread_impl.h"
static void relock(void *m)
struct cm {
pthread_cond_t *c;
pthread_mutex_t *m;
};
static void cleanup(void *p)
{
pthread_mutex_lock(m);
struct cm *cm = p;
a_dec(&cm->c->_c_waiters);
pthread_mutex_lock(cm->m);
}
int pthread_cond_timedwait(pthread_cond_t *c, pthread_mutex_t *m, const struct timespec *ts)
{
struct cm cm = { .c=c, .m=m };
int r, e=0;
if (ts && ts->tv_nsec >= 1000000000UL)
@ -17,8 +25,10 @@ int pthread_cond_timedwait(pthread_cond_t *c, pthread_mutex_t *m, const struct t
c->_c_block = 1;
if ((r=pthread_mutex_unlock(m))) return r;
do e = __timedwait(&c->_c_block, 1, c->_c_clock, ts, relock, m, 0);
a_inc(&c->_c_waiters);
do e = __timedwait(&c->_c_block, 1, c->_c_clock, ts, cleanup, &cm, 0);
while (e == EINTR);
a_dec(&c->_c_waiters);
if ((r=pthread_mutex_lock(m))) return r;