1 #include "pthread_impl.h"
3 void __vm_lock_impl(int);
4 void __vm_unlock_impl(void);
6 static int pshared_barrier_wait(pthread_barrier_t
*b
)
8 int limit
= (b
->_b_limit
& INT_MAX
) + 1;
12 if (limit
==1) return PTHREAD_BARRIER_SERIAL_THREAD
;
14 while ((v
=a_cas(&b
->_b_lock
, 0, limit
)))
15 __wait(&b
->_b_lock
, &b
->_b_waiters
, v
, 0);
17 /* Wait for <limit> threads to get to the barrier */
18 if (++b
->_b_count
== limit
) {
19 a_store(&b
->_b_count
, 0);
20 ret
= PTHREAD_BARRIER_SERIAL_THREAD
;
21 if (b
->_b_waiters2
) __wake(&b
->_b_count
, -1, 0);
23 a_store(&b
->_b_lock
, 0);
24 if (b
->_b_waiters
) __wake(&b
->_b_lock
, 1, 0);
25 while ((v
=b
->_b_count
)>0)
26 __wait(&b
->_b_count
, &b
->_b_waiters2
, v
, 0);
31 /* Ensure all threads have a vm lock before proceeding */
32 if (a_fetch_add(&b
->_b_count
, -1)==1-limit
) {
33 a_store(&b
->_b_count
, 0);
34 if (b
->_b_waiters2
) __wake(&b
->_b_count
, -1, 0);
36 while ((v
=b
->_b_count
))
37 __wait(&b
->_b_count
, &b
->_b_waiters2
, v
, 0);
40 /* Perform a recursive unlock suitable for self-sync'd destruction */
44 } while (a_cas(&b
->_b_lock
, v
, v
==INT_MIN
+1 ? 0 : v
-1) != v
);
46 /* Wake a thread waiting to reuse or destroy the barrier */
47 if (v
==INT_MIN
+1 || (v
==1 && w
))
48 __wake(&b
->_b_lock
, 1, 0);
63 int pthread_barrier_wait(pthread_barrier_t
*b
)
65 int limit
= b
->_b_limit
;
66 struct instance
*inst
;
68 /* Trivial case: count was set at 1 */
69 if (!limit
) return PTHREAD_BARRIER_SERIAL_THREAD
;
71 /* Process-shared barriers require a separate, inefficient wait */
72 if (limit
< 0) return pshared_barrier_wait(b
);
74 /* Otherwise we need a lock on the barrier object */
75 while (a_swap(&b
->_b_lock
, 1))
76 __wait(&b
->_b_lock
, &b
->_b_waiters
, 1, 1);
79 /* First thread to enter the barrier becomes the "instance owner" */
81 struct instance new_inst
= { 0 };
83 b
->_b_inst
= inst
= &new_inst
;
84 a_store(&b
->_b_lock
, 0);
85 if (b
->_b_waiters
) __wake(&b
->_b_lock
, 1, 1);
86 while (spins
-- && !inst
->finished
)
88 a_inc(&inst
->finished
);
89 while (inst
->finished
== 1)
90 __syscall(SYS_futex
, &inst
->finished
, FUTEX_WAIT
,1,0);
91 return PTHREAD_BARRIER_SERIAL_THREAD
;
94 /* Last thread to enter the barrier wakes all non-instance-owners */
95 if (++inst
->count
== limit
) {
97 a_store(&b
->_b_lock
, 0);
98 if (b
->_b_waiters
) __wake(&b
->_b_lock
, 1, 1);
99 a_store(&inst
->last
, 1);
101 __wake(&inst
->last
, -1, 1);
103 a_store(&b
->_b_lock
, 0);
104 if (b
->_b_waiters
) __wake(&b
->_b_lock
, 1, 1);
105 __wait(&inst
->last
, &inst
->waiters
, 0, 1);
108 /* Last thread to exit the barrier wakes the instance owner */
109 if (a_fetch_add(&inst
->count
,-1)==1 && a_fetch_add(&inst
->finished
,1))
110 __wake(&inst
->finished
, 1, 1);