revert previous change in cond var waiter move
[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         for (;;) {
34                 w = c->_c_waiters;
35                 a_fetch_add(&m->_m_waiters, w);
36                 if (a_cas(&c->_c_waiters, w, 0) == w) break;
37                 a_fetch_add(&m->_m_waiters, -w);
38         }
39
40         /* Perform the futex requeue, waking one waiter unless we know
41          * that the calling thread holds the mutex. */
42         __syscall(SYS_futex, &c->_c_block, FUTEX_REQUEUE,
43                 !m->_m_type || (m->_m_lock&INT_MAX)!=pthread_self()->tid,
44                 INT_MAX, &m->_m_lock);
45
46         unlock(c);
47         return 0;
48 }