Replace FSF snail mail address with URLs.
[glibc.git] / nptl / sysdeps / unix / sysv / linux / sh / pthread_cond_wait.S
blobba0d99353af1075d128d5204a66ec3d02bee69cc
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, see
16    <http://www.gnu.org/licenses/>.  */
18 #include <sysdep.h>
19 #include <shlib-compat.h>
20 #include <lowlevellock.h>
21 #include <lowlevelcond.h>
22 #include <tcb-offsets.h>
23 #include <kernel-features.h>
24 #include "lowlevel-atomic.h"
26         .text
28 /* int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)  */
29         .globl  __pthread_cond_wait
30         .type   __pthread_cond_wait, @function
31         .align  5
32 __pthread_cond_wait:
33 .LSTARTCODE:
34         mov.l   r8, @-r15
35 .Lpush_r8:
36         mov.l   r9, @-r15
37 .Lpush_r9:
38         mov.l   r10, @-r15
39 .Lpush_r10:
40         mov.l   r11, @-r15
41 .Lpush_r11:
42         mov.l   r12, @-r15
43 .Lpush_r12:
44         sts.l   pr, @-r15
45 .Lpush_pr:
46         add     #-48, r15
47 .Lalloc:
48         mov     r4, r8
49         mov     r5, r9
50 #ifdef PIC
51         mova    .Lgot0, r0
52         mov.l   .Lgot0, r12
53         add     r0, r12
54 #endif
56         /* Get internal lock.  */
57         mov     #0, r3
58         mov     #1, r4
59 #if cond_lock != 0
60         CMPXCHG (r3, @(cond_lock,r8), r4, r2)
61 #else
62         CMPXCHG (r3, @r8, r4, r2)
63 #endif
64         bt      2f
65         bra     1f
66          nop
67 #ifdef PIC
68         .align  2
69 .Lgot0:
70         .long   _GLOBAL_OFFSET_TABLE_
71 #endif
73 2:      
74         /* Store the reference to the mutex.  If there is already a
75            different value in there this is a bad user bug.  */
76         mov.l   @(dep_mutex,r8),r0
77         cmp/eq  #-1, r0
78         bt      15f
79         mov.l   r9, @(dep_mutex,r8)
81 15:     
82         /* Unlock the mutex.  */
83         mov.l   .Lmunlock0, r1
84         mov     #0, r5
85         bsrf    r1
86          mov    r9, r4
87 .Lmunlock0b:
89         tst     r0, r0
90         bt      0f
91         bra     12f
92          nop
94         mov     #1, r2
95         mov     #0, r3
97         clrt
98         mov.l   @(total_seq,r8),r0
99         mov.l   @(total_seq+4,r8),r1
100         addc    r2, r0
101         addc    r3, r1
102         mov.l   r0,@(total_seq,r8)
103         mov.l   r1,@(total_seq+4,r8)
104         mov.l   @(cond_futex,r8),r0
105         add     r2, r0
106         mov.l   r0,@(cond_futex,r8)
107         mov     #(1 << nwaiters_shift), r2
108         mov.l   @(cond_nwaiters,r8), r0
109         add     r2, r0
110         mov.l   r0, @(cond_nwaiters,r8)
112         /* Get and store current wakeup_seq value.  */
113         mov.l   @(wakeup_seq,r8), r10
114         mov.l   @(wakeup_seq+4,r8), r11
115         mov.l   @(broadcast_seq,r8), r0
116         mov.l   r0, @(4,r15)
119         mov.l   @(cond_futex,r8),r0
120         mov.l   r0, @(8,r15)
122         /* Unlock.  */
123 #if cond_lock != 0
124         DEC (@(cond_lock,r8), r2)
125 #else
126         DEC (@r8, r2)
127 #endif
128         tst     r2, r2
129         bf      3f
131 .LcleanupSTART:
132         mov.l   .Lenable0, r1
133         bsrf    r1
134          nop
135 .Lenable0b:
136         mov.l   r0, @r15
138         mov     #0, r7
139         mov.l   @(dep_mutex,r8), r0
140         cmp/eq  #-1, r0
141         bt/s    99f
142          mov    #FUTEX_WAIT, r5
143 #ifdef __ASSUME_PRIVATE_FUTEX
144         mov     #(FUTEX_WAIT|FUTEX_PRIVATE_FLAG), r5
145         extu.b  r5, r5
146 #else
147         stc     gbr, r1
148         mov.w   .Lpfoff0, r2
149         add     r2, r1
150         mov.l   @r1, r5
151         mov     #FUTEX_WAIT, r0
152         or      r0, r5
153 #endif
154 99:     
155         mov.l   @(8,r15), r6
156         mov     r8, r4
157         add     #cond_futex, r4
158         mov     #SYS_futex, r3
159         extu.b  r3, r3
160         trapa   #0x14
161         SYSCALL_INST_PAD
163         mov.l   .Ldisable0, r1
164         bsrf    r1
165          mov.l  @r15, r4
166 .Ldisable0b:    
167 .LcleanupEND:
169         /* Lock.  */
170         mov     #0, r3
171         mov     #1, r4
172 #if cond_lock != 0
173         CMPXCHG (r3, @(cond_lock,r8), r4, r2)
174 #else
175         CMPXCHG (r3, @r8, r4, r2)
176 #endif
177         bf      5f
179         mov.l   @(broadcast_seq,r8), r0
180         mov.l   @(4,r15), r1
181         cmp/eq  r0, r1
182         bf      16f
184         mov.l   @(woken_seq,r8), r0
185         mov.l   @(woken_seq+4,r8), r1
187         mov.l   @(wakeup_seq,r8), r2
188         mov.l   @(wakeup_seq+4,r8), r3
190         cmp/eq  r3, r11
191         bf      7f
192         cmp/eq  r2, r10
193         bt      8b
195         cmp/eq  r1, r3
196         bf      9f
197         cmp/eq  r0, r2
198         bt      8b
200         mov     #1, r2
201         mov     #0, r3
203         clrt
204         mov.l   @(woken_seq,r8),r0
205         mov.l   @(woken_seq+4,r8),r1
206         addc    r2, r0
207         addc    r3, r1
208         mov.l   r0,@(woken_seq,r8)
209         mov.l   r1,@(woken_seq+4,r8)
212         mov     #(1 << nwaiters_shift), r2
213         mov.l   @(cond_nwaiters,r8),r0
214         sub     r2, r0
215         mov.l   r0,@(cond_nwaiters,r8)
217         /* Wake up a thread which wants to destroy the condvar object.  */
218         mov.l   @(total_seq,r8),r0
219         mov.l   @(total_seq+4,r8),r1
220         and     r1, r0
221         not     r0, r0
222         cmp/eq  #0, r0
223         bf/s    17f
224          mov    #((1 << nwaiters_shift) - 1), r1
225         not     r1, r1
226         mov.l   @(cond_nwaiters,r8),r0
227         tst     r1, r0
228         bf      17f
230         mov     r8, r4
231         add     #cond_nwaiters, r4
232         mov.l   @(dep_mutex,r8), r0
233         cmp/eq  #-1, r0
234         bt/s    99f
235          mov    #FUTEX_WAKE, r5
236 #ifdef __ASSUME_PRIVATE_FUTEX
237         mov     #(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), r5
238         extu.b  r5, r5
239 #else
240         stc     gbr, r1
241         mov.w   .Lpfoff0, r2
242         add     r2, r1
243         mov.l   @r1, r5
244         mov     #FUTEX_WAKE, r0
245         or      r0, r5
246 #endif
247 99:     
248         mov     #1, r6
249         mov     #0, r7
250         mov     #SYS_futex, r3
251         extu.b  r3, r3
252         trapa   #0x14
253         SYSCALL_INST_PAD
256 #if cond_lock != 0
257         DEC (@(cond_lock,r8), r2)
258 #else
259         DEC (@r8, r2)
260 #endif
261         tst     r2, r2
262         bf      10f
265         mov.l   .Lmlocki0, r1
266         bsrf    r1
267          mov    r9, r4
268 .Lmlocki0b:
269         /* We return the result of the mutex_lock operation.  */
272         add     #48, r15
273         lds.l   @r15+, pr
274         mov.l   @r15+, r12
275         mov.l   @r15+, r11
276         mov.l   @r15+, r10
277         mov.l   @r15+, r9
278         rts
279          mov.l  @r15+, r8
281 #ifndef __ASSUME_PRIVATE_FUTEX
282 .Lpfoff0:
283         .word   PRIVATE_FUTEX - TLS_PRE_TCB_SIZE
284 #endif
285         .align  2
286 .Lmunlock0:
287         .long   __pthread_mutex_unlock_usercnt-.Lmunlock0b
288 .Lenable0:
289         .long   __pthread_enable_asynccancel-.Lenable0b
290 .Ldisable0:
291         .long   __pthread_disable_asynccancel-.Ldisable0b
292 .Lmlocki0:
293         .long   __pthread_mutex_cond_lock-.Lmlocki0b
296         /* Initial locking failed.  */
297         mov     r8, r5
298 #if cond_lock != 0
299         add     #cond_lock, r5
300 #endif
301         mov.l   @(dep_mutex,r8), r0
302         cmp/eq  #-1, r0
303         bf/s    99f
304          mov    #LLL_PRIVATE, r6
305         mov     #LLL_SHARED, r6
306 99:     
307         extu.b  r6, r6
308         mov.l   .Lwait0, r1
309         bsrf    r1
310          mov    r2, r4
311 .Lwait0b:
312         bra     2b
313          nop
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   @(dep_mutex,r8), r0
321         cmp/eq  #-1, r0
322         bf/s    99f
323          mov    #LLL_PRIVATE, r5
324         mov     #LLL_SHARED, r5
325 99:     
326         mov.l   .Lwake0, r1
327         bsrf    r1
328          extu.b r5, r5
329 .Lwake0b:
330         bra     4b
331          nop
334         /* Locking in loop failed.  */
335         mov     r8, r5
336 #if cond_lock != 0
337         add     #cond_lock, r5
338 #endif
339         mov.l   @(dep_mutex,r8), r0
340         cmp/eq  #-1, r0
341         bf/s    99f
342          mov    #LLL_PRIVATE, r6
343         mov     #LLL_SHARED, r6
344 99:     
345         extu.b  r6, r6
346         mov.l   .Lwait1, r1
347         bsrf    r1
348          mov    r2, r4
349 .Lwait1b:
350         bra     6b
351          nop
354         /* Unlock after loop requires wakeup.  */
355         mov     r8, r4
356 #if cond_lock != 0
357         add     #cond_lock, r4
358 #endif
359         mov.l   @(dep_mutex,r8), r0
360         cmp/eq  #-1, r0
361         bf/s    99f
362          mov    #LLL_PRIVATE, r5
363         mov     #LLL_SHARED, r5
364 99:     
365         mov.l   .Lwake1, r1
366         bsrf    r1
367          extu.b r5, r5
368 .Lwake1b:
369         bra     11b
370          nop
373         /* The initial unlocking of the mutex failed.  */
374         mov.l   r0, @(12,r15)
375 #if cond_lock != 0
376         DEC (@(cond_lock,r8), r2)
377 #else
378         DEC (@r8, r2)
379 #endif
380         tst     r2, r2
381         bf      13f
383         mov     r8, r4
384 #if cond_lock != 0
385         add     #cond_lock, r4
386 #endif
387         mov.l   @(dep_mutex,r8), r0
388         cmp/eq  #-1, r0
389         bf/s    99f
390          mov    #LLL_PRIVATE, r5
391         mov     #LLL_SHARED, r5
392 99:     
393         mov.l   .Lwake2, r1
394         bsrf    r1
395          extu.b r5, r5
396 .Lwake2b:
399         bra     14b
400          mov.l  @(12,r15), r0
402         .align  2
403 .Lwait0:
404         .long   __lll_lock_wait-.Lwait0b
405 .Lwake0:
406         .long   __lll_unlock_wake-.Lwake0b
407 .Lwait1:
408         .long   __lll_lock_wait-.Lwait1b
409 .Lwake1:
410         .long   __lll_unlock_wake-.Lwake1b
411 .Lwake2:
412         .long   __lll_unlock_wake-.Lwake2b
413         .size   __pthread_cond_wait, .-__pthread_cond_wait
414 versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
415                   GLIBC_2_3_2)
418         .type   __condvar_w_cleanup, @function
419 __condvar_w_cleanup:
420         mov     r4, r11
422         /* Get internal lock.  */
423         mov     #0, r3
424         mov     #1, r4
425 #if cond_lock != 0
426         CMPXCHG (r3, @(cond_lock,r8), r4, r2)
427 #else
428         CMPXCHG (r3, @r8, r4, r2)
429 #endif
430         bt      1f
431          nop
433         mov     r8, r5
434 #if cond_lock != 0
435         add     #cond_lock, r5
436 #endif
437         mov.l   @(dep_mutex,r8), r0
438         cmp/eq  #-1, r0
439         bf/s    99f
440          mov    #LLL_PRIVATE, r6
441         mov     #LLL_SHARED, r6
442 99:     
443         extu.b  r6, r6
444         mov.l   .Lwait3, r1
445         bsrf    r1
446          mov    r2, r4
447 .Lwait3b:
450         mov.l   @(broadcast_seq,r8), r0
451         mov.l   @(4,r15), r1
452         cmp/eq  r0, r1
453         bf      3f
455         mov     #1, r2
456         mov     #0, r3
458         /* We increment the wakeup_seq counter only if it is lower than
459            total_seq.  If this is not the case the thread was woken and
460            then canceled.  In this case we ignore the signal.  */
461         mov.l   @(total_seq+4,r8), r0
462         mov.l   @(wakeup_seq+4,r8), r1
463         cmp/hi  r1, r0
464         bt/s    6f
465          cmp/hi r0, r1
466         bt      7f
467         mov.l   @(total_seq,r8), r0
468         mov.l   @(wakeup_seq,r8), r1
469         cmp/hs  r0, r1
470         bt      7f
473         clrt
474         mov.l   @(wakeup_seq,r8),r0
475         mov.l   @(wakeup_seq+4,r8),r1
476         addc    r2, r0
477         addc    r3, r1
478         mov.l   r0,@(wakeup_seq,r8)
479         mov.l   r1,@(wakeup_seq+4,r8)
480         mov.l   @(cond_futex,r8),r0
481         add     r2, r0
482         mov.l   r0,@(cond_futex,r8)
485         clrt
486         mov.l   @(woken_seq,r8),r0
487         mov.l   @(woken_seq+4,r8),r1
488         addc    r2, r0
489         addc    r3, r1
490         mov.l   r0,@(woken_seq,r8)
491         mov.l   r1,@(woken_seq+4,r8)
494         mov     #(1 << nwaiters_shift), r2
495         mov.l   @(cond_nwaiters,r8),r0
496         sub     r2, r0
497         mov.l   r0,@(cond_nwaiters,r8)
499         /* Wake up a thread which wants to destroy the condvar object.  */
500         mov     #0, r10
501         mov.l   @(total_seq,r8),r0
502         mov.l   @(total_seq+4,r8),r1
503         and     r1, r0
504         not     r0, r0
505         cmp/eq  #0, r0
506         bf/s    4f
507          mov    #((1 << nwaiters_shift) - 1), r1
508         not     r1, r1
509         mov.l   @(cond_nwaiters,r8),r0
510         tst     r1, r0
511         bf      4f
513         mov     r8, r4
514         add     #cond_nwaiters, r4
515         mov.l   @(dep_mutex,r8), r0
516         cmp/eq  #-1, r0
517         bt/s    99f
518          mov    #FUTEX_WAKE, r5
519 #ifdef __ASSUME_PRIVATE_FUTEX
520         mov     #(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), r5
521         extu.b  r5, r5
522 #else
523         stc     gbr, r1
524         mov.w   .Lpfoff1, r2
525         add     r2, r1
526         mov.l   @r1, r5
527         mov     #FUTEX_WAKE, r0
528         or      r0, r5
529 #endif
530 99:     
531         mov     #1, r6
532         mov     #0, r7
533         mov     #SYS_futex, r3
534         extu.b  r3, r3
535         trapa   #0x14
536         SYSCALL_INST_PAD
537         mov     #1, r10
540 #if cond_lock != 0
541         DEC (@(cond_lock,r8), r2)
542 #else
543         DEC (@r8, r2)
544 #endif
545         tst     r2, r2
546         bt      2f
548         mov     r8, r4
549 #if cond_lock != 0
550         add     #cond_lock, r4
551 #endif
552         mov.l   @(dep_mutex,r8), r0
553         cmp/eq  #-1, r0
554         bf/s    99f
555          mov    #LLL_PRIVATE, r5
556         mov     #LLL_SHARED, r5
557 99:     
558         mov.l   .Lwake3, r1
559         bsrf    r1
560          extu.b r5, r5
561 .Lwake3b:
564         /* Wake up all waiters to make sure no signal gets lost.  */
565         tst     r10, r10
566         bf/s    5f
567          mov    r8, r4
568         add     #cond_futex, r4
569         mov.l   @(dep_mutex,r8), r0
570         cmp/eq  #-1, r0
571         bt/s    99f
572          mov    #FUTEX_WAKE, r5
573 #ifdef __ASSUME_PRIVATE_FUTEX
574         mov     #(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), r5
575         extu.b  r5, r5
576 #else
577         stc     gbr, r1
578         mov.w   .Lpfoff1, r2
579         add     r2, r1
580         mov.l   @r1, r5
581         mov     #FUTEX_WAKE, r0
582         or      r0, r5
583 #endif
584 99:     
585         mov     #-1, r6
586         shlr    r6              /* r6 = 0x7fffffff */
587         mov     #0, r7
588         mov     #SYS_futex, r3
589         extu.b  r3, r3
590         trapa   #0x14
591         SYSCALL_INST_PAD
594         mov.l   .Lmlocki3, r1
595         bsrf    r1
596          mov     r9, r4
597 .Lmlocki3b:
599 .LcallUR:
600         mov.l   .Lresume, r1
601 #ifdef PIC
602         add     r12, r1
603 #endif
604         jsr     @r1
605          mov    r11, r4
606         sleep
608 #ifndef __ASSUME_PRIVATE_FUTEX
609 .Lpfoff1:
610         .word   PRIVATE_FUTEX - TLS_PRE_TCB_SIZE
611 #endif
612         .align  2
613 .Lwait3:
614         .long   __lll_lock_wait-.Lwait3b
615 .Lwake3:
616         .long   __lll_unlock_wake-.Lwake3b
617 .Lmlocki3:
618         .long   __pthread_mutex_cond_lock-.Lmlocki3b
619 .Lresume:
620 #ifdef PIC
621         .long   _Unwind_Resume@GOTOFF
622 #else
623         .long   _Unwind_Resume
624 #endif
625 .LENDCODE:
626         .size   __condvar_w_cleanup, .-__condvar_w_cleanup
629         .section .gcc_except_table,"a",@progbits
630 .LexceptSTART:
631         .byte   0xff                            ! @LPStart format (omit)
632         .byte   0xff                            ! @TType format (omit)
633         .byte   0x0b                            ! call-site format
634                                                 ! DW_EH_PE_sdata4
635         .uleb128 .Lcstend-.Lcstbegin
636 .Lcstbegin:
637         .ualong .LcleanupSTART-.LSTARTCODE
638         .ualong .LcleanupEND-.LcleanupSTART
639         .ualong __condvar_w_cleanup-.LSTARTCODE
640         .uleb128  0
641         .ualong .LcallUR-.LSTARTCODE
642         .ualong .LENDCODE-.LcallUR
643         .ualong 0
644         .uleb128  0
645 .Lcstend:
647         .section .eh_frame,"a",@progbits
648 .LSTARTFRAME:
649         .ualong .LENDCIE-.LSTARTCIE             ! Length of the CIE.
650 .LSTARTCIE:
651         .ualong 0                               ! CIE ID.
652         .byte   1                               ! Version number.
653 #ifdef SHARED
654         .string "zPLR"                          ! NUL-terminated augmentation
655                                                 ! string.
656 #else
657         .string "zPL"                           ! NUL-terminated augmentation
658                                                 ! string.
659 #endif
660         .uleb128 1                              ! Code alignment factor.
661         .sleb128 -4                             ! Data alignment factor.
662         .byte   0x11                            ! Return address register
663                                                 ! column.
664 #ifdef SHARED
665         .uleb128 7                              ! Augmentation value length.
666         .byte   0x9b                            ! Personality: DW_EH_PE_pcrel
667                                                 ! + DW_EH_PE_sdata4
668                                                 ! + DW_EH_PE_indirect
669         .ualong DW.ref.__gcc_personality_v0-.
670         .byte   0x1b                            ! LSDA Encoding: DW_EH_PE_pcrel
671                                                 ! + DW_EH_PE_sdata4.
672         .byte   0x1b                            ! FDE Encoding: DW_EH_PE_pcrel
673                                                 ! + DW_EH_PE_sdata4.
674 #else
675         .uleb128 6                              ! Augmentation value length.
676         .byte   0x0                             ! Personality: absolute
677         .ualong __gcc_personality_v0
678         .byte   0x0                             ! LSDA Encoding: absolute
679 #endif
680         .byte 0x0c                              ! DW_CFA_def_cfa
681         .uleb128 0xf
682         .uleb128 0
683         .align 2
684 .LENDCIE:
686         .ualong .LENDFDE-.LSTARTFDE             ! Length of the FDE.
687 .LSTARTFDE:
688         .ualong .LSTARTFDE-.LSTARTFRAME         ! CIE pointer.
689 #ifdef SHARED
690         .ualong .LSTARTCODE-.                   ! PC-relative start address
691                                                 ! of the code.
692 #else
693         .ualong .LSTARTCODE                     ! Start address of the code.
694 #endif
695         .ualong .LENDCODE-.LSTARTCODE           ! Length of the code.
696         .uleb128 4                              ! Augmentation size
697 #ifdef SHARED
698         .ualong .LexceptSTART-.
699 #else
700         .ualong .LexceptSTART
701 #endif
702         .byte   0x4
703         .ualong .Lpush_r8-.LSTARTCODE
704         .byte   0xe
705         .uleb128 4
706         .byte   0x88
707         .uleb128 1
708         .byte   0x4
709         .ualong .Lpush_r9-.Lpush_r8
710         .byte   0xe
711         .uleb128 8
712         .byte   0x89
713         .uleb128 2
714         .byte   0x4
715         .ualong .Lpush_r10-.Lpush_r9
716         .byte   0xe
717         .uleb128 12
718         .byte   0x8a
719         .uleb128 3
720         .byte   0x4
721         .ualong .Lpush_r11-.Lpush_r10
722         .byte   0xe
723         .uleb128 16
724         .byte   0x8b
725         .uleb128 4
726         .byte   0x4
727         .ualong .Lpush_r12-.Lpush_r11
728         .byte   0xe
729         .uleb128 20
730         .byte   0x8c
731         .uleb128 5
732         .byte   0x4
733         .ualong .Lpush_pr-.Lpush_r12
734         .byte   0xe
735         .uleb128 24
736         .byte   0x91
737         .uleb128 6
738         .byte   0x4
739         .ualong .Lalloc-.Lpush_pr
740         .byte   0xe
741         .uleb128 72
742         .align  2
743 .LENDFDE:
745 #ifdef SHARED
746         .hidden DW.ref.__gcc_personality_v0
747         .weak   DW.ref.__gcc_personality_v0
748         .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
749         .align 4
750         .type   DW.ref.__gcc_personality_v0, @object
751         .size   DW.ref.__gcc_personality_v0, 4
752 DW.ref.__gcc_personality_v0:
753         .long   __gcc_personality_v0
754 #endif