1 #include "pthread_impl.h"
5 void __vm_lock(int inc)
9 if (inc*v < 0) __wait(vmlock, vmlock+1, v, 1);
10 else if (a_cas(vmlock, v, v+inc)==v) break;
14 void __vm_unlock(void)
16 int inc = vmlock[0]>0 ? -1 : 1;
17 if (a_fetch_add(vmlock, inc)==-inc && vmlock[1])
18 __wake(vmlock, -1, 1);
21 static int pshared_barrier_wait(pthread_barrier_t *b)
23 int limit = (b->_b_limit & INT_MAX) + 1;
27 if (limit==1) return PTHREAD_BARRIER_SERIAL_THREAD;
29 while ((v=a_cas(&b->_b_lock, 0, limit)))
30 __wait(&b->_b_lock, &b->_b_waiters, v, 0);
32 /* Wait for <limit> threads to get to the barrier */
33 if (++b->_b_count == limit) {
34 a_store(&b->_b_count, 0);
35 ret = PTHREAD_BARRIER_SERIAL_THREAD;
36 if (b->_b_waiters2) __wake(&b->_b_count, -1, 0);
38 a_store(&b->_b_lock, 0);
39 if (b->_b_waiters) __wake(&b->_b_lock, 1, 0);
40 while ((v=b->_b_count)>0)
41 __wait(&b->_b_count, &b->_b_waiters2, v, 0);
46 /* Ensure all threads have a vm lock before proceeding */
47 if (a_fetch_add(&b->_b_count, -1)==1-limit) {
48 a_store(&b->_b_count, 0);
49 if (b->_b_waiters2) __wake(&b->_b_count, -1, 0);
51 while ((v=b->_b_count))
52 __wait(&b->_b_count, &b->_b_waiters2, v, 0);
55 /* Perform a recursive unlock suitable for self-sync'd destruction */
59 } while (a_cas(&b->_b_lock, v, v==INT_MIN+1 ? 0 : v-1) != v);
61 /* Wake a thread waiting to reuse or destroy the barrier */
62 if (v==INT_MIN+1 || (v==1 && w))
63 __wake(&b->_b_lock, 1, 0);
78 int pthread_barrier_wait(pthread_barrier_t *b)
80 int limit = b->_b_limit;
81 struct instance *inst;
83 /* Trivial case: count was set at 1 */
84 if (!limit) return PTHREAD_BARRIER_SERIAL_THREAD;
86 /* Process-shared barriers require a separate, inefficient wait */
87 if (limit < 0) return pshared_barrier_wait(b);
89 /* Otherwise we need a lock on the barrier object */
90 while (a_swap(&b->_b_lock, 1))
91 __wait(&b->_b_lock, &b->_b_waiters, 1, 1);
94 /* First thread to enter the barrier becomes the "instance owner" */
96 struct instance new_inst = { 0 };
98 b->_b_inst = inst = &new_inst;
99 a_store(&b->_b_lock, 0);
100 if (b->_b_waiters) __wake(&b->_b_lock, 1, 1);
101 while (spins-- && !inst->finished)
103 a_inc(&inst->finished);
104 while (inst->finished == 1)
105 __syscall(SYS_futex, &inst->finished, FUTEX_WAIT,1,0);
106 return PTHREAD_BARRIER_SERIAL_THREAD;
109 /* Last thread to enter the barrier wakes all non-instance-owners */
110 if (++inst->count == limit) {
112 a_store(&b->_b_lock, 0);
113 if (b->_b_waiters) __wake(&b->_b_lock, 1, 1);
114 a_store(&inst->last, 1);
116 __wake(&inst->last, -1, 1);
118 a_store(&b->_b_lock, 0);
119 if (b->_b_waiters) __wake(&b->_b_lock, 1, 1);
120 __wait(&inst->last, &inst->waiters, 0, 1);
123 /* Last thread to exit the barrier wakes the instance owner */
124 if (a_fetch_add(&inst->count,-1)==1 && a_fetch_add(&inst->finished,1))
125 __wake(&inst->finished, 1, 1);