Updated to fedora-glibc-20041102T1153
[glibc.git] / nptl / sysdeps / unix / sysv / linux / sh / pthread_cond_timedwait.S
blob74206a71ec1a4f5f21ea2236d9b37800c244cc13
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 <pthread-errnos.h>
23 #include "lowlevel-atomic.h"
25 #define SYS_gettimeofday        __NR_gettimeofday
26 #define SYS_futex               240
27 #define FUTEX_WAIT              0
28 #define FUTEX_WAKE              1
31         .text
33 /* int pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
34                                const struct timespec *abstime)  */
35         .globl  __pthread_cond_timedwait
36         .type   __pthread_cond_timedwait, @function
37         .align  5
38 __pthread_cond_timedwait:
39 .LSTARTCODE:
40         mov.l   r8, @-r15
41 .Lpush_r8:
42         mov.l   r9, @-r15
43 .Lpush_r9:
44         mov.l   r10, @-r15
45 .Lpush_r10:
46         mov.l   r11, @-r15
47 .Lpush_r11:
48         mov.l   r12, @-r15
49 .Lpush_r12:
50         mov.l   r13, @-r15
51 .Lpush_r13:
52         sts.l   pr, @-r15
53 .Lpush_pr:
54         add     #-64, r15
55 .Lalloc:
56         mov     r4, r8
57         mov     r5, r9
58         mov     r6, r13
59 #ifdef PIC
60         mova    .Lgot0, r0
61         mov.l   .Lgot0, r12
62         add     r0, r12
63 #endif
65         mov.l   @(4,r13), r0
66         mov.l   .L1g, r1
67         cmp/hs  r1, r0
68         bf      0f
69         bra     18f
70          mov    #EINVAL, r0
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      17f
95         mov.l   r9, @(dep_mutex,r8)
97 17:     
98         /* Unlock the mutex.  */
99         mov.l   .Lmunlock1, r1
100         mov     #0, r5
101         bsrf    r1
102          mov    r9, r4
103 .Lmunlock1b:
105         tst     r0, r0
106         bt      0f
107         bra     16f
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 << clock_bits), r2
124         mov.l   @(cond_nwaiters,r8), r0
125         add     r2, r0
126         mov.l   r0, @(cond_nwaiters,r8)
127         
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)
134 8:      
135         /* Get current time.  */
136 #ifdef __NR_clock_gettime
137         /* Get the clock number.         */
138         mov.l   @(cond_nwaiters,r8), r4
139         mov     #((1 << clock_bits) - 1), r0
140         and     r0, r4
141         /* Only clocks 0 and 1 are allowed.  Both are handled in the
142            kernel.  */
143         mov     r15, r5
144         add     #16, r5
145         mov.w   .L__NR_clock_gettime, r3
146         trapa   #0x12
147         SYSCALL_INST_PAD
148 # ifndef __ASSUME_POSIX_TIMERS
149         cmp/eq  #-ENOSYS, r0
150         bt      19f
151 # endif
153         /* Compute relative timeout.  */
154         mov.l   @r13, r2
155         mov.l   @(4,r13), r3
156         mov.l   @(16,r15), r0
157         bra     0f
158          mov.l  @(20,r15), r1
159 .L__NR_clock_gettime:
160         .word   __NR_clock_gettime
162 # ifndef __ASSUME_POSIX_TIMERS
163 19:     
164         mov     r15, r4
165         add     #16, r4
166         mov     #0, r5
167         mov     #SYS_gettimeofday, r3
168         trapa   #0x12
169         SYSCALL_INST_PAD
171         /* Compute relative timeout.  */
172         mov.l   @(20,r15), r0
173         mov.w   .L1k, r1
174         dmulu.l r0, r1          /* Micro seconds to nano seconds.  */
175         mov.l   @r13, r2
176         mov.l   @(4,r13), r3
177         mov.l   @(16,r15), r0
178         sts     macl, r1
179 #endif
180 0:      
181 #else
182         mov     r15, r4
183         add     #16, r4
184         mov     #0, r5
185         mov     #SYS_gettimeofday, r3
186         trapa   #0x12
187         SYSCALL_INST_PAD
189         /* Compute relative timeout.  */
190         mov.l   @(20,r15), r0
191         mov.w   .L1k, r1
192         dmulu.l r0, r1          /* Micro seconds to nano seconds.  */
193         mov.l   @r13, r2
194         mov.l   @(4,r13), r3
195         mov.l   @(16,r15), r0
196         sts     macl, r1
197 #endif
198         sub     r0, r2
199         clrt
200         subc    r1, r3
201         bf      12f
202         mov.l   .L1g, r1
203         add     r1, r3
204         add     #-1, r2
206         mov     #-ETIMEDOUT, r1
207         mov.l   r1, @(12,r15)
208         cmp/pz  r2
209         bf      6f              /* Time is already up.  */
211         /* Store relative timeout.  */
212         mov.l   r2, @(16,r15)
213         mov.l   r3, @(20,r15)
214         mov.l   @(cond_futex,r8), r1
215         mov.l   r1, @(8,r15)
217         /* Unlock.  */
218 #if cond_lock != 0
219         DEC (@(cond_lock,r8), r2)
220 #else
221         DEC (@r8, r2)
222 #endif
223         tst     r2, r2
224         bt      4f
225         bra     3f
226          nop
228 .LcleanupSTART:
229         mov.l   .Lenable1, r1
230         bsrf    r1
231          nop
232 .Lenable1b:
233         mov.l   r0, @r15
235         mov     r15, r7
236         add     #16, r7
237         mov     #FUTEX_WAIT, r5
238         mov.l   @(8,r15), r6
239         mov     r8, r4
240         add     #cond_futex, r4
241         mov     #SYS_futex, r3
242         extu.b  r3, r3
243         trapa   #0x14
244         SYSCALL_INST_PAD
245         mov.l   r0, @(12,r15)
247         mov.l   .Ldisable1, r1
248         bsrf    r1
249          mov.l  @r15, r4
250 .Ldisable1b:
251 .LcleanupEND:
253         /* Lock.  */
254         mov     #0, r3
255         mov     #1, r4
256 #if cond_lock != 0
257         CMPXCHG (r3, @(cond_lock,r8), r4, r2)
258 #else
259         CMPXCHG (r3, @r8, r4, r2)
260 #endif
261         bf      5f
263         mov.l   @(broadcast_seq,r8), r0
264         mov.l   @(4,r15), r1
265         cmp/eq  r0, r1
266         bf      23f
268         mov.l   @(woken_seq,r8), r0
269         mov.l   @(woken_seq+4,r8), r1
271         mov.l   @(wakeup_seq,r8), r2
272         mov.l   @(wakeup_seq+4,r8), r3
274         cmp/eq  r3, r11
275         bf      7f
276         cmp/eq  r2, r10
277         bt      15f
279         cmp/eq  r1, r3
280         bf      9f
281         cmp/eq  r0, r2
282         bf      9f
284         mov.l   @(12,r15),r0
285         cmp/eq  #-ETIMEDOUT, r0
286         bf      8b
288         mov     #1, r2
289         mov     #0, r3
291         clrt
292         mov.l   @(wakeup_seq,r8),r0
293         mov.l   @(wakeup_seq+4,r8),r1
294         addc    r2, r0
295         addc    r3, r1
296         mov.l   r0,@(wakeup_seq,r8)
297         mov.l   r1,@(wakeup_seq+4,r8)
298         mov.l   @(cond_futex,r8),r0
299         add     r2, r0
300         mov.l   r0,@(cond_futex,r8)
301         mov     #ETIMEDOUT, r0
302         bra     14f
303          mov.l  r0, @(24,r15)
306         mov     #0, r0
307         bra     24f
308          mov.l  r0, @(24,r15)
311         mov     #0, r0
312         mov.l   r0, @(24,r15)
314         mov     #1, r2
315         mov     #0, r3
317         clrt
318         mov.l   @(woken_seq,r8),r0
319         mov.l   @(woken_seq+4,r8),r1
320         addc    r2, r0
321         addc    r3, r1
322         mov.l   r0,@(woken_seq,r8)
323         mov.l   r1,@(woken_seq+4,r8)
326         mov     #(1 << clock_bits), r2
327         mov.l   @(cond_nwaiters,r8),r0
328         sub     r2, r0
329         mov.l   r0,@(cond_nwaiters,r8)
331         /* Wake up a thread which wants to destroy the condvar object.  */
332         mov.l   @(total_seq,r8),r0
333         mov.l   @(total_seq+4,r8),r1
334         and     r1, r0
335         not     r0, r0
336         cmp/eq  #0, r0
337         bf/s    25f
338          mov    #((1 << clock_bits) - 1), r1
339         not     r1, r1
340         mov.l   @(cond_nwaiters,r8),r0
341         tst     r1, r0
342         bf      25f
344         mov     r8, r4
345         add     #cond_nwaiters, r4
346         mov     #FUTEX_WAKE, r5
347         mov     #1, r6
348         mov     #0, r7
349         mov     #SYS_futex, r3
350         extu.b  r3, r3
351         trapa   #0x14
352         SYSCALL_INST_PAD
353         
354 25:     
355 #if cond_lock != 0
356         DEC (@(cond_lock,r8), r2)
357 #else
358         DEC (@r8, r2)
359 #endif
360         tst     r2, r2
361         bf      10f
364         mov     r9, r4
365         mov.l   .Lmlocki1, r1
366         bsrf    r1
367          nop
368 .Lmlocki1b:
370         /* We return the result of the mutex_lock operation if it failed.  */
371         tst     r0, r0
372         bf      18f
373         mov.l   @(24,r15), r0
375 18:     
376         add     #64, r15
377         lds.l   @r15+, pr
378         mov.l   @r15+, r13
379         mov.l   @r15+, r12
380         mov.l   @r15+, r11
381         mov.l   @r15+, r10
382         mov.l   @r15+, r9
383         rts
384          mov.l  @r15+, r8
386 .L1k:
387         .word   1000
388         .align  2
389 .Lmunlock1:
390         .long   __pthread_mutex_unlock_usercnt-.Lmunlock1b
391 .Lenable1:
392         .long   __pthread_enable_asynccancel-.Lenable1b
393 .Ldisable1:
394         .long   __pthread_disable_asynccancel-.Ldisable1b
395 .Lmlocki1:
396         .long   __pthread_mutex_cond_lock-.Lmlocki1b
397 .L1g:
398         .long   1000000000
401         /* Initial locking failed.  */
402         mov     r8, r5
403 #if cond_lock != 0
404         add     #cond_lock, r5
405 #endif
406         mov.l   .Lmwait2, r1
407         bsrf    r1
408          mov    r2, r4
409 .Lmwait2b:
410         bra     2b
411          nop
414         /* Unlock in loop requires wakeup.  */
415         mov     r8, r4
416 #if cond_lock != 0
417         add     #cond_lock, r4
418 #endif
419         mov.l   .Lmwake2, r1
420         bsrf    r1
421          nop
422 .Lmwake2b:
423         bra     4b
424          nop
427         /* Locking in loop failed.  */
428         mov     r8, r5
429 #if cond_lock != 0
430         add     #cond_lock, r5
431 #endif
432         mov.l   .Lmwait3, r1
433         bsrf    r1
434          mov    r2, r4
435 .Lmwait3b:
436         bra     6b
437          nop
440         /* Unlock after loop requires wakeup.  */
441         mov     r8, r4
442 #if cond_lock != 0
443         add     #cond_lock, r4
444 #endif
445         mov.l   .Lmwake3, r1
446         bsrf    r1
447          nop
448 .Lmwake3b:
449         bra     11b
450          nop
453         /* The initial unlocking of the mutex failed.  */
454         mov.l   r0, @(24,r15)
455 #if cond_lock != 0
456         DEC (@(cond_lock,r8), r2)
457 #else
458         DEC (@r8, r2)
459 #endif
460         tst     r2, r2
461         bf      17f
463         mov     r8, r4
464 #if cond_lock != 0
465         add     #cond_lock, r4
466 #endif
467         mov.l   .Lmwake4, r1
468         bsrf    r1
469          nop
470 .Lmwake4b:
472         bra     18b
473          mov.l  @(24,r15), r0
475         .align  2
476 .Lmwait2:
477         .long   __lll_mutex_lock_wait-.Lmwait2b
478 .Lmwake2:
479         .long   __lll_mutex_unlock_wake-.Lmwake2b
480 .Lmwait3:
481         .long   __lll_mutex_lock_wait-.Lmwait3b
482 .Lmwake3:
483         .long   __lll_mutex_unlock_wake-.Lmwake3b
484 .Lmwake4:
485         .long   __lll_mutex_unlock_wake-.Lmwake4b
486         .size   __pthread_cond_timedwait, .-__pthread_cond_timedwait
487 versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
488                   GLIBC_2_3_2)
491         .type   __condvar_tw_cleanup, @function
492 __condvar_tw_cleanup:
493         mov     r4, r11
495         /* Get internal lock.  */
496         mov     #0, r3
497         mov     #1, r4
498 #if cond_lock != 0
499         CMPXCHG (r3, @(cond_lock,r8), r4, r2)
500 #else
501         CMPXCHG (r3, @r8, r4, r2)
502 #endif
503         bt      1f
504          nop
506         mov     r8, r5
507 #if cond_lock != 0
508         add     #cond_lock, r5
509 #endif
510         mov.l   .Lmwait5, r1
511         bsrf    r1
512          mov    r2, r4
513 .Lmwait5b:
516         mov.l   @(broadcast_seq,r8), r0
517         mov.l   @(4,r15), r1
518         cmp/eq  r0, r1
519         bf      3f
521         mov     #1, r2
522         mov     #0, r3
524         clrt
525         mov.l   @(wakeup_seq,r8),r0
526         mov.l   @(wakeup_seq+4,r8),r1
527         addc    r2, r0
528         addc    r3, r1
529         mov.l   r0,@(wakeup_seq,r8)
530         mov.l   r1,@(wakeup_seq+4,r8)
531         mov.l   @(cond_futex,r8),r0
532         add     r2, r0
533         mov.l   r0,@(cond_futex,r8)
535         clrt
536         mov.l   @(woken_seq,r8),r0
537         mov.l   @(woken_seq+4,r8),r1
538         addc    r2, r0
539         addc    r3, r1
540         mov.l   r0,@(woken_seq,r8)
541         mov.l   r1,@(woken_seq+4,r8)
544         mov     #(1 << clock_bits), r2
545         mov.l   @(cond_nwaiters,r8),r0
546         sub     r2, r0
547         mov.l   r0,@(cond_nwaiters,r8)
549         /* Wake up a thread which wants to destroy the condvar object.  */
550         mov     #0, r10
551         mov.l   @(total_seq,r8),r0
552         mov.l   @(total_seq+4,r8),r1
553         and     r1, r0
554         not     r0, r0
555         cmp/eq  #0, r0
556         bf/s    4f
557          mov    #((1 << clock_bits) - 1), r1
558         not     r1, r1
559         mov.l   @(cond_nwaiters,r8),r0
560         tst     r1, r0
561         bf      4f
563         mov     r8, r4
564         add     #cond_nwaiters, r4
565         mov     #FUTEX_WAKE, r5
566         mov     #1, r6
567         mov     #0, r7
568         mov     #SYS_futex, r3
569         extu.b  r3, r3
570         trapa   #0x14
571         SYSCALL_INST_PAD
572         mov     #1, r10
575 #if cond_lock != 0
576         DEC (@(cond_lock,r8), r2)
577 #else
578         DEC (@r8, r2)
579 #endif
580         tst     r2, r2
581         bt      2f
583         mov     r8, r4
584 #if cond_lock != 0
585         add     #cond_lock, r4
586 #endif
587         mov.l   .Lmwake5, r1
588         bsrf    r1
589          nop
590 .Lmwake5b:
593         /* Wake up all waiters to make sure no signal gets lost.  */
594         tst     r10, r10
595         bf/s    5f
596          mov    r8, r4
597         add     #cond_futex, r4
598         mov     #FUTEX_WAKE, r5
599         mov     #-1, r6
600         shlr    r6              /* r6 = 0x7fffffff */
601         mov     #0, r7
602         mov     #SYS_futex, r3
603         extu.b  r3, r3
604         trapa   #0x14
605         SYSCALL_INST_PAD
608         mov.l   .Lmlocki5, r1
609         bsrf    r1
610          mov     r9, r4
611 .Lmlocki5b:
613 .LcallUR:
614         mov.l   .Lresume, r1
615 #ifdef PIC
616         add     r12, r1
617 #endif
618         jsr     @r1
619          mov    r11, r4
620         sleep
622         .align  2
623 .Lmwait5:
624         .long   __lll_mutex_lock_wait-.Lmwait5b
625 .Lmwake5:
626         .long   __lll_mutex_unlock_wake-.Lmwake5b
627 .Lmlocki5:
628         .long   __pthread_mutex_cond_lock-.Lmlocki5b
629 .Lresume:
630 #ifdef PIC
631         .long   _Unwind_Resume@GOTOFF
632 #else
633         .long   _Unwind_Resume
634 #endif
635 .LENDCODE:
636         .size   __condvar_tw_cleanup, .-__condvar_tw_cleanup
639         .section .gcc_except_table,"a",@progbits
640 .LexceptSTART:
641         .byte   0xff                            ! @LPStart format (omit)
642         .byte   0xff                            ! @TType format (omit)
643         .byte   0x0b                            ! call-site format
644                                                 ! DW_EH_PE_sdata4
645         .uleb128 .Lcstend-.Lcstbegin
646 .Lcstbegin:
647         .ualong .LcleanupSTART-.LSTARTCODE
648         .ualong .LcleanupEND-.LcleanupSTART
649         .ualong __condvar_tw_cleanup-.LSTARTCODE
650         .uleb128  0
651         .ualong .LcallUR-.LSTARTCODE
652         .ualong .LENDCODE-.LcallUR
653         .ualong 0
654         .uleb128  0
655 .Lcstend:
657         .section .eh_frame,"a",@progbits
658 .LSTARTFRAME:
659         .ualong .LENDCIE-.LSTARTCIE             ! Length of the CIE.
660 .LSTARTCIE:
661         .ualong 0                               ! CIE ID.
662         .byte   1                               ! Version number.
663 #ifdef SHARED
664         .string "zPLR"                          ! NUL-terminated augmentation
665                                                 ! string.
666 #else
667         .string "zPL"                           ! NUL-terminated augmentation
668                                                 ! string.
669 #endif
670         .uleb128 1                              ! Code alignment factor.
671         .sleb128 -4                             ! Data alignment factor.
672         .byte   0x11                            ! Return address register
673                                                 ! column.
674 #ifdef SHARED
675         .uleb128 7                              ! Augmentation value length.
676         .byte   0x9b                            ! Personality: DW_EH_PE_pcrel
677                                                 ! + DW_EH_PE_sdata4
678                                                 ! + DW_EH_PE_indirect
679         .ualong DW.ref.__gcc_personality_v0-.
680         .byte   0x1b                            ! LSDA Encoding: DW_EH_PE_pcrel
681                                                 ! + DW_EH_PE_sdata4.
682         .byte   0x1b                            ! FDE Encoding: DW_EH_PE_pcrel
683                                                 ! + DW_EH_PE_sdata4.
684 #else
685         .uleb128 6                              ! Augmentation value length.
686         .byte   0x0                             ! Personality: absolute
687         .ualong __gcc_personality_v0
688         .byte   0x0                             ! LSDA Encoding: absolute
689 #endif
690         .byte 0x0c                              ! DW_CFA_def_cfa
691         .uleb128 0xf
692         .uleb128 0
693         .align 2
694 .LENDCIE:
696         .ualong .LENDFDE-.LSTARTFDE             ! Length of the FDE.
697 .LSTARTFDE:
698         .ualong .LSTARTFDE-.LSTARTFRAME         ! CIE pointer.
699 #ifdef SHARED
700         .ualong .LSTARTCODE-.                   ! PC-relative start address
701                                                 ! of the code.
702 #else
703         .ualong .LSTARTCODE                     ! Start address of the code.
704 #endif
705         .ualong .LENDCODE-.LSTARTCODE           ! Length of the code.
706         .uleb128 4                              ! Augmentation size
707 #ifdef SHARED
708         .ualong .LexceptSTART-.
709 #else
710         .ualong .LexceptSTART
711 #endif
712         .byte   0x4
713         .ualong .Lpush_r8-.LSTARTCODE
714         .byte   0xe
715         .uleb128 4
716         .byte   0x88
717         .uleb128 1
718         .byte   0x4
719         .ualong .Lpush_r9-.Lpush_r8
720         .byte   0xe
721         .uleb128 8
722         .byte   0x89
723         .uleb128 2
724         .byte   0x4
725         .ualong .Lpush_r10-.Lpush_r9
726         .byte   0xe
727         .uleb128 12
728         .byte   0x8a
729         .uleb128 3
730         .byte   0x4
731         .ualong .Lpush_r11-.Lpush_r10
732         .byte   0xe
733         .uleb128 16
734         .byte   0x8b
735         .uleb128 4
736         .byte   0x4
737         .ualong .Lpush_r12-.Lpush_r11
738         .byte   0xe
739         .uleb128 20
740         .byte   0x8c
741         .uleb128 5
742         .byte   0x4
743         .ualong .Lpush_r13-.Lpush_r12
744         .byte   0xe
745         .uleb128 24
746         .byte   0x8d
747         .uleb128 6
748         .byte   0x4
749         .ualong .Lpush_pr-.Lpush_r13
750         .byte   0xe
751         .uleb128 28
752         .byte   0x91
753         .uleb128 7
754         .byte   0x4
755         .ualong .Lalloc-.Lpush_pr
756         .byte   0xe
757         .uleb128 92
758         .align  2
759 .LENDFDE:
761 #ifdef SHARED
762         .hidden DW.ref.__gcc_personality_v0
763         .weak   DW.ref.__gcc_personality_v0
764         .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
765         .align 4
766         .type   DW.ref.__gcc_personality_v0, @object
767         .size   DW.ref.__gcc_personality_v0, 4
768 DW.ref.__gcc_personality_v0:
769         .long   __gcc_personality_v0
770 #endif