1 #include "pthread_impl.h"
3 static int pshared_barrier_wait(pthread_barrier_t
*b
)
5 int limit
= (b
->_b_limit
& INT_MAX
) + 1;
9 if (limit
==1) return PTHREAD_BARRIER_SERIAL_THREAD
;
11 while ((v
=a_cas(&b
->_b_lock
, 0, limit
)))
12 __wait(&b
->_b_lock
, &b
->_b_waiters
, v
, 0);
14 /* Wait for <limit> threads to get to the barrier */
15 if (++b
->_b_count
== limit
) {
16 a_store(&b
->_b_count
, 0);
17 ret
= PTHREAD_BARRIER_SERIAL_THREAD
;
18 if (b
->_b_waiters2
) __wake(&b
->_b_count
, -1, 0);
20 a_store(&b
->_b_lock
, 0);
21 if (b
->_b_waiters
) __wake(&b
->_b_lock
, 1, 0);
22 while ((v
=b
->_b_count
)>0)
23 __wait(&b
->_b_count
, &b
->_b_waiters2
, v
, 0);
28 /* Ensure all threads have a vm lock before proceeding */
29 if (a_fetch_add(&b
->_b_count
, -1)==1-limit
) {
30 a_store(&b
->_b_count
, 0);
31 if (b
->_b_waiters2
) __wake(&b
->_b_count
, -1, 0);
33 while ((v
=b
->_b_count
))
34 __wait(&b
->_b_count
, &b
->_b_waiters2
, v
, 0);
37 /* Perform a recursive unlock suitable for self-sync'd destruction */
41 } while (a_cas(&b
->_b_lock
, v
, v
==INT_MIN
+1 ? 0 : v
-1) != v
);
43 /* Wake a thread waiting to reuse or destroy the barrier */
44 if (v
==INT_MIN
+1 || (v
==1 && w
))
45 __wake(&b
->_b_lock
, 1, 0);
57 volatile int finished
;
60 int pthread_barrier_wait(pthread_barrier_t
*b
)
62 int limit
= b
->_b_limit
;
63 struct instance
*inst
;
65 /* Trivial case: count was set at 1 */
66 if (!limit
) return PTHREAD_BARRIER_SERIAL_THREAD
;
68 /* Process-shared barriers require a separate, inefficient wait */
69 if (limit
< 0) return pshared_barrier_wait(b
);
71 /* Otherwise we need a lock on the barrier object */
72 while (a_swap(&b
->_b_lock
, 1))
73 __wait(&b
->_b_lock
, &b
->_b_waiters
, 1, 1);
76 /* First thread to enter the barrier becomes the "instance owner" */
78 struct instance new_inst
= { 0 };
80 b
->_b_inst
= inst
= &new_inst
;
81 a_store(&b
->_b_lock
, 0);
82 if (b
->_b_waiters
) __wake(&b
->_b_lock
, 1, 1);
83 while (spins
-- && !inst
->finished
)
85 a_inc(&inst
->finished
);
86 while (inst
->finished
== 1)
87 __syscall(SYS_futex
,&inst
->finished
,FUTEX_WAIT
|FUTEX_PRIVATE
,1,0) != -ENOSYS
88 || __syscall(SYS_futex
,&inst
->finished
,FUTEX_WAIT
,1,0);
89 return PTHREAD_BARRIER_SERIAL_THREAD
;
92 /* Last thread to enter the barrier wakes all non-instance-owners */
93 if (++inst
->count
== limit
) {
95 a_store(&b
->_b_lock
, 0);
96 if (b
->_b_waiters
) __wake(&b
->_b_lock
, 1, 1);
97 a_store(&inst
->last
, 1);
99 __wake(&inst
->last
, -1, 1);
101 a_store(&b
->_b_lock
, 0);
102 if (b
->_b_waiters
) __wake(&b
->_b_lock
, 1, 1);
103 __wait(&inst
->last
, &inst
->waiters
, 0, 1);
106 /* Last thread to exit the barrier wakes the instance owner */
107 if (a_fetch_add(&inst
->count
,-1)==1 && a_fetch_add(&inst
->finished
,1))
108 __wake(&inst
->finished
, 1, 1);