diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/internal/pthread_impl.h | 1 | ||||
| -rw-r--r-- | src/thread/pthread_cond_broadcast.c | 8 | ||||
| -rw-r--r-- | src/thread/pthread_cond_timedwait.c | 22 | 
3 files changed, 17 insertions, 14 deletions
| diff --git a/src/internal/pthread_impl.h b/src/internal/pthread_impl.h index 63639ec2..bbb4502f 100644 --- a/src/internal/pthread_impl.h +++ b/src/internal/pthread_impl.h @@ -70,6 +70,7 @@ struct __timer {  #define _c_clock __u.__i[4]  #define _c_lock __u.__i[5]  #define _c_lockwait __u.__i[6] +#define _c_waiters2 __u.__i[7]  #define _rw_lock __u.__i[0]  #define _rw_waiters __u.__i[1]  #define _b_inst __u.__p[0] 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. */ diff --git a/src/thread/pthread_cond_timedwait.c b/src/thread/pthread_cond_timedwait.c index e9b5e2fc..e3dc8147 100644 --- a/src/thread/pthread_cond_timedwait.c +++ b/src/thread/pthread_cond_timedwait.c @@ -7,6 +7,8 @@ struct cm {  static void unwait(pthread_cond_t *c, pthread_mutex_t *m)  { +	int w; +  	/* Removing a waiter is non-trivial if we could be using requeue  	 * based broadcast signals, due to mutex access issues, etc. */ @@ -18,8 +20,10 @@ static void unwait(pthread_cond_t *c, pthread_mutex_t *m)  	while (a_swap(&c->_c_lock, 1))  		__wait(&c->_c_lock, &c->_c_lockwait, 1, 1); -	if (c->_c_waiters) c->_c_waiters--; -	else a_dec(&m->_m_waiters); +	/* Atomically decrement waiters2 if positive, else mutex waiters. */ +	do w = c->_c_waiters2; +	while (w && a_cas(&c->_c_waiters2, w, w-1)!=w); +	if (!w) a_dec(&m->_m_waiters);  	a_store(&c->_c_lock, 0);  	if (c->_c_lockwait) __wake(&c->_c_lock, 1, 1); @@ -42,16 +46,10 @@ int pthread_cond_timedwait(pthread_cond_t *c, pthread_mutex_t *m, const struct t  	pthread_testcancel(); -	if (c->_c_mutex == (void *)-1) { -		a_inc(&c->_c_waiters); -	} else { -		c->_c_mutex = m; -		while (a_swap(&c->_c_lock, 1)) -			__wait(&c->_c_lock, &c->_c_lockwait, 1, 1); -		c->_c_waiters++; -		a_store(&c->_c_lock, 0); -		if (c->_c_lockwait) __wake(&c->_c_lock, 1, 1); -	} +	if (c->_c_mutex != (void *)-1) c->_c_mutex = m; + +	a_inc(&c->_c_waiters); +	a_inc(&c->_c_waiters2);  	seq = c->_c_seq; | 
