Update copyright notices with scripts/update-copyrights
[glibc.git] / nptl / sysdeps / unix / sysv / linux / sh / pthread_cond_wait.S
blobad01966fc6fd4bf79316e9f9187dce1f29bb9241
1 /* Copyright (C) 2003-2014 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         cfi_startproc
33 __pthread_cond_wait:
34 .LSTARTCODE:
35 #ifdef SHARED
36         cfi_personality(DW_EH_PE_pcrel | DW_EH_PE_sdata4 | DW_EH_PE_indirect,
37                         DW.ref.__gcc_personality_v0)
38         cfi_lsda(DW_EH_PE_pcrel | DW_EH_PE_sdata4, .LexceptSTART)
39 #else
40         cfi_personality(DW_EH_PE_absptr, __gcc_personality_v0)
41         cfi_lsda(DW_EH_PE_absptr, .LexceptSTART)
42 #endif
43         mov.l   r8, @-r15
44         cfi_adjust_cfa_offset (4)
45         cfi_rel_offset (r8, 0)
46         mov.l   r9, @-r15
47         cfi_adjust_cfa_offset (4)
48         cfi_rel_offset (r9, 0)
49         mov.l   r10, @-r15
50         cfi_adjust_cfa_offset (4)
51         cfi_rel_offset (r10, 0)
52         mov.l   r11, @-r15
53         cfi_adjust_cfa_offset (4)
54         cfi_rel_offset (r11, 0)
55         mov.l   r12, @-r15
56         cfi_adjust_cfa_offset (4)
57         cfi_rel_offset (r12, 0)
58         sts.l   pr, @-r15
59         cfi_adjust_cfa_offset (4)
60         cfi_rel_offset (pr, 0)
61         add     #-48, r15
62         cfi_adjust_cfa_offset (48)
64         mov     r4, r8
65         mov     r5, r9
66 #ifdef PIC
67         mova    .Lgot0, r0
68         mov.l   .Lgot0, r12
69         add     r0, r12
70 #endif
72         /* Get internal lock.  */
73         mov     #0, r3
74         mov     #1, r4
75 #if cond_lock != 0
76         CMPXCHG (r3, @(cond_lock,r8), r4, r2)
77 #else
78         CMPXCHG (r3, @r8, r4, r2)
79 #endif
80         bt      2f
81         bra     1f
82          nop
83 #ifdef PIC
84         .align  2
85 .Lgot0:
86         .long   _GLOBAL_OFFSET_TABLE_
87 #endif
90         /* Store the reference to the mutex.  If there is already a
91            different value in there this is a bad user bug.  */
92         mov.l   @(dep_mutex,r8),r0
93         cmp/eq  #-1, r0
94         bt      15f
95         mov.l   r9, @(dep_mutex,r8)
97 15:
98         /* Unlock the mutex.  */
99         mov.l   .Lmunlock0, r1
100         mov     #0, r5
101         bsrf    r1
102          mov    r9, r4
103 .Lmunlock0b:
105         tst     r0, r0
106         bt      0f
107         bra     12f
108          nop
110         mov     #1, r2
111         mov     #0, r3
113         clrt
114         mov.l   @(total_seq,r8),r0
115         mov.l   @(total_seq+4,r8),r1
116         addc    r2, r0
117         addc    r3, r1
118         mov.l   r0,@(total_seq,r8)
119         mov.l   r1,@(total_seq+4,r8)
120         mov.l   @(cond_futex,r8),r0
121         add     r2, r0
122         mov.l   r0,@(cond_futex,r8)
123         mov     #(1 << nwaiters_shift), r2
124         mov.l   @(cond_nwaiters,r8), r0
125         add     r2, r0
126         mov.l   r0, @(cond_nwaiters,r8)
128         /* Get and store current wakeup_seq value.  */
129         mov.l   @(wakeup_seq,r8), r10
130         mov.l   @(wakeup_seq+4,r8), r11
131         mov.l   @(broadcast_seq,r8), r0
132         mov.l   r0, @(4,r15)
135         mov.l   @(cond_futex,r8),r0
136         mov.l   r0, @(8,r15)
138         /* Unlock.  */
139 #if cond_lock != 0
140         DEC (@(cond_lock,r8), r2)
141 #else
142         DEC (@r8, r2)
143 #endif
144         tst     r2, r2
145         bf      3f
147 .LcleanupSTART:
148         mov.l   .Lenable0, r1
149         bsrf    r1
150          nop
151 .Lenable0b:
152         mov.l   r0, @r15
154         mov     #0, r7
155         mov.l   @(dep_mutex,r8), r0
156         cmp/eq  #-1, r0
157         bt/s    99f
158          mov    #FUTEX_WAIT, r5
159 #ifdef __ASSUME_PRIVATE_FUTEX
160         mov     #(FUTEX_WAIT|FUTEX_PRIVATE_FLAG), r5
161         extu.b  r5, r5
162 #else
163         stc     gbr, r1
164         mov.w   .Lpfoff0, r2
165         add     r2, r1
166         mov.l   @r1, r5
167         mov     #FUTEX_WAIT, r0
168         or      r0, r5
169 #endif
171         mov.l   @(8,r15), r6
172         mov     r8, r4
173         add     #cond_futex, r4
174         mov     #SYS_futex, r3
175         extu.b  r3, r3
176         trapa   #0x14
177         SYSCALL_INST_PAD
179         mov.l   .Ldisable0, r1
180         bsrf    r1
181          mov.l  @r15, r4
182 .Ldisable0b:
183 .LcleanupEND:
185         /* Lock.  */
186         mov     #0, r3
187         mov     #1, r4
188 #if cond_lock != 0
189         CMPXCHG (r3, @(cond_lock,r8), r4, r2)
190 #else
191         CMPXCHG (r3, @r8, r4, r2)
192 #endif
193         bf      5f
195         mov.l   @(broadcast_seq,r8), r0
196         mov.l   @(4,r15), r1
197         cmp/eq  r0, r1
198         bf      16f
200         mov.l   @(woken_seq,r8), r0
201         mov.l   @(woken_seq+4,r8), r1
203         mov.l   @(wakeup_seq,r8), r2
204         mov.l   @(wakeup_seq+4,r8), r3
206         cmp/eq  r3, r11
207         bf      7f
208         cmp/eq  r2, r10
209         bt      8b
211         cmp/eq  r1, r3
212         bf      9f
213         cmp/eq  r0, r2
214         bt      8b
216         mov     #1, r2
217         mov     #0, r3
219         clrt
220         mov.l   @(woken_seq,r8),r0
221         mov.l   @(woken_seq+4,r8),r1
222         addc    r2, r0
223         addc    r3, r1
224         mov.l   r0,@(woken_seq,r8)
225         mov.l   r1,@(woken_seq+4,r8)
228         mov     #(1 << nwaiters_shift), r2
229         mov.l   @(cond_nwaiters,r8),r0
230         sub     r2, r0
231         mov.l   r0,@(cond_nwaiters,r8)
233         /* Wake up a thread which wants to destroy the condvar object.  */
234         mov.l   @(total_seq,r8),r0
235         mov.l   @(total_seq+4,r8),r1
236         and     r1, r0
237         not     r0, r0
238         cmp/eq  #0, r0
239         bf/s    17f
240          mov    #((1 << nwaiters_shift) - 1), r1
241         not     r1, r1
242         mov.l   @(cond_nwaiters,r8),r0
243         tst     r1, r0
244         bf      17f
246         mov     r8, r4
247         add     #cond_nwaiters, r4
248         mov.l   @(dep_mutex,r8), r0
249         cmp/eq  #-1, r0
250         bt/s    99f
251          mov    #FUTEX_WAKE, r5
252 #ifdef __ASSUME_PRIVATE_FUTEX
253         mov     #(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), r5
254         extu.b  r5, r5
255 #else
256         stc     gbr, r1
257         mov.w   .Lpfoff0, r2
258         add     r2, r1
259         mov.l   @r1, r5
260         mov     #FUTEX_WAKE, r0
261         or      r0, r5
262 #endif
264         mov     #1, r6
265         mov     #0, r7
266         mov     #SYS_futex, r3
267         extu.b  r3, r3
268         trapa   #0x14
269         SYSCALL_INST_PAD
272 #if cond_lock != 0
273         DEC (@(cond_lock,r8), r2)
274 #else
275         DEC (@r8, r2)
276 #endif
277         tst     r2, r2
278         bf      10f
281         mov.l   .Lmlocki0, r1
282         bsrf    r1
283          mov    r9, r4
284 .Lmlocki0b:
285         /* We return the result of the mutex_lock operation.  */
288         cfi_remember_state
289         add     #48, r15
290         cfi_adjust_cfa_offset (-48)
291         lds.l   @r15+, pr
292         cfi_adjust_cfa_offset (-4)
293         cfi_restore (pr)
294         mov.l   @r15+, r12
295         cfi_adjust_cfa_offset (-4)
296         cfi_restore (r12)
297         mov.l   @r15+, r11
298         cfi_adjust_cfa_offset (-4)
299         cfi_restore (r11)
300         mov.l   @r15+, r10
301         cfi_adjust_cfa_offset (-4)
302         cfi_restore (r10)
303         mov.l   @r15+, r9
304         cfi_adjust_cfa_offset (-4)
305         cfi_restore (r9)
306         rts
307          mov.l  @r15+, r8
308         /* Omit CFI for restore in delay slot.  */
309         cfi_restore_state
311 #ifndef __ASSUME_PRIVATE_FUTEX
312 .Lpfoff0:
313         .word   PRIVATE_FUTEX - TLS_PRE_TCB_SIZE
314 #endif
315         .align  2
316 .Lmunlock0:
317         .long   __pthread_mutex_unlock_usercnt-.Lmunlock0b
318 .Lenable0:
319         .long   __pthread_enable_asynccancel-.Lenable0b
320 .Ldisable0:
321         .long   __pthread_disable_asynccancel-.Ldisable0b
322 .Lmlocki0:
323         .long   __pthread_mutex_cond_lock-.Lmlocki0b
326         /* Initial locking failed.  */
327         mov     r8, r5
328 #if cond_lock != 0
329         add     #cond_lock, r5
330 #endif
331         mov.l   @(dep_mutex,r8), r0
332         cmp/eq  #-1, r0
333         bf/s    99f
334          mov    #LLL_PRIVATE, r6
335         mov     #LLL_SHARED, r6
337         extu.b  r6, r6
338         mov.l   .Lwait0, r1
339         bsrf    r1
340          mov    r2, r4
341 .Lwait0b:
342         bra     2b
343          nop
345         /* Unlock in loop requires waekup.  */
346         mov     r8, r4
347 #if cond_lock != 0
348         add     #cond_lock, r4
349 #endif
350         mov.l   @(dep_mutex,r8), r0
351         cmp/eq  #-1, r0
352         bf/s    99f
353          mov    #LLL_PRIVATE, r5
354         mov     #LLL_SHARED, r5
356         mov.l   .Lwake0, r1
357         bsrf    r1
358          extu.b r5, r5
359 .Lwake0b:
360         bra     4b
361          nop
364         /* Locking in loop failed.  */
365         mov     r8, r5
366 #if cond_lock != 0
367         add     #cond_lock, r5
368 #endif
369         mov.l   @(dep_mutex,r8), r0
370         cmp/eq  #-1, r0
371         bf/s    99f
372          mov    #LLL_PRIVATE, r6
373         mov     #LLL_SHARED, r6
375         extu.b  r6, r6
376         mov.l   .Lwait1, r1
377         bsrf    r1
378          mov    r2, r4
379 .Lwait1b:
380         bra     6b
381          nop
384         /* Unlock after loop requires wakeup.  */
385         mov     r8, r4
386 #if cond_lock != 0
387         add     #cond_lock, r4
388 #endif
389         mov.l   @(dep_mutex,r8), r0
390         cmp/eq  #-1, r0
391         bf/s    99f
392          mov    #LLL_PRIVATE, r5
393         mov     #LLL_SHARED, r5
395         mov.l   .Lwake1, r1
396         bsrf    r1
397          extu.b r5, r5
398 .Lwake1b:
399         bra     11b
400          nop
403         /* The initial unlocking of the mutex failed.  */
404         mov.l   r0, @(12,r15)
405 #if cond_lock != 0
406         DEC (@(cond_lock,r8), r2)
407 #else
408         DEC (@r8, r2)
409 #endif
410         tst     r2, r2
411         bf      13f
413         mov     r8, r4
414 #if cond_lock != 0
415         add     #cond_lock, r4
416 #endif
417         mov.l   @(dep_mutex,r8), r0
418         cmp/eq  #-1, r0
419         bf/s    99f
420          mov    #LLL_PRIVATE, r5
421         mov     #LLL_SHARED, r5
423         mov.l   .Lwake2, r1
424         bsrf    r1
425          extu.b r5, r5
426 .Lwake2b:
429         bra     14b
430          mov.l  @(12,r15), r0
432         .align  2
433 .Lwait0:
434         .long   __lll_lock_wait-.Lwait0b
435 .Lwake0:
436         .long   __lll_unlock_wake-.Lwake0b
437 .Lwait1:
438         .long   __lll_lock_wait-.Lwait1b
439 .Lwake1:
440         .long   __lll_unlock_wake-.Lwake1b
441 .Lwake2:
442         .long   __lll_unlock_wake-.Lwake2b
443         .size   __pthread_cond_wait, .-__pthread_cond_wait
444 versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
445                   GLIBC_2_3_2)
448         .type   __condvar_w_cleanup, @function
449 __condvar_w_cleanup:
450         mov     r4, r11
452         /* Get internal lock.  */
453         mov     #0, r3
454         mov     #1, r4
455 #if cond_lock != 0
456         CMPXCHG (r3, @(cond_lock,r8), r4, r2)
457 #else
458         CMPXCHG (r3, @r8, r4, r2)
459 #endif
460         bt      1f
461          nop
463         mov     r8, r5
464 #if cond_lock != 0
465         add     #cond_lock, r5
466 #endif
467         mov.l   @(dep_mutex,r8), r0
468         cmp/eq  #-1, r0
469         bf/s    99f
470          mov    #LLL_PRIVATE, r6
471         mov     #LLL_SHARED, r6
473         extu.b  r6, r6
474         mov.l   .Lwait3, r1
475         bsrf    r1
476          mov    r2, r4
477 .Lwait3b:
480         mov.l   @(broadcast_seq,r8), r0
481         mov.l   @(4,r15), r1
482         cmp/eq  r0, r1
483         bf      3f
485         mov     #1, r2
486         mov     #0, r3
488         /* We increment the wakeup_seq counter only if it is lower than
489            total_seq.  If this is not the case the thread was woken and
490            then canceled.  In this case we ignore the signal.  */
491         mov.l   @(total_seq+4,r8), r0
492         mov.l   @(wakeup_seq+4,r8), r1
493         cmp/hi  r1, r0
494         bt/s    6f
495          cmp/hi r0, r1
496         bt      7f
497         mov.l   @(total_seq,r8), r0
498         mov.l   @(wakeup_seq,r8), r1
499         cmp/hs  r0, r1
500         bt      7f
503         clrt
504         mov.l   @(wakeup_seq,r8),r0
505         mov.l   @(wakeup_seq+4,r8),r1
506         addc    r2, r0
507         addc    r3, r1
508         mov.l   r0,@(wakeup_seq,r8)
509         mov.l   r1,@(wakeup_seq+4,r8)
510         mov.l   @(cond_futex,r8),r0
511         add     r2, r0
512         mov.l   r0,@(cond_futex,r8)
515         clrt
516         mov.l   @(woken_seq,r8),r0
517         mov.l   @(woken_seq+4,r8),r1
518         addc    r2, r0
519         addc    r3, r1
520         mov.l   r0,@(woken_seq,r8)
521         mov.l   r1,@(woken_seq+4,r8)
524         mov     #(1 << nwaiters_shift), r2
525         mov.l   @(cond_nwaiters,r8),r0
526         sub     r2, r0
527         mov.l   r0,@(cond_nwaiters,r8)
529         /* Wake up a thread which wants to destroy the condvar object.  */
530         mov     #0, r10
531         mov.l   @(total_seq,r8),r0
532         mov.l   @(total_seq+4,r8),r1
533         and     r1, r0
534         not     r0, r0
535         cmp/eq  #0, r0
536         bf/s    4f
537          mov    #((1 << nwaiters_shift) - 1), r1
538         not     r1, r1
539         mov.l   @(cond_nwaiters,r8),r0
540         tst     r1, r0
541         bf      4f
543         mov     r8, r4
544         add     #cond_nwaiters, r4
545         mov.l   @(dep_mutex,r8), r0
546         cmp/eq  #-1, r0
547         bt/s    99f
548          mov    #FUTEX_WAKE, r5
549 #ifdef __ASSUME_PRIVATE_FUTEX
550         mov     #(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), r5
551         extu.b  r5, r5
552 #else
553         stc     gbr, r1
554         mov.w   .Lpfoff1, r2
555         add     r2, r1
556         mov.l   @r1, r5
557         mov     #FUTEX_WAKE, r0
558         or      r0, r5
559 #endif
561         mov     #1, r6
562         mov     #0, r7
563         mov     #SYS_futex, r3
564         extu.b  r3, r3
565         trapa   #0x14
566         SYSCALL_INST_PAD
567         mov     #1, r10
570 #if cond_lock != 0
571         DEC (@(cond_lock,r8), r2)
572 #else
573         DEC (@r8, r2)
574 #endif
575         tst     r2, r2
576         bt      2f
578         mov     r8, r4
579 #if cond_lock != 0
580         add     #cond_lock, r4
581 #endif
582         mov.l   @(dep_mutex,r8), r0
583         cmp/eq  #-1, r0
584         bf/s    99f
585          mov    #LLL_PRIVATE, r5
586         mov     #LLL_SHARED, r5
588         mov.l   .Lwake3, r1
589         bsrf    r1
590          extu.b r5, r5
591 .Lwake3b:
594         /* Wake up all waiters to make sure no signal gets lost.  */
595         tst     r10, r10
596         bf/s    5f
597          mov    r8, r4
598         add     #cond_futex, r4
599         mov.l   @(dep_mutex,r8), r0
600         cmp/eq  #-1, r0
601         bt/s    99f
602          mov    #FUTEX_WAKE, r5
603 #ifdef __ASSUME_PRIVATE_FUTEX
604         mov     #(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), r5
605         extu.b  r5, r5
606 #else
607         stc     gbr, r1
608         mov.w   .Lpfoff1, r2
609         add     r2, r1
610         mov.l   @r1, r5
611         mov     #FUTEX_WAKE, r0
612         or      r0, r5
613 #endif
615         mov     #-1, r6
616         shlr    r6              /* r6 = 0x7fffffff */
617         mov     #0, r7
618         mov     #SYS_futex, r3
619         extu.b  r3, r3
620         trapa   #0x14
621         SYSCALL_INST_PAD
624         mov.l   .Lmlocki3, r1
625         bsrf    r1
626          mov     r9, r4
627 .Lmlocki3b:
629 .LcallUR:
630         mov.l   .Lresume, r1
631 #ifdef PIC
632         add     r12, r1
633 #endif
634         jsr     @r1
635          mov    r11, r4
636         sleep
638 #ifndef __ASSUME_PRIVATE_FUTEX
639 .Lpfoff1:
640         .word   PRIVATE_FUTEX - TLS_PRE_TCB_SIZE
641 #endif
642         .align  2
643 .Lwait3:
644         .long   __lll_lock_wait-.Lwait3b
645 .Lwake3:
646         .long   __lll_unlock_wake-.Lwake3b
647 .Lmlocki3:
648         .long   __pthread_mutex_cond_lock-.Lmlocki3b
649 .Lresume:
650 #ifdef PIC
651         .long   _Unwind_Resume@GOTOFF
652 #else
653         .long   _Unwind_Resume
654 #endif
655 .LENDCODE:
656         cfi_endproc
657         .size   __condvar_w_cleanup, .-__condvar_w_cleanup
660         .section .gcc_except_table,"a",@progbits
661 .LexceptSTART:
662         .byte   DW_EH_PE_omit                   ! @LPStart format (omit)
663         .byte   DW_EH_PE_omit                   ! @TType format (omit)
664         .byte   DW_EH_PE_sdata4                 ! call-site format
665         .uleb128 .Lcstend-.Lcstbegin
666 .Lcstbegin:
667         .ualong .LcleanupSTART-.LSTARTCODE
668         .ualong .LcleanupEND-.LcleanupSTART
669         .ualong __condvar_w_cleanup-.LSTARTCODE
670         .uleb128  0
671         .ualong .LcallUR-.LSTARTCODE
672         .ualong .LENDCODE-.LcallUR
673         .ualong 0
674         .uleb128  0
675 .Lcstend:
678 #ifdef SHARED
679         .hidden DW.ref.__gcc_personality_v0
680         .weak   DW.ref.__gcc_personality_v0
681         .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
682         .align 4
683         .type   DW.ref.__gcc_personality_v0, @object
684         .size   DW.ref.__gcc_personality_v0, 4
685 DW.ref.__gcc_personality_v0:
686         .long   __gcc_personality_v0
687 #endif