mirror of
https://github.com/fluencelabs/musl
synced 2025-06-21 10:41:53 +00:00
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:
@ -66,6 +66,7 @@ struct __timer {
|
|||||||
#define _m_count __u.__i[5]
|
#define _m_count __u.__i[5]
|
||||||
#define _c_block __u.__i[0]
|
#define _c_block __u.__i[0]
|
||||||
#define _c_clock __u.__i[1]
|
#define _c_clock __u.__i[1]
|
||||||
|
#define _c_waiters __u.__i[2]
|
||||||
#define _rw_lock __u.__i[0]
|
#define _rw_lock __u.__i[0]
|
||||||
#define _rw_waiters __u.__i[1]
|
#define _rw_waiters __u.__i[1]
|
||||||
#define _b_inst __u.__p[0]
|
#define _b_inst __u.__p[0]
|
||||||
|
@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
int pthread_cond_broadcast(pthread_cond_t *c)
|
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);
|
__wake(&c->_c_block, -1, 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
int pthread_cond_signal(pthread_cond_t *c)
|
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);
|
__wake(&c->_c_block, 1, 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,20 @@
|
|||||||
#include "pthread_impl.h"
|
#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)
|
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;
|
int r, e=0;
|
||||||
|
|
||||||
if (ts && ts->tv_nsec >= 1000000000UL)
|
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;
|
c->_c_block = 1;
|
||||||
if ((r=pthread_mutex_unlock(m))) return r;
|
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);
|
while (e == EINTR);
|
||||||
|
a_dec(&c->_c_waiters);
|
||||||
|
|
||||||
if ((r=pthread_mutex_lock(m))) return r;
|
if ((r=pthread_mutex_lock(m))) return r;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user