Update.
[glibc.git] / nptl / sysdeps / unix / sysv / linux / sh / pthread_cond_wait.S
blob2d6b68566888adb925b802bc233ea1bdc9fd4914
1 /* Copyright (C) 2003, 2004 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 <lowlevelcond.h>
22 #include "lowlevel-atomic.h"
24 #define SYS_futex               240
25 #define FUTEX_WAIT              0
26 #define FUTEX_WAKE              1
29         .text
31 /* int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)  */
32         .globl  __pthread_cond_wait
33         .type   __pthread_cond_wait, @function
34         .align  5
35 __pthread_cond_wait:
36 .LSTARTCODE:
37         mov.l   r8, @-r15
38 .Lpush_r8:
39         mov.l   r9, @-r15
40 .Lpush_r9:
41         mov.l   r10, @-r15
42 .Lpush_r10:
43         mov.l   r11, @-r15
44 .Lpush_r11:
45         mov.l   r12, @-r15
46 .Lpush_r12:
47         sts.l   pr, @-r15
48 .Lpush_pr:
49         add     #-48, r15
50 .Lalloc:
51         mov     r4, r8
52         mov     r5, r9
53 #ifdef PIC
54         mova    .Lgot0, r0
55         mov.l   .Lgot0, r12
56         add     r0, r12
57 #endif
59         /* Get internal lock.  */
60         mov     #0, r3
61         mov     #1, r4
62 #if cond_lock != 0
63         CMPXCHG (r3, @(cond_lock,r8), r4, r2)
64 #else
65         CMPXCHG (r3, @r8, r4, r2)
66 #endif
67         bt      2f
68         bra     1f
69          nop
70 #ifdef PIC
71         .align  2
72 .Lgot0:
73         .long   _GLOBAL_OFFSET_TABLE_
74 #endif
76 2:      
77         /* Store the reference to the mutex.  If there is already a
78            different value in there this is a bad user bug.  */
79         mov.l   @(dep_mutex,r8),r0
80         cmp/eq  #-1, r0
81         bt      15f
82         mov.l   r9, @(dep_mutex,r8)
84 15:     
85         /* Unlock the mutex.  */
86         mov.l   .Lmunlock0, r1
87         mov     #0, r5
88         bsrf    r1
89          mov    r9, r4
90 .Lmunlock0b:
92         tst     r0, r0
93         bt      0f
94         bra     12f
95          nop
97         mov     #1, r2
98         mov     #0, r3
100         clrt
101         mov.l   @(total_seq,r8),r0
102         mov.l   @(total_seq+4,r8),r1
103         addc    r2, r0
104         addc    r3, r1
105         mov.l   r0,@(total_seq,r8)
106         mov.l   r1,@(total_seq+4,r8)
107         mov.l   @(cond_futex,r8),r0
108         add     r2, r0
109         mov.l   r0,@(cond_futex,r8)
110         mov     #(1 << clock_bits), r2
111         mov.l   @(cond_nwaiters,r8), r0
112         add     r2, r0
113         mov.l   r0, @(cond_nwaiters,r8)
115         /* Get and store current wakeup_seq value.  */
116         mov.l   @(wakeup_seq,r8), r10
117         mov.l   @(wakeup_seq+4,r8), r11
118         mov.l   @(broadcast_seq,r8), r0
119         mov.l   r0, @(4,r15)
122         mov.l   @(cond_futex,r8),r0
123         mov.l   r0, @(8,r15)
125         /* Unlock.  */
126 #if cond_lock != 0
127         DEC (@(cond_lock,r8), r2)
128 #else
129         DEC (@r8, r2)
130 #endif
131         tst     r2, r2
132         bf      3f
134 .LcleanupSTART:
135         mov.l   .Lenable0, r1
136         bsrf    r1
137          nop
138 .Lenable0b:
139         mov.l   r0, @r15
141         mov     #0, r7
142         mov     #FUTEX_WAIT, r5
143         mov.l   @(8,r15), r6
144         mov     r8, r4
145         add     #cond_futex, r4
146         mov     #SYS_futex, r3
147         extu.b  r3, r3
148         trapa   #0x14
149         SYSCALL_INST_PAD
151         mov.l   .Ldisable0, r1
152         bsrf    r1
153          mov.l  @r15, r4
154 .Ldisable0b:    
155 .LcleanupEND:
157         /* Lock.  */
158         mov     #0, r3
159         mov     #1, r4
160 #if cond_lock != 0
161         CMPXCHG (r3, @(cond_lock,r8), r4, r2)
162 #else
163         CMPXCHG (r3, @r8, r4, r2)
164 #endif
165         bf      5f
167         mov.l   @(broadcast_seq,r8), r0
168         mov.l   @(4,r15), r1
169         cmp/eq  r0, r1
170         bf      16f
172         mov.l   @(woken_seq,r8), r0
173         mov.l   @(woken_seq+4,r8), r1
175         mov.l   @(wakeup_seq,r8), r2
176         mov.l   @(wakeup_seq+4,r8), r3
178         cmp/eq  r3, r11
179         bf      7f
180         cmp/eq  r2, r10
181         bt      8b
183         cmp/eq  r1, r3
184         bf      9f
185         cmp/eq  r0, r2
186         bt      8b
188         mov     #1, r2
189         mov     #0, r3
191         clrt
192         mov.l   @(woken_seq,r8),r0
193         mov.l   @(woken_seq+4,r8),r1
194         addc    r2, r0
195         addc    r3, r1
196         mov.l   r0,@(woken_seq,r8)
197         mov.l   r1,@(woken_seq+4,r8)
200         mov     #(1 << clock_bits), r2
201         mov.l   @(cond_nwaiters,r8),r0
202         sub     r2, r0
203         mov.l   r0,@(cond_nwaiters,r8)
205         /* Wake up a thread which wants to destroy the condvar object.  */
206         mov.l   @(total_seq,r8),r0
207         mov.l   @(total_seq+4,r8),r1
208         and     r1, r0
209         not     r0, r0
210         cmp/eq  #0, r0
211         bf/s    17f
212          mov    #((1 << clock_bits) - 1), r1
213         not     r1, r1
214         mov.l   @(cond_nwaiters,r8),r0
215         tst     r1, r0
216         bf      17f
218         mov     r8, r4
219         add     #cond_nwaiters, r4
220         mov     #FUTEX_WAKE, r5
221         mov     #1, r6
222         mov     #0, r7
223         mov     #SYS_futex, r3
224         extu.b  r3, r3
225         trapa   #0x14
226         SYSCALL_INST_PAD
229 #if cond_lock != 0
230         DEC (@(cond_lock,r8), r2)
231 #else
232         DEC (@r8, r2)
233 #endif
234         tst     r2, r2
235         bf      10f
238         mov.l   .Lmlocki0, r1
239         bsrf    r1
240          mov    r9, r4
241 .Lmlocki0b:
242         /* We return the result of the mutex_lock operation.  */
245         add     #48, r15
246         lds.l   @r15+, pr
247         mov.l   @r15+, r12
248         mov.l   @r15+, r11
249         mov.l   @r15+, r10
250         mov.l   @r15+, r9
251         rts
252          mov.l  @r15+, r8
254         .align  2
255 .Lmunlock0:
256         .long   __pthread_mutex_unlock_usercnt-.Lmunlock0b
257 .Lenable0:
258         .long   __pthread_enable_asynccancel-.Lenable0b
259 .Ldisable0:
260         .long   __pthread_disable_asynccancel-.Ldisable0b
261 .Lmlocki0:
262         .long   __pthread_mutex_cond_lock-.Lmlocki0b
265         /* Initial locking failed.  */
266         mov     r8, r5
267 #if cond_lock != 0
268         add     #cond_lock, r5
269 #endif
270         mov.l   .Lmwait0, r1
271         bsrf    r1
272          mov    r2, r4
273 .Lmwait0b:
274         bra     2b
275          nop
277         /* Unlock in loop requires waekup.  */
278         mov     r8, r4
279 #if cond_lock != 0
280         add     #cond_lock, r4
281 #endif
282         mov.l   .Lmwake0, r1
283         bsrf    r1
284          nop
285 .Lmwake0b:
286         bra     4b
287          nop
290         /* Locking in loop failed.  */
291         mov     r8, r5
292 #if cond_lock != 0
293         add     #cond_lock, r5
294 #endif
295         mov.l   .Lmwait1, r1
296         bsrf    r1
297          mov    r2, r4
298 .Lmwait1b:
299         bra     6b
300          nop
303         /* Unlock after loop requires wakeup.  */
304         mov     r8, r4
305 #if cond_lock != 0
306         add     #cond_lock, r4
307 #endif
308         mov.l   .Lmwake1, r1
309         bsrf    r1
310          nop
311 .Lmwake1b:
312         bra     11b
313          nop
316         /* The initial unlocking of the mutex failed.  */
317         mov.l   r0, @(12,r15)
318 #if cond_lock != 0
319         DEC (@(cond_lock,r8), r2)
320 #else
321         DEC (@r8, r2)
322 #endif
323         tst     r2, r2
324         bf      13f
326         mov     r8, r4
327 #if cond_lock != 0
328         add     #cond_lock, r4
329 #endif
330         mov.l   .Lmwake2, r1
331         bsrf    r1
332          nop
333 .Lmwake2b:
336         bra     14b
337          mov.l  @(12,r15), r0
339         .align  2
340 .Lmwait0:
341         .long   __lll_mutex_lock_wait-.Lmwait0b
342 .Lmwake0:
343         .long   __lll_mutex_unlock_wake-.Lmwake0b
344 .Lmwait1:
345         .long   __lll_mutex_lock_wait-.Lmwait1b
346 .Lmwake1:
347         .long   __lll_mutex_unlock_wake-.Lmwake1b
348 .Lmwake2:
349         .long   __lll_mutex_unlock_wake-.Lmwake2b
350         .size   __pthread_cond_wait, .-__pthread_cond_wait
351 versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
352                   GLIBC_2_3_2)
355         .type   __condvar_w_cleanup, @function
356 __condvar_w_cleanup:
357         mov     r4, r11
359         /* Get internal lock.  */
360         mov     #0, r3
361         mov     #1, r4
362 #if cond_lock != 0
363         CMPXCHG (r3, @(cond_lock,r8), r4, r2)
364 #else
365         CMPXCHG (r3, @r8, r4, r2)
366 #endif
367         bt      1f
368          nop
370         mov     r8, r5
371 #if cond_lock != 0
372         add     #cond_lock, r5
373 #endif
374         mov.l   .Lmwait3, r1
375         bsrf    r1
376          mov    r2, r4
377 .Lmwait3b:
380         mov.l   @(broadcast_seq,r8), r0
381         mov.l   @(4,r15), r1
382         cmp/eq  r0, r1
383         bf      3f
385         mov     #1, r2
386         mov     #0, r3
388         clrt
389         mov.l   @(wakeup_seq,r8),r0
390         mov.l   @(wakeup_seq+4,r8),r1
391         addc    r2, r0
392         addc    r3, r1
393         mov.l   r0,@(wakeup_seq,r8)
394         mov.l   r1,@(wakeup_seq+4,r8)
395         mov.l   @(cond_futex,r8),r0
396         add     r2, r0
397         mov.l   r0,@(cond_futex,r8)
399         clrt
400         mov.l   @(woken_seq,r8),r0
401         mov.l   @(woken_seq+4,r8),r1
402         addc    r2, r0
403         addc    r3, r1
404         mov.l   r0,@(woken_seq,r8)
405         mov.l   r1,@(woken_seq+4,r8)
408         mov     #(1 << clock_bits), r2
409         mov.l   @(cond_nwaiters,r8),r0
410         sub     r2, r0
411         mov.l   r0,@(cond_nwaiters,r8)
413         /* Wake up a thread which wants to destroy the condvar object.  */
414         mov     #0, r10
415         mov.l   @(total_seq,r8),r0
416         mov.l   @(total_seq+4,r8),r1
417         and     r1, r0
418         not     r0, r0
419         cmp/eq  #0, r0
420         bf/s    4f
421          mov    #((1 << clock_bits) - 1), r1
422         not     r1, r1
423         mov.l   @(cond_nwaiters,r8),r0
424         tst     r1, r0
425         bf      4f
427         mov     r8, r4
428         add     #cond_nwaiters, r4
429         mov     #FUTEX_WAKE, r5
430         mov     #1, r6
431         mov     #0, r7
432         mov     #SYS_futex, r3
433         extu.b  r3, r3
434         trapa   #0x14
435         SYSCALL_INST_PAD
436         mov     #1, r10
439 #if cond_lock != 0
440         DEC (@(cond_lock,r8), r2)
441 #else
442         DEC (@r8, r2)
443 #endif
444         tst     r2, r2
445         bt      2f
447         mov     r8, r4
448 #if cond_lock != 0
449         add     #cond_lock, r4
450 #endif
451         mov.l   .Lmwake3, r1
452         bsrf    r1
453          nop
454 .Lmwake3b:
457         /* Wake up all waiters to make sure no signal gets lost.  */
458         tst     r10, r10
459         bf/s    5f
460          mov    r8, r4
461         add     #cond_futex, r4
462         mov     #FUTEX_WAKE, r5
463         mov     #-1, r6
464         shlr    r6              /* r6 = 0x7fffffff */
465         mov     #0, r7
466         mov     #SYS_futex, r3
467         extu.b  r3, r3
468         trapa   #0x14
469         SYSCALL_INST_PAD
472         mov.l   .Lmlocki3, r1
473         bsrf    r1
474          mov     r9, r4
475 .Lmlocki3b:
477 .LcallUR:
478         mov.l   .Lresume, r1
479 #ifdef PIC
480         add     r12, r1
481 #endif
482         jsr     @r1
483          mov    r11, r4
484         sleep
486         .align  2
487 .Lmwait3:
488         .long   __lll_mutex_lock_wait-.Lmwait3b
489 .Lmwake3:
490         .long   __lll_mutex_unlock_wake-.Lmwake3b
491 .Lmlocki3:
492         .long   __pthread_mutex_cond_lock-.Lmlocki3b
493 .Lresume:
494 #ifdef PIC
495         .long   _Unwind_Resume@GOTOFF
496 #else
497         .long   _Unwind_Resume
498 #endif
499 .LENDCODE:
500         .size   __condvar_w_cleanup, .-__condvar_w_cleanup
503         .section .gcc_except_table,"a",@progbits
504 .LexceptSTART:
505         .byte   0xff                            ! @LPStart format (omit)
506         .byte   0xff                            ! @TType format (omit)
507         .byte   0x0b                            ! call-site format
508                                                 ! DW_EH_PE_sdata4
509         .uleb128 .Lcstend-.Lcstbegin
510 .Lcstbegin:
511         .ualong .LcleanupSTART-.LSTARTCODE
512         .ualong .LcleanupEND-.LcleanupSTART
513         .ualong __condvar_w_cleanup-.LSTARTCODE
514         .uleb128  0
515         .ualong .LcallUR-.LSTARTCODE
516         .ualong .LENDCODE-.LcallUR
517         .ualong 0
518         .uleb128  0
519 .Lcstend:
521         .section .eh_frame,"a",@progbits
522 .LSTARTFRAME:
523         .ualong .LENDCIE-.LSTARTCIE             ! Length of the CIE.
524 .LSTARTCIE:
525         .ualong 0                               ! CIE ID.
526         .byte   1                               ! Version number.
527 #ifdef SHARED
528         .string "zPLR"                          ! NUL-terminated augmentation
529                                                 ! string.
530 #else
531         .string "zPL"                           ! NUL-terminated augmentation
532                                                 ! string.
533 #endif
534         .uleb128 1                              ! Code alignment factor.
535         .sleb128 -4                             ! Data alignment factor.
536         .byte   0x11                            ! Return address register
537                                                 ! column.
538 #ifdef SHARED
539         .uleb128 7                              ! Augmentation value length.
540         .byte   0x9b                            ! Personality: DW_EH_PE_pcrel
541                                                 ! + DW_EH_PE_sdata4
542                                                 ! + DW_EH_PE_indirect
543         .ualong DW.ref.__gcc_personality_v0-.
544         .byte   0x1b                            ! LSDA Encoding: DW_EH_PE_pcrel
545                                                 ! + DW_EH_PE_sdata4.
546         .byte   0x1b                            ! FDE Encoding: DW_EH_PE_pcrel
547                                                 ! + DW_EH_PE_sdata4.
548 #else
549         .uleb128 6                              ! Augmentation value length.
550         .byte   0x0                             ! Personality: absolute
551         .ualong __gcc_personality_v0
552         .byte   0x0                             ! LSDA Encoding: absolute
553 #endif
554         .byte 0x0c                              ! DW_CFA_def_cfa
555         .uleb128 0xf
556         .uleb128 0
557         .align 2
558 .LENDCIE:
560         .ualong .LENDFDE-.LSTARTFDE             ! Length of the FDE.
561 .LSTARTFDE:
562         .ualong .LSTARTFDE-.LSTARTFRAME         ! CIE pointer.
563 #ifdef SHARED
564         .ualong .LSTARTCODE-.                   ! PC-relative start address
565                                                 ! of the code.
566 #else
567         .ualong .LSTARTCODE                     ! Start address of the code.
568 #endif
569         .ualong .LENDCODE-.LSTARTCODE           ! Length of the code.
570         .uleb128 4                              ! Augmentation size
571 #ifdef SHARED
572         .ualong .LexceptSTART-.
573 #else
574         .ualong .LexceptSTART
575 #endif
576         .byte   0x4
577         .ualong .Lpush_r8-.LSTARTCODE
578         .byte   0xe
579         .uleb128 4
580         .byte   0x88
581         .uleb128 1
582         .byte   0x4
583         .ualong .Lpush_r9-.Lpush_r8
584         .byte   0xe
585         .uleb128 8
586         .byte   0x89
587         .uleb128 2
588         .byte   0x4
589         .ualong .Lpush_r10-.Lpush_r9
590         .byte   0xe
591         .uleb128 12
592         .byte   0x8a
593         .uleb128 3
594         .byte   0x4
595         .ualong .Lpush_r11-.Lpush_r10
596         .byte   0xe
597         .uleb128 16
598         .byte   0x8b
599         .uleb128 4
600         .byte   0x4
601         .ualong .Lpush_r12-.Lpush_r11
602         .byte   0xe
603         .uleb128 20
604         .byte   0x8c
605         .uleb128 5
606         .byte   0x4
607         .ualong .Lpush_pr-.Lpush_r12
608         .byte   0xe
609         .uleb128 24
610         .byte   0x91
611         .uleb128 6
612         .byte   0x4
613         .ualong .Lalloc-.Lpush_pr
614         .byte   0xe
615         .uleb128 72
616         .align  2
617 .LENDFDE:
619 #ifdef SHARED
620         .hidden DW.ref.__gcc_personality_v0
621         .weak   DW.ref.__gcc_personality_v0
622         .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
623         .align 4
624         .type   DW.ref.__gcc_personality_v0, @object
625         .size   DW.ref.__gcc_personality_v0, 4
626 DW.ref.__gcc_personality_v0:
627         .long   __gcc_personality_v0
628 #endif