pthread_rwlock_timedwrlock implementation for Linux/SH.
[kopensolaris-gnu/glibc.git] / nptl / sysdeps / unix / sysv / linux / sh / pthread_cond_wait.S
1 /* Copyright (C) 2003 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, write to the Free
16    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17    02111-1307 USA.  */
18
19 #include <sysdep.h>
20 #include <shlib-compat.h>
21 #include <lowlevelcond.h>
22 #include "lowlevel-atomic.h"
23
24 #define SYS_futex               240
25 #define FUTEX_WAIT              0
26 #define FUTEX_WAKE              1
27
28
29         .text
30
31         .align  5
32         .type   __condvar_cleanup, @function
33         .globl  __condvar_cleanup
34         .hidden __condvar_cleanup
35 __condvar_cleanup:
36         mov.l   r8, @-r15
37         sts.l   pr, @-r15
38         mov     r4, r8
39
40         /* Get internal lock.  */
41         mov     #1, r3
42 #if cond_lock != 0
43         XADD (r3, @(cond_lock,r8), r2)
44 #else
45         XADD (r3, @r8, r2)
46 #endif
47         tst     r2, r2
48         bt      1f
49         mov     r8, r5
50 #if cond_lock != 0
51         add     #cond_lock, r5
52 #endif
53         mov     r2, r4
54         mov.l   .Lwait0, r1
55         bsrf    r1
56          nop
57 .Lwait0b:
58 1:
59         mov     #1, r2
60         mov     #0, r3
61
62         clrt
63         mov.l   @(wakeup_seq,r8),r0
64         mov.l   @(wakeup_seq+4,r8),r1
65         addc    r2, r0
66         addc    r3, r1
67         mov.l   r0,@(wakeup_seq,r8)
68         mov.l   r1,@(wakeup_seq+4,r8)
69
70         clrt
71         mov.l   @(woken_seq,r8),r0
72         mov.l   @(woken_seq+4,r8),r1
73         addc    r2, r0
74         addc    r3, r1
75         mov.l   r0,@(woken_seq,r8)
76         mov.l   r1,@(woken_seq+4,r8)
77
78         /* Release internal lock.  */
79 #if cond_lock != 0
80         DEC (@(cond_lock,r8), r2)
81 #else
82         DEC (@r8, r2)
83 #endif
84         tst     r2, r2
85         bt      2f
86
87         mov     r8, r4
88 #if cond_lock != 0
89         add     #cond_lock, r4
90 #endif
91         mov.l   .Lwake0, r1
92         bsrf    r1
93          nop
94 .Lwake0b:
95 2:
96         lds.l   @r15+, pr
97         rts
98          mov.l  @r15+, r8
99
100         .align  2
101 .Lwait0:        
102         .long   __lll_mutex_lock_wait-.Lwait0b
103 .Lwake0:
104         .long   __lll_mutex_unlock_wake-.Lwake0b
105         .size   __condvar_cleanup, .-__condvar_cleanup
106
107
108 /* int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)  */
109         .globl  __pthread_cond_wait
110         .type   __pthread_cond_wait, @function
111         .align  5
112 __pthread_cond_wait:
113         mov.l   r12, @-r15
114         mov.l   r9, @-r15
115         mov.l   r8, @-r15
116         sts.l   pr, @-r15
117         add     #-32, r15
118         mov     r4, r8
119         mov     r5, r9
120
121         /* Get internal lock.  */
122         mov     #1, r3
123 #if cond_lock != 0
124         XADD (r3, @(cond_lock,r8), r2)
125 #else
126         XADD (r3, @r8, r2)
127 #endif
128         tst     r2, r2
129         bf      1f
130 2:      
131         /* Unlock the mutex.  */
132         mov.l   .Lmunlock0, r1
133         bsrf    r1
134          mov    r9, r4
135 .Lmunlock0b:
136
137         mov     #1, r2
138         mov     #0, r3
139
140         clrt
141         mov.l   @(total_seq,r8),r0
142         mov.l   @(total_seq+4,r8),r1
143         addc    r2, r0
144         addc    r3, r1
145         mov.l   r0,@(total_seq,r8)
146         mov.l   r1,@(total_seq+4,r8)
147
148         /* Install cancellation handler.  */
149 #ifdef PIC
150         mova    .Lgot0, r0
151         mov.l   .Lgot0, r12
152         add     r0, r12
153         mov.l   .Lccleanup0, r5
154         add     r12, r5
155 #else
156         mov.l   .Lccleanup0, r5
157 #endif
158         mov     r15, r4
159         add     #12, r4
160
161         mov.l   .Lccpush0, r1
162         bsrf    r1
163          mov    r8, r6
164 .Lccpush0b:
165
166         /* Get and store current wakeup_seq value.  */
167         mov.l   @(wakeup_seq,r8), r0
168         mov.l   @(wakeup_seq+4,r8), r1
169         mov.l   r0, @(4,r15)
170         mov.l   r1, @(8,r15)
171
172 8:
173         /* Unlock.  */
174 #if cond_lock != 0
175         DEC (@(cond_lock,r8), r2)
176 #else
177         DEC (@r8, r2)
178 #endif
179         tst     r2, r2
180         bf      3f
181 4:
182         mov.l   .Lenable0, r1
183         bsrf    r1
184          nop
185 .Lenable0b:
186         mov.l   r0, @r15
187
188         mov     #0, r7
189         mov     #FUTEX_WAIT, r5
190         mov.l   @(4,r15), r6
191         mov     r8, r4
192         add     #wakeup_seq, r4
193         mov     #SYS_futex, r3
194         extu.b  r3, r3
195         trapa   #0x14
196         SYSCALL_INST_PAD
197
198         mov.l   .Ldisable0, r1
199         bsrf    r1
200          mov.l  @r15, r4
201 .Ldisable0b:    
202
203         /* Lock.  */
204         mov     #1, r3
205 #if cond_lock != 0
206         XADD (r3, @(cond_lock,r8), r2)
207 #else
208         XADD (r3, @r8, r2)
209 #endif
210         tst     r2, r2
211         bf      5f
212 6:
213         mov.l   @(woken_seq,r8), r0
214         mov.l   @(woken_seq+4,r8), r1
215
216         mov.l   @(wakeup_seq,r8), r2
217         mov.l   @(wakeup_seq+4,r8), r3
218
219         mov.l   @(8,r15), r5
220         cmp/hi  r5, r1
221         bt      7f
222         cmp/hi  r1, r5
223         bt      8b
224
225         mov.l   @(4,r15), r5
226         cmp/hi  r0, r5
227         bt      8b
228 7:
229         cmp/hi  r1, r3
230         bt      9f
231         cmp/hi  r3, r1
232         bt      8b
233         cmp/hi  r0, r2
234         bf      8b
235 9:
236         mov     #1, r2
237         mov     #0, r3
238
239         clrt
240         mov.l   @(woken_seq,r8),r0
241         mov.l   @(woken_seq+4,r8),r1
242         addc    r2, r0
243         addc    r3, r1
244         mov.l   r0,@(woken_seq,r8)
245         mov.l   r1,@(woken_seq+4,r8)
246
247 #if cond_lock != 0
248         DEC (@(cond_lock,r8), r2)
249 #else
250         DEC (@r8, r2)
251 #endif
252         tst     r2, r2
253         bf      10f
254
255 11:
256         /* Remove cancellation handler.  */
257         mov     r15, r4
258         add     #12, r4
259         mov.l   .Lcpop0, r1
260         bsrf    r1
261          mov    #0, r5
262 .Lcpop0b:
263
264         mov     r9, r4
265         mov.l   .Lmlocki0, r1
266         bsrf    r1
267          mov    #0, r5
268 .Lmlocki0b:
269
270         add     #32, r15
271
272         /* We return the result of the mutex_lock operation.  */
273         lds.l   @r15+, pr
274         mov.l   @r15+, r8
275         mov.l   @r15+, r9
276         rts
277          mov.l  @r15+, r12
278
279         .align  2
280 .Lmunlock0:
281         .long   __pthread_mutex_unlock_internal-.Lmunlock0b
282 #ifdef PIC
283 .Lgot0:
284         .long   _GLOBAL_OFFSET_TABLE_
285 .Lccleanup0:
286         .long   __condvar_cleanup@GOTOFF
287 #else
288 .Lccleanup0:
289         .long   __condvar_cleanup
290 #endif
291 .Lccpush0:
292         .long   __pthread_cleanup_push-.Lccpush0b
293 .Lenable0:
294         .long   __pthread_enable_asynccancel-.Lenable0b
295 .Ldisable0:
296         .long   __pthread_disable_asynccancel-.Ldisable0b
297 .Lcpop0:
298         .long   __pthread_cleanup_pop-.Lcpop0b
299 .Lmlocki0:
300         .long   __pthread_mutex_lock_internal-.Lmlocki0b
301
302 1:
303         /* Initial locking failed.  */
304         mov     r8, r5
305 #if cond_lock != 0
306         add     #cond_lock, r5
307 #endif
308         mov.l   .Lmwait0, r1
309         bsrf    r1
310          mov    r2, r4
311 .Lmwait0b:
312         bra     2b
313          nop
314 3:
315         /* Unlock in loop requires waekup.  */
316         mov     r8, r4
317 #if cond_lock != 0
318         add     #cond_lock, r4
319 #endif
320         mov.l   .Lmwake0, r1
321         bsrf    r1
322          nop
323 .Lmwake0b:
324         bra     4b
325          nop
326
327 5:
328         /* Locking in loop failed.  */
329         mov     r8, r5
330 #if cond_lock != 0
331         add     #cond_lock, r5
332 #endif
333         mov.l   .Lmwait1, r1
334         bsrf    r1
335          mov    r2, r4
336 .Lmwait1b:
337         bra     6b
338          nop
339
340 10:
341         /* Unlock after loop requires wakeup.  */
342         mov     r8, r4
343 #if cond_lock != 0
344         add     #cond_lock, r4
345 #endif
346         mov.l   .Lmwake1, r1
347         bsrf    r1
348          nop
349 .Lmwake1b:
350         bra     11b
351          nop
352
353         .align  2
354 .Lmwait0:
355         .long   __lll_mutex_lock_wait-.Lmwait0b
356 .Lmwake0:
357         .long   __lll_mutex_unlock_wake-.Lmwake0b
358 .Lmwait1:
359         .long   __lll_mutex_lock_wait-.Lmwait1b
360 .Lmwake1:
361         .long   __lll_mutex_unlock_wake-.Lmwake1b
362         .size   __pthread_cond_wait, .-__pthread_cond_wait
363 versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
364                   GLIBC_2_3_2)