2.5-18.1
[glibc.git] / nptl / sysdeps / unix / sysv / linux / sh / pthread_cond_wait.S
blob6c59f3e6c030be27164b4094c44175f85aba79a1
1 /* Copyright (C) 2003, 2004, 2006 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         /* We increment the wakeup_seq counter only if it is lower than
389            total_seq.  If this is not the case the thread was woken and
390            then canceled.  In this case we ignore the signal.  */
391         mov.l   @(total_seq+4,r8), r0
392         mov.l   @(wakeup_seq+4,r8), r1
393         cmp/hi  r1, r0
394         bt/s    6f
395          cmp/hi r0, r1
396         bt      7f
397         mov.l   @(total_seq,r8), r0
398         mov.l   @(wakeup_seq,r8), r1
399         cmp/hs  r0, r1
400         bt      7f
403         clrt
404         mov.l   @(wakeup_seq,r8),r0
405         mov.l   @(wakeup_seq+4,r8),r1
406         addc    r2, r0
407         addc    r3, r1
408         mov.l   r0,@(wakeup_seq,r8)
409         mov.l   r1,@(wakeup_seq+4,r8)
410         mov.l   @(cond_futex,r8),r0
411         add     r2, r0
412         mov.l   r0,@(cond_futex,r8)
415         clrt
416         mov.l   @(woken_seq,r8),r0
417         mov.l   @(woken_seq+4,r8),r1
418         addc    r2, r0
419         addc    r3, r1
420         mov.l   r0,@(woken_seq,r8)
421         mov.l   r1,@(woken_seq+4,r8)
424         mov     #(1 << clock_bits), r2
425         mov.l   @(cond_nwaiters,r8),r0
426         sub     r2, r0
427         mov.l   r0,@(cond_nwaiters,r8)
429         /* Wake up a thread which wants to destroy the condvar object.  */
430         mov     #0, r10
431         mov.l   @(total_seq,r8),r0
432         mov.l   @(total_seq+4,r8),r1
433         and     r1, r0
434         not     r0, r0
435         cmp/eq  #0, r0
436         bf/s    4f
437          mov    #((1 << clock_bits) - 1), r1
438         not     r1, r1
439         mov.l   @(cond_nwaiters,r8),r0
440         tst     r1, r0
441         bf      4f
443         mov     r8, r4
444         add     #cond_nwaiters, r4
445         mov     #FUTEX_WAKE, r5
446         mov     #1, r6
447         mov     #0, r7
448         mov     #SYS_futex, r3
449         extu.b  r3, r3
450         trapa   #0x14
451         SYSCALL_INST_PAD
452         mov     #1, r10
455 #if cond_lock != 0
456         DEC (@(cond_lock,r8), r2)
457 #else
458         DEC (@r8, r2)
459 #endif
460         tst     r2, r2
461         bt      2f
463         mov     r8, r4
464 #if cond_lock != 0
465         add     #cond_lock, r4
466 #endif
467         mov.l   .Lmwake3, r1
468         bsrf    r1
469          nop
470 .Lmwake3b:
473         /* Wake up all waiters to make sure no signal gets lost.  */
474         tst     r10, r10
475         bf/s    5f
476          mov    r8, r4
477         add     #cond_futex, r4
478         mov     #FUTEX_WAKE, r5
479         mov     #-1, r6
480         shlr    r6              /* r6 = 0x7fffffff */
481         mov     #0, r7
482         mov     #SYS_futex, r3
483         extu.b  r3, r3
484         trapa   #0x14
485         SYSCALL_INST_PAD
488         mov.l   .Lmlocki3, r1
489         bsrf    r1
490          mov     r9, r4
491 .Lmlocki3b:
493 .LcallUR:
494         mov.l   .Lresume, r1
495 #ifdef PIC
496         add     r12, r1
497 #endif
498         jsr     @r1
499          mov    r11, r4
500         sleep
502         .align  2
503 .Lmwait3:
504         .long   __lll_mutex_lock_wait-.Lmwait3b
505 .Lmwake3:
506         .long   __lll_mutex_unlock_wake-.Lmwake3b
507 .Lmlocki3:
508         .long   __pthread_mutex_cond_lock-.Lmlocki3b
509 .Lresume:
510 #ifdef PIC
511         .long   _Unwind_Resume@GOTOFF
512 #else
513         .long   _Unwind_Resume
514 #endif
515 .LENDCODE:
516         .size   __condvar_w_cleanup, .-__condvar_w_cleanup
519         .section .gcc_except_table,"a",@progbits
520 .LexceptSTART:
521         .byte   0xff                            ! @LPStart format (omit)
522         .byte   0xff                            ! @TType format (omit)
523         .byte   0x0b                            ! call-site format
524                                                 ! DW_EH_PE_sdata4
525         .uleb128 .Lcstend-.Lcstbegin
526 .Lcstbegin:
527         .ualong .LcleanupSTART-.LSTARTCODE
528         .ualong .LcleanupEND-.LcleanupSTART
529         .ualong __condvar_w_cleanup-.LSTARTCODE
530         .uleb128  0
531         .ualong .LcallUR-.LSTARTCODE
532         .ualong .LENDCODE-.LcallUR
533         .ualong 0
534         .uleb128  0
535 .Lcstend:
537         .section .eh_frame,"a",@progbits
538 .LSTARTFRAME:
539         .ualong .LENDCIE-.LSTARTCIE             ! Length of the CIE.
540 .LSTARTCIE:
541         .ualong 0                               ! CIE ID.
542         .byte   1                               ! Version number.
543 #ifdef SHARED
544         .string "zPLR"                          ! NUL-terminated augmentation
545                                                 ! string.
546 #else
547         .string "zPL"                           ! NUL-terminated augmentation
548                                                 ! string.
549 #endif
550         .uleb128 1                              ! Code alignment factor.
551         .sleb128 -4                             ! Data alignment factor.
552         .byte   0x11                            ! Return address register
553                                                 ! column.
554 #ifdef SHARED
555         .uleb128 7                              ! Augmentation value length.
556         .byte   0x9b                            ! Personality: DW_EH_PE_pcrel
557                                                 ! + DW_EH_PE_sdata4
558                                                 ! + DW_EH_PE_indirect
559         .ualong DW.ref.__gcc_personality_v0-.
560         .byte   0x1b                            ! LSDA Encoding: DW_EH_PE_pcrel
561                                                 ! + DW_EH_PE_sdata4.
562         .byte   0x1b                            ! FDE Encoding: DW_EH_PE_pcrel
563                                                 ! + DW_EH_PE_sdata4.
564 #else
565         .uleb128 6                              ! Augmentation value length.
566         .byte   0x0                             ! Personality: absolute
567         .ualong __gcc_personality_v0
568         .byte   0x0                             ! LSDA Encoding: absolute
569 #endif
570         .byte 0x0c                              ! DW_CFA_def_cfa
571         .uleb128 0xf
572         .uleb128 0
573         .align 2
574 .LENDCIE:
576         .ualong .LENDFDE-.LSTARTFDE             ! Length of the FDE.
577 .LSTARTFDE:
578         .ualong .LSTARTFDE-.LSTARTFRAME         ! CIE pointer.
579 #ifdef SHARED
580         .ualong .LSTARTCODE-.                   ! PC-relative start address
581                                                 ! of the code.
582 #else
583         .ualong .LSTARTCODE                     ! Start address of the code.
584 #endif
585         .ualong .LENDCODE-.LSTARTCODE           ! Length of the code.
586         .uleb128 4                              ! Augmentation size
587 #ifdef SHARED
588         .ualong .LexceptSTART-.
589 #else
590         .ualong .LexceptSTART
591 #endif
592         .byte   0x4
593         .ualong .Lpush_r8-.LSTARTCODE
594         .byte   0xe
595         .uleb128 4
596         .byte   0x88
597         .uleb128 1
598         .byte   0x4
599         .ualong .Lpush_r9-.Lpush_r8
600         .byte   0xe
601         .uleb128 8
602         .byte   0x89
603         .uleb128 2
604         .byte   0x4
605         .ualong .Lpush_r10-.Lpush_r9
606         .byte   0xe
607         .uleb128 12
608         .byte   0x8a
609         .uleb128 3
610         .byte   0x4
611         .ualong .Lpush_r11-.Lpush_r10
612         .byte   0xe
613         .uleb128 16
614         .byte   0x8b
615         .uleb128 4
616         .byte   0x4
617         .ualong .Lpush_r12-.Lpush_r11
618         .byte   0xe
619         .uleb128 20
620         .byte   0x8c
621         .uleb128 5
622         .byte   0x4
623         .ualong .Lpush_pr-.Lpush_r12
624         .byte   0xe
625         .uleb128 24
626         .byte   0x91
627         .uleb128 6
628         .byte   0x4
629         .ualong .Lalloc-.Lpush_pr
630         .byte   0xe
631         .uleb128 72
632         .align  2
633 .LENDFDE:
635 #ifdef SHARED
636         .hidden DW.ref.__gcc_personality_v0
637         .weak   DW.ref.__gcc_personality_v0
638         .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
639         .align 4
640         .type   DW.ref.__gcc_personality_v0, @object
641         .size   DW.ref.__gcc_personality_v0, 4
642 DW.ref.__gcc_personality_v0:
643         .long   __gcc_personality_v0
644 #endif