optimize cond waiter move using atomic swap instead of cas loop
[musl] / src / thread / pthread_cond_broadcast.c
1 #include "pthread_impl.h"
2
3 static void unlock(pthread_cond_t *c)
4 {
5         a_dec(&c->_c_bcast);
6         if (c->_c_leavers) __wake(&c->_c_bcast, -1, 0);
7 }
8
9 int pthread_cond_broadcast(pthread_cond_t *c)
10 {
11         pthread_mutex_t *m;
12         int w;
13
14         if (!c->_c_waiters) return 0;
15         a_inc(&c->_c_bcast);
16         if (!c->_c_waiters) {
17                 unlock(c);
18                 return 0;
19         }
20
21         a_store(&c->_c_block, 0);
22
23         m = c->_c_mutex;
24
25         /* If mutex ptr is not available, simply wake all waiters. */
26         if (m == (void *)-1) {
27                 unlock(c);
28                 __wake(&c->_c_block, -1, 0);
29                 return 0;
30         }
31
32         /* Move waiter count to the mutex */
33         w = a_swap(&c->_c_waiters, 0);
34         a_fetch_add(&m->_m_waiters, w);
35
36         /* Perform the futex requeue, waking one waiter unless we know
37          * that the calling thread holds the mutex. */
38         __syscall(SYS_futex, &c->_c_block, FUTEX_REQUEUE,
39                 !m->_m_type || (m->_m_lock&INT_MAX)!=pthread_self()->tid,
40                 INT_MAX, &m->_m_lock);
41
42         unlock(c);
43         return 0;
44 }