2.9
[glibc/nacl-glibc.git] / nptl / sysdeps / unix / sysv / linux / sh / pthread_barrier_wait.S
blob4a6059aef499b8f75e9624a7aed86dd0d9c8fd2c
1 /* Copyright (C) 2003, 2004, 2007, 2008 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
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.
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.
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, write to the Free
16    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17    02111-1307 USA.  */
19 #include <sysdep.h>
20 #include <lowlevellock.h>
21 #include <lowlevelbarrier.h>
22 #include "lowlevel-atomic.h"
24         .text
26         .globl  pthread_barrier_wait
27         .type   pthread_barrier_wait,@function
28         .align  5
29 pthread_barrier_wait:
30         mov.l   r9, @-r15
31         mov.l   r8, @-r15
32         sts.l   pr, @-r15
33         mov     r4, r8
35         /* Get the mutex.  */
36         mov     #0, r3
37         mov     #1, r4
38         CMPXCHG (r3, @(MUTEX,r8), r4, r2)
39         bf      1f
41         /* One less waiter.  If this was the last one needed wake
42            everybody.  */
44         mov.l   @(LEFT,r8), r0
45         add     #-1, r0
46         mov.l   r0, @(LEFT,r8)
47         tst     r0, r0
48         bt      3f
50         /* There are more threads to come.  */
51         mov.l   @(CURR_EVENT,r8), r6
53         /* Release the mutex.  */
54         DEC (@(MUTEX,r8), r2)
55         tst     r2, r2
56         bf      6f
58         /* Wait for the remaining threads.  The call will return immediately
59            if the CURR_EVENT memory has meanwhile been changed.  */
60         mov     r8, r4
61 #if CURR_EVENT != 0
62         add     #CURR_EVENT, r4
63 #endif
64 #if FUTEX_WAIT == 0
65         mov.l   @(PRIVATE,r8), r5
66 #else
67         mov     #FUTEX_WAIT, r5
68         mov.l   @(PRIVATE,r8), r0
69         or      r0, r5
70 #endif
71         mov     #0, r7
73         mov     #SYS_futex, r3
74         extu.b  r3, r3
75         trapa   #0x14
76         SYSCALL_INST_PAD
78         /* Don't return on spurious wakeups.  The syscall does not change
79            any register except r0 so there is no need to reload any of
80            them.  */
81         mov.l   @(CURR_EVENT,r8), r0
82         cmp/eq  r0, r6
83         bt      8b
85         /* Increment LEFT.  If this brings the count back to the
86            initial count unlock the object.  */
87         mov     #1, r3
88         mov.l   @(INIT_COUNT,r8), r4
89         XADD    (r3, @(LEFT,r8), r2, r5)
90         add     #-1, r4
91         cmp/eq  r2, r4
92         bf      10f
94         /* Release the mutex.  We cannot release the lock before
95            waking the waiting threads since otherwise a new thread might
96            arrive and gets waken up, too.  */
97         DEC (@(MUTEX,r8), r2)
98         tst     r2, r2
99         bf      9f
102         mov     #0, r0          /* != PTHREAD_BARRIER_SERIAL_THREAD */
103         lds.l   @r15+, pr
104         mov.l   @r15+, r8
105         rts
106          mov.l  @r15+, r9
109         /* The necessary number of threads arrived.  */
110         mov.l   @(CURR_EVENT,r8), r1
111         add     #1, r1
112         mov.l   r1, @(CURR_EVENT,r8)
114         /* Wake up all waiters.  The count is a signed number in the kernel
115            so 0x7fffffff is the highest value.  */
116         mov.l   .Lall, r6
117         mov     r8, r4
118 #if CURR_EVENT != 0
119         add     #CURR_EVENT, r4
120 #endif
121         mov     #0, r7
122         mov     #FUTEX_WAKE, r5
123         mov.l   @(PRIVATE,r8), r0
124         or      r0, r5
125         mov     #SYS_futex, r3
126         extu.b  r3, r3
127         trapa   #0x14
128         SYSCALL_INST_PAD
130         /* Increment LEFT.  If this brings the count back to the
131            initial count unlock the object.  */
132         mov     #1, r3
133         mov.l   @(INIT_COUNT,r8), r4
134         XADD    (r3, @(LEFT,r8), r2, r5)
135         add     #-1, r4
136         cmp/eq  r2, r4
137         bf      5f
139         /* Release the mutex.  */
140         DEC (@(MUTEX,r8), r2)
141         tst     r2, r2
142         bf      4f
144         mov     #-1, r0         /* == PTHREAD_BARRIER_SERIAL_THREAD */
145         lds.l   @r15+, pr
146         mov.l   @r15+, r8
147         rts
148          mov.l  @r15+, r9
151         mov.l   @(PRIVATE,r8), r6
152         mov     #LLL_SHARED, r0
153         extu.b  r0, r0
154         xor     r0, r6
155         mov     r2, r4
156         mov     r8, r5
157         mov.l   .Lwait0, r1
158         bsrf    r1
159          add    #MUTEX, r5
160 .Lwait0b:
161         bra     2b
162          nop
165         mov.l   @(PRIVATE,r8), r5
166         mov     #LLL_SHARED, r0
167         extu.b  r0, r0
168         xor     r0, r5
169         mov     r8, r4
170         mov.l   .Lwake0, r1
171         bsrf    r1
172          add    #MUTEX, r4
173 .Lwake0b:
174         bra     5b
175          nop
178         mov     r6, r9
179         mov.l   @(PRIVATE,r8), r5
180         mov     #LLL_SHARED, r0
181         extu.b  r0, r0
182         xor     r0, r5
183         mov     r8, r4
184         mov.l   .Lwake1, r1
185         bsrf    r1
186          add    #MUTEX, r4
187 .Lwake1b:
188         bra     7b
189          mov    r9, r6
191 9:      
192         mov     r6, r9
193         mov.l   @(PRIVATE,r8), r5
194         mov     #LLL_SHARED, r0
195         extu.b  r0, r0
196         xor     r0, r5
197         mov     r8, r4
198         mov.l   .Lwake2, r1
199         bsrf    r1
200          add    #MUTEX, r4
201 .Lwake2b:
202         bra     10b
203          mov    r9, r6
205         .align  2
206 .Lall:
207         .long   0x7fffffff
208 .Lwait0:
209         .long   __lll_lock_wait-.Lwait0b
210 .Lwake0:
211         .long   __lll_unlock_wake-.Lwake0b
212 .Lwake1:
213         .long   __lll_unlock_wake-.Lwake1b
214 .Lwake2:
215         .long   __lll_unlock_wake-.Lwake2b
216         .size   pthread_barrier_wait,.-pthread_barrier_wait