source: asp3_tinet_ecnl_arm/trunk/musl-1.1.18/src/thread/pthread_barrier_wait.c@ 352

Last change on this file since 352 was 352, checked in by coas-nagasima, 6 years ago

arm向けASP3版ECNLを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 2.9 KB
Line 
1#include "pthread_impl.h"
2
3static int pshared_barrier_wait(pthread_barrier_t *b)
4{
5 int limit = (b->_b_limit & INT_MAX) + 1;
6 int ret = 0;
7 int v, w;
8
9 if (limit==1) return PTHREAD_BARRIER_SERIAL_THREAD;
10
11 while ((v=a_cas(&b->_b_lock, 0, limit)))
12 __wait(&b->_b_lock, &b->_b_waiters, v, 0);
13
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);
19 } else {
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);
24 }
25
26 __vm_lock();
27
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);
32 } else {
33 while ((v=b->_b_count))
34 __wait(&b->_b_count, &b->_b_waiters2, v, 0);
35 }
36
37 /* Perform a recursive unlock suitable for self-sync'd destruction */
38 do {
39 v = b->_b_lock;
40 w = b->_b_waiters;
41 } while (a_cas(&b->_b_lock, v, v==INT_MIN+1 ? 0 : v-1) != v);
42
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);
46
47 __vm_unlock();
48
49 return ret;
50}
51
52struct instance
53{
54 volatile int count;
55 volatile int last;
56 volatile int waiters;
57 volatile int finished;
58};
59
60int pthread_barrier_wait(pthread_barrier_t *b)
61{
62 int limit = b->_b_limit;
63 struct instance *inst;
64
65 /* Trivial case: count was set at 1 */
66 if (!limit) return PTHREAD_BARRIER_SERIAL_THREAD;
67
68 /* Process-shared barriers require a separate, inefficient wait */
69 if (limit < 0) return pshared_barrier_wait(b);
70
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);
74 inst = b->_b_inst;
75
76 /* First thread to enter the barrier becomes the "instance owner" */
77 if (!inst) {
78 struct instance new_inst = { 0 };
79 int spins = 200;
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)
84 a_spin();
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;
90 }
91
92 /* Last thread to enter the barrier wakes all non-instance-owners */
93 if (++inst->count == limit) {
94 b->_b_inst = 0;
95 a_store(&b->_b_lock, 0);
96 if (b->_b_waiters) __wake(&b->_b_lock, 1, 1);
97 a_store(&inst->last, 1);
98 if (inst->waiters)
99 __wake(&inst->last, -1, 1);
100 } else {
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);
104 }
105
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);
109
110 return 0;
111}
Note: See TracBrowser for help on using the repository browser.