2.9
[glibc/nacl-glibc.git] / nptl / sysdeps / unix / sysv / linux / sh / pthread_cond_broadcast.S
blob7dff15ac52a5d638657be60f20dcdc9c603e71cb
1 /* Copyright (C) 2003, 2004, 2006, 2007 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 <shlib-compat.h>
21 #include <lowlevellock.h>
22 #include <lowlevelcond.h>
23 #include <kernel-features.h>
24 #include <pthread-pi-defines.h>
25 #include <pthread-errnos.h>
26 #include "lowlevel-atomic.h"
28         .text
30         /* int pthread_cond_broadcast (pthread_cond_t *cond) */
31         .globl  __pthread_cond_broadcast
32         .type   __pthread_cond_broadcast, @function
33         .align  5
34 __pthread_cond_broadcast:
35         mov.l   r10, @-r15
36         mov.l   r9, @-r15
37         mov.l   r8, @-r15
38         sts.l   pr, @-r15
39         mov     r4, r8
41         /* Get internal lock.  */
42         mov     #0, r3
43         mov     #1, r4
44 #if cond_lock != 0
45         CMPXCHG (r3, @(cond_lock,r8), r4, r2)
46 #else
47         CMPXCHG (r3, @r8, r4, r2)
48 #endif
49         bf      1f
51         mov.l   @(total_seq+4,r8),r0
52         mov.l   @(total_seq,r8),r1
53         mov.l   @(wakeup_seq+4,r8), r2
54         cmp/hi  r2, r0
55         bt      3f
56         cmp/hi  r0, r2
57         bt      4f
58         mov.l   @(wakeup_seq,r8), r2
59         cmp/hi  r2, r1
60         bf      4f
63         /* Cause all currently waiting threads to recognize they are
64            woken up.  */
65         mov.l   r1, @(wakeup_seq,r8)
66         mov.l   r0, @(wakeup_seq+4,r8)
67         mov.l   r1, @(woken_seq,r8)
68         mov.l   r0, @(woken_seq+4,r8)
69         mov.l   @(broadcast_seq,r8), r2
70         add     #1, r2
71         mov.l   r2, @(broadcast_seq,r8)
72         add     r1, r1
73         mov     r1, r10
74         mov.l   r10, @(cond_futex,r8)
76         /* Get the address of the mutex used.  */
77         mov.l   @(dep_mutex,r8), r9
79         /* Unlock.  */
80 #if cond_lock != 0
81         DEC (@(cond_lock,r8), r2)
82 #else
83         DEC (@r8, r2)
84 #endif
85         tst     r2, r2
86         bf      7f
89         /* Don't use requeue for pshared condvars.  */
90         mov     #-1, r0
91         cmp/eq  r0, r9
92         mov     r8, r4
93         bt/s    9f
94          add    #cond_futex, r4
96         /* XXX: The kernel only supports FUTEX_CMP_REQUEUE to the same
97            type of futex (private resp. shared).  */
98         mov.l   @(MUTEX_KIND,r9), r0
99         tst     #(PI_BIT|PS_BIT), r0
100         bf      9f
102         /* Wake up all threads.  */
103 #ifdef __ASSUME_PRIVATE_FUTEX
104         mov     #(FUTEX_CMP_REQUEUE|FUTEX_PRIVATE_FLAG), r5
105         extu.b  r5, r5
106 #else
107         stc     gbr, r1
108         mov.w   .Lpfoff, r2
109         add     r2, r1
110         mov.l   @r1, r5
111         mov     #FUTEX_CMP_REQUEUE, r0
112         or      r0, r5
113 #endif
114         mov     #1, r6
115         mov     #-1, r7
116         shlr    r7              /* r7 = 0x7fffffff */
117         mov     r9, r0
118 # if MUTEX_FUTEX != 0
119         add     #MUTEX_FUTEX, r0
120 # endif
121         mov     r10, r1
122         mov     #SYS_futex, r3
123         extu.b  r3, r3
124         trapa   #0x16
125         SYSCALL_INST_PAD
127         /* For any kind of error, which mainly is EAGAIN, we try again
128            with WAKE.  The general test also covers running on old
129            kernels.  */
130         mov     r0, r1
131         mov     #-12, r2
132         shad    r2, r1
133         not     r1, r1
134         tst     r1, r1
135         mov     r8, r4
136         bt/s    9f
137          add    #cond_futex, r4
140         mov     #0, r0
141         lds.l   @r15+, pr
142         mov.l   @r15+, r8
143         mov.l   @r15+, r9
144         rts
145          mov.l  @r15+, r10
148         /* Unlock.  */
149 #if cond_lock != 0
150         DEC (@(cond_lock,r8), r2)
151 #else
152         DEC (@r8, r2)
153 #endif
154         tst     r2, r2
155         bf      5f
157         mov     #0, r0
158         lds.l   @r15+, pr
159         mov.l   @r15+, r8
160         mov.l   @r15+, r9
161         rts
162          mov.l  @r15+, r10
165         /* Initial locking failed.  */
166         mov     r8, r5
167 #if cond_lock != 0
168         add     #cond_lock, r5
169 #endif
170         mov.l   @(dep_mutex,r8), r0
171         cmp/eq  #-1, r0
172         bf/s    99f
173          mov    #LLL_PRIVATE, r6
174         mov     #LLL_SHARED, r6
175 99:     
176         extu.b  r6, r6
177         mov.l   .Lwait5, r1
178         bsrf    r1
179          mov    r2, r4
180 .Lwait5b:
181         bra     2b
182          nop
185         /* Unlock in loop requires wakeup.  */
186         mov     r8, r4
187 #if cond_lock != 0
188         add     #cond_lock, r4
189 #endif
190         mov.l   @(dep_mutex,r8), r0
191         cmp/eq  #-1, r0
192         bf/s    99f
193          mov    #LLL_PRIVATE, r5
194         mov     #LLL_SHARED, r5
195 99:     
196         mov.l   .Lwake5, r1
197         bsrf    r1
198          extu.b r5, r5
199 .Lwake5b:
200         bra     6b
201          nop
204         /* Unlock in loop requires wakeup.  */
205         mov     r8, r4
206 #if cond_lock != 0
207         add     #cond_lock, r4
208 #endif
209         mov     #-1, r0
210         cmp/eq  r0, r9
211         bf/s    99f
212          mov    #LLL_PRIVATE, r5
213         mov     #LLL_SHARED, r5
214 99:     
215         mov.l   .Lwake6, r1
216         bsrf    r1
217          extu.b r5, r5
218 .Lwake6b:
219         bra     8b
220          nop
223         mov     #-1, r0
224         cmp/eq  r0, r9
225         bt/s    99f
226          mov    #FUTEX_WAKE, r5
227 #ifdef __ASSUME_PRIVATE_FUTEX
228         mov     #(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), r5
229         extu.b  r5, r5
230 #else
231         stc     gbr, r1
232         mov.w   .Lpfoff, r2
233         add     r2, r1
234         mov.l   @r1, r5
235         mov     #FUTEX_WAKE, r0
236         or      r0, r5
237 #endif
238 99:     
239         mov     #-1, r6
240         shlr    r6              /* r6 = 0x7fffffff */
241         mov     #0, r7
242         mov     #SYS_futex, r3
243         extu.b  r3, r3
244         trapa   #0x14
245         SYSCALL_INST_PAD
246         bra     10b
247          nop
249 #ifndef __ASSUME_PRIVATE_FUTEX
250 .Lpfoff:
251         .word   PRIVATE_FUTEX - TLS_PRE_TCB_SIZE
252 #endif
254         .align  2
255 .Lwait5:
256         .long   __lll_lock_wait-.Lwait5b
257 .Lwake5:
258         .long   __lll_unlock_wake-.Lwake5b
259 .Lwake6:
260         .long   __lll_unlock_wake-.Lwake6b
261         .size   __pthread_cond_broadcast, .-__pthread_cond_broadcast
262 versioned_symbol (libpthread, __pthread_cond_broadcast, pthread_cond_broadcast,
263                   GLIBC_2_3_2)