OSDN Git Service

Replace FSF snail mail address with URLs
[uclinux-h8/uClibc.git] / libpthread / nptl / sysdeps / unix / sysv / linux / sh / pthread_barrier_wait.S
1 /* Copyright (C) 2003, 2004, 2007, 2008 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, see
16    <http://www.gnu.org/licenses/>.  */
17
18 #include <sysdep.h>
19 #include <lowlevellock.h>
20 #include <lowlevelbarrier.h>
21 #include "lowlevel-atomic.h"
22
23         .text
24
25         .globl  pthread_barrier_wait
26         .type   pthread_barrier_wait,@function
27         .align  5
28 pthread_barrier_wait:
29         mov.l   r9, @-r15
30         mov.l   r8, @-r15
31         sts.l   pr, @-r15
32         mov     r4, r8
33
34         /* Get the mutex.  */
35         mov     #0, r3
36         mov     #1, r4
37         CMPXCHG (r3, @(MUTEX,r8), r4, r2)
38         bf      1f
39
40         /* One less waiter.  If this was the last one needed wake
41            everybody.  */
42 2:
43         mov.l   @(LEFT,r8), r0
44         add     #-1, r0
45         mov.l   r0, @(LEFT,r8)
46         tst     r0, r0
47         bt      3f
48
49         /* There are more threads to come.  */
50         mov.l   @(CURR_EVENT,r8), r6
51
52         /* Release the mutex.  */
53         DEC (@(MUTEX,r8), r2)
54         tst     r2, r2
55         bf      6f
56 7:
57         /* Wait for the remaining threads.  The call will return immediately
58            if the CURR_EVENT memory has meanwhile been changed.  */
59         mov     r8, r4
60 #if CURR_EVENT != 0
61         add     #CURR_EVENT, r4
62 #endif
63 #if FUTEX_WAIT == 0
64         mov.l   @(PRIVATE,r8), r5
65 #else
66         mov     #FUTEX_WAIT, r5
67         mov.l   @(PRIVATE,r8), r0
68         or      r0, r5
69 #endif
70         mov     #0, r7
71 8:
72         mov     #SYS_futex, r3
73         extu.b  r3, r3
74         trapa   #0x14
75         SYSCALL_INST_PAD
76
77         /* Don't return on spurious wakeups.  The syscall does not change
78            any register except r0 so there is no need to reload any of
79            them.  */
80         mov.l   @(CURR_EVENT,r8), r0
81         cmp/eq  r0, r6
82         bt      8b
83
84         /* Increment LEFT.  If this brings the count back to the
85            initial count unlock the object.  */
86         mov     #1, r3
87         mov.l   @(INIT_COUNT,r8), r4
88         XADD    (r3, @(LEFT,r8), r2, r5)
89         add     #-1, r4
90         cmp/eq  r2, r4
91         bf      10f
92
93         /* Release the mutex.  We cannot release the lock before
94            waking the waiting threads since otherwise a new thread might
95            arrive and gets waken up, too.  */
96         DEC (@(MUTEX,r8), r2)
97         tst     r2, r2
98         bf      9f
99
100 10:
101         mov     #0, r0          /* != PTHREAD_BARRIER_SERIAL_THREAD */
102         lds.l   @r15+, pr
103         mov.l   @r15+, r8
104         rts
105          mov.l  @r15+, r9
106
107 3:
108         /* The necessary number of threads arrived.  */
109         mov.l   @(CURR_EVENT,r8), r1
110         add     #1, r1
111         mov.l   r1, @(CURR_EVENT,r8)
112
113         /* Wake up all waiters.  The count is a signed number in the kernel
114            so 0x7fffffff is the highest value.  */
115         mov.l   .Lall, r6
116         mov     r8, r4
117 #if CURR_EVENT != 0
118         add     #CURR_EVENT, r4
119 #endif
120         mov     #0, r7
121         mov     #FUTEX_WAKE, r5
122         mov.l   @(PRIVATE,r8), r0
123         or      r0, r5
124         mov     #SYS_futex, r3
125         extu.b  r3, r3
126         trapa   #0x14
127         SYSCALL_INST_PAD
128
129         /* Increment LEFT.  If this brings the count back to the
130            initial count unlock the object.  */
131         mov     #1, r3
132         mov.l   @(INIT_COUNT,r8), r4
133         XADD    (r3, @(LEFT,r8), r2, r5)
134         add     #-1, r4
135         cmp/eq  r2, r4
136         bf      5f
137
138         /* Release the mutex.  */
139         DEC (@(MUTEX,r8), r2)
140         tst     r2, r2
141         bf      4f
142 5:
143         mov     #-1, r0         /* == PTHREAD_BARRIER_SERIAL_THREAD */
144         lds.l   @r15+, pr
145         mov.l   @r15+, r8
146         rts
147          mov.l  @r15+, r9
148
149 1:
150         mov.l   @(PRIVATE,r8), r6
151         mov     #LLL_SHARED, r0
152         extu.b  r0, r0
153         xor     r0, r6
154         mov     r2, r4
155         mov     r8, r5
156         mov.l   .Lwait0, r1
157         bsrf    r1
158          add    #MUTEX, r5
159 .Lwait0b:
160         bra     2b
161          nop
162
163 4:
164         mov.l   @(PRIVATE,r8), r5
165         mov     #LLL_SHARED, r0
166         extu.b  r0, r0
167         xor     r0, r5
168         mov     r8, r4
169         mov.l   .Lwake0, r1
170         bsrf    r1
171          add    #MUTEX, r4
172 .Lwake0b:
173         bra     5b
174          nop
175
176 6:
177         mov     r6, r9
178         mov.l   @(PRIVATE,r8), r5
179         mov     #LLL_SHARED, r0
180         extu.b  r0, r0
181         xor     r0, r5
182         mov     r8, r4
183         mov.l   .Lwake1, r1
184         bsrf    r1
185          add    #MUTEX, r4
186 .Lwake1b:
187         bra     7b
188          mov    r9, r6
189
190 9:      
191         mov     r6, r9
192         mov.l   @(PRIVATE,r8), r5
193         mov     #LLL_SHARED, r0
194         extu.b  r0, r0
195         xor     r0, r5
196         mov     r8, r4
197         mov.l   .Lwake2, r1
198         bsrf    r1
199          add    #MUTEX, r4
200 .Lwake2b:
201         bra     10b
202          mov    r9, r6
203
204         .align  2
205 .Lall:
206         .long   0x7fffffff
207 .Lwait0:
208         .long   __lll_lock_wait-.Lwait0b
209 .Lwake0:
210         .long   __lll_unlock_wake-.Lwake0b
211 .Lwake1:
212         .long   __lll_unlock_wake-.Lwake1b
213 .Lwake2:
214         .long   __lll_unlock_wake-.Lwake2b
215         .size   pthread_barrier_wait,.-pthread_barrier_wait