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:
parent
2eff02e4a0
commit
4b153ac424
4 changed files with 18 additions and 5 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue