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/>. */
19 #include <lowlevellock.h>
20 #include <lowlevelcond.h>
21 #include <pthread-errnos.h>
22 #include <bits/kernel-features.h>
23 #include <tcb-offsets.h>
24 #include "lowlevel-atomic.h"
28 /* int pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
29 const struct timespec *abstime) */
30 .globl __pthread_cond_timedwait
31 .type __pthread_cond_timedwait, @function
32 .protected __pthread_cond_timedwait
34 __pthread_cond_timedwait:
68 /* Get internal lock. */
72 CMPXCHG (r3, @(cond_lock,r8), r4, r2)
74 CMPXCHG (r3, @r8, r4, r2)
82 .long _GLOBAL_OFFSET_TABLE_
86 /* Store the reference to the mutex. If there is already a
87 different value in there this is a bad user bug. */
88 mov.l @(dep_mutex,r8),r0
91 mov.l r9, @(dep_mutex,r8)
94 /* Unlock the mutex. */
110 mov.l @(total_seq,r8),r0
111 mov.l @(total_seq+4,r8),r1
114 mov.l r0,@(total_seq,r8)
115 mov.l r1,@(total_seq+4,r8)
116 mov.l @(cond_futex,r8), r0
118 mov.l r0, @(cond_futex,r8)
119 mov #(1 << nwaiters_shift), r2
120 mov.l @(cond_nwaiters,r8), r0
122 mov.l r0, @(cond_nwaiters,r8)
124 /* Get and store current wakeup_seq value. */
125 mov.l @(wakeup_seq,r8), r10
126 mov.l @(wakeup_seq+4,r8), r11
127 mov.l @(broadcast_seq,r8), r0
131 /* Get current time. */
132 #ifdef __NR_clock_gettime
133 /* Get the clock number. */
134 mov.l @(cond_nwaiters,r8), r4
135 mov #((1 << nwaiters_shift) - 1), r0
137 /* Only clocks 0 and 1 are allowed. Both are handled in the
141 mov.w .L__NR_clock_gettime, r3
144 # ifndef __ASSUME_POSIX_TIMERS
149 /* Compute relative timeout. */
155 .L__NR_clock_gettime:
156 .word __NR_clock_gettime
158 # ifndef __ASSUME_POSIX_TIMERS
163 mov #__NR_gettimeofday, r3
167 /* Compute relative timeout. */
170 dmulu.l r0, r1 /* Micro seconds to nano seconds. */
181 mov #__NR_gettimeofday, r3
185 /* Compute relative timeout. */
188 dmulu.l r0, r1 /* Micro seconds to nano seconds. */
205 bf 6f /* Time is already up. */
207 /* Store relative timeout. */
210 mov.l @(cond_futex,r8), r1
215 DEC (@(cond_lock,r8), r2)
233 mov.l @(dep_mutex,r8), r0
237 #ifdef __ASSUME_PRIVATE_FUTEX
238 mov #(FUTEX_WAIT|FUTEX_PRIVATE_FLAG), r5
268 CMPXCHG (r3, @(cond_lock,r8), r4, r2)
270 CMPXCHG (r3, @r8, r4, r2)
274 mov.l @(broadcast_seq,r8), r0
279 mov.l @(woken_seq,r8), r0
280 mov.l @(woken_seq+4,r8), r1
282 mov.l @(wakeup_seq,r8), r2
283 mov.l @(wakeup_seq+4,r8), r3
296 cmp/eq #-ETIMEDOUT, r0
303 mov.l @(wakeup_seq,r8),r0
304 mov.l @(wakeup_seq+4,r8),r1
307 mov.l r0,@(wakeup_seq,r8)
308 mov.l r1,@(wakeup_seq+4,r8)
309 mov.l @(cond_futex,r8),r0
311 mov.l r0,@(cond_futex,r8)
329 mov.l @(woken_seq,r8),r0
330 mov.l @(woken_seq+4,r8),r1
333 mov.l r0,@(woken_seq,r8)
334 mov.l r1,@(woken_seq+4,r8)
337 mov #(1 << nwaiters_shift), r2
338 mov.l @(cond_nwaiters,r8),r0
340 mov.l r0,@(cond_nwaiters,r8)
342 /* Wake up a thread which wants to destroy the condvar object. */
343 mov.l @(total_seq,r8),r0
344 mov.l @(total_seq+4,r8),r1
349 mov #((1 << nwaiters_shift) - 1), r1
351 mov.l @(cond_nwaiters,r8),r0
356 add #cond_nwaiters, r4
357 mov.l @(dep_mutex,r8), r0
361 #ifdef __ASSUME_PRIVATE_FUTEX
362 mov #(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), r5
382 DEC (@(cond_lock,r8), r2)
396 /* We return the result of the mutex_lock operation if it failed. */
412 #ifndef __ASSUME_PRIVATE_FUTEX
414 .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE
420 .long __pthread_mutex_unlock_usercnt-.Lmunlock1b
422 .long __pthread_enable_asynccancel-.Lenable1b
424 .long __pthread_disable_asynccancel-.Ldisable1b
426 .long __pthread_mutex_cond_lock-.Lmlocki1b
431 /* Initial locking failed. */
436 mov.l @(dep_mutex,r8), r0
451 /* Unlock in loop requires wakeup. */
456 mov.l @(dep_mutex,r8), r0
470 /* Locking in loop failed. */
475 mov.l @(dep_mutex,r8), r0
490 /* Unlock after loop requires wakeup. */
495 mov.l @(dep_mutex,r8), r0
509 /* The initial unlocking of the mutex failed. */
512 DEC (@(cond_lock,r8), r2)
523 mov.l @(dep_mutex,r8), r0
539 .long __lll_lock_wait-.Lwait2b
541 .long __lll_unlock_wake-.Lmwait2b
543 .long __lll_lock_wait-.Lwait3b
545 .long __lll_unlock_wake-.Lmwait3b
547 .long __lll_unlock_wake-.Lmwait4b
548 .size __pthread_cond_timedwait, .-__pthread_cond_timedwait
549 weak_alias (__pthread_cond_timedwait, pthread_cond_timedwait)
552 .type __condvar_tw_cleanup, @function
553 __condvar_tw_cleanup:
556 /* Get internal lock. */
560 CMPXCHG (r3, @(cond_lock,r8), r4, r2)
562 CMPXCHG (r3, @r8, r4, r2)
571 mov.l @(dep_mutex,r8), r0
584 mov.l @(broadcast_seq,r8), r0
592 /* We increment the wakeup_seq counter only if it is lower than
593 total_seq. If this is not the case the thread was woken and
594 then canceled. In this case we ignore the signal. */
595 mov.l @(total_seq+4,r8), r0
596 mov.l @(wakeup_seq+4,r8), r1
601 mov.l @(total_seq,r8), r0
602 mov.l @(wakeup_seq,r8), r1
608 mov.l @(wakeup_seq,r8),r0
609 mov.l @(wakeup_seq+4,r8),r1
612 mov.l r0,@(wakeup_seq,r8)
613 mov.l r1,@(wakeup_seq+4,r8)
614 mov.l @(cond_futex,r8),r0
616 mov.l r0,@(cond_futex,r8)
620 mov.l @(woken_seq,r8),r0
621 mov.l @(woken_seq+4,r8),r1
624 mov.l r0,@(woken_seq,r8)
625 mov.l r1,@(woken_seq+4,r8)
628 mov #(1 << nwaiters_shift), r2
629 mov.l @(cond_nwaiters,r8),r0
631 mov.l r0,@(cond_nwaiters,r8)
633 /* Wake up a thread which wants to destroy the condvar object. */
635 mov.l @(total_seq,r8),r0
636 mov.l @(total_seq+4,r8),r1
641 mov #((1 << nwaiters_shift) - 1), r1
643 mov.l @(cond_nwaiters,r8),r0
648 add #cond_nwaiters, r4
660 DEC (@(cond_lock,r8), r2)
671 mov.l @(dep_mutex,r8), r0
683 /* Wake up all waiters to make sure no signal gets lost. */
690 shlr r6 /* r6 = 0x7fffffff */
714 .long __lll_lock_wait-.Lwait5b
716 .long __lll_unlock_wake-.Lmwait5b
718 .long __pthread_mutex_cond_lock-.Lmlocki5b
721 .long _Unwind_Resume@GOTOFF
726 .size __condvar_tw_cleanup, .-__condvar_tw_cleanup
729 .section .gcc_except_table,"a",@progbits
731 .byte 0xff ! @LPStart format (omit)
732 .byte 0xff ! @TType format (omit)
733 .byte 0x0b ! call-site format
735 .uleb128 .Lcstend-.Lcstbegin
737 .ualong .LcleanupSTART-.LSTARTCODE
738 .ualong .LcleanupEND-.LcleanupSTART
739 .ualong __condvar_tw_cleanup-.LSTARTCODE
741 .ualong .LcallUR-.LSTARTCODE
742 .ualong .LENDCODE-.LcallUR
747 .section .eh_frame,"a",@progbits
749 .ualong .LENDCIE-.LSTARTCIE ! Length of the CIE.
752 .byte 1 ! Version number.
754 .string "zPLR" ! NUL-terminated augmentation
757 .string "zPL" ! NUL-terminated augmentation
760 .uleb128 1 ! Code alignment factor.
761 .sleb128 -4 ! Data alignment factor.
762 .byte 0x11 ! Return address register
765 .uleb128 7 ! Augmentation value length.
766 .byte 0x9b ! Personality: DW_EH_PE_pcrel
768 ! + DW_EH_PE_indirect
769 .ualong DW.ref.__gcc_personality_v0-.
770 .byte 0x1b ! LSDA Encoding: DW_EH_PE_pcrel
772 .byte 0x1b ! FDE Encoding: DW_EH_PE_pcrel
775 .uleb128 6 ! Augmentation value length.
776 .byte 0x0 ! Personality: absolute
777 .ualong __gcc_personality_v0
778 .byte 0x0 ! LSDA Encoding: absolute
780 .byte 0x0c ! DW_CFA_def_cfa
786 .ualong .LENDFDE-.LSTARTFDE ! Length of the FDE.
788 .ualong .LSTARTFDE-.LSTARTFRAME ! CIE pointer.
790 .ualong .LSTARTCODE-. ! PC-relative start address
793 .ualong .LSTARTCODE ! Start address of the code.
795 .ualong .LENDCODE-.LSTARTCODE ! Length of the code.
796 .uleb128 4 ! Augmentation size
798 .ualong .LexceptSTART-.
800 .ualong .LexceptSTART
803 .ualong .Lpush_r8-.LSTARTCODE
809 .ualong .Lpush_r9-.Lpush_r8
815 .ualong .Lpush_r10-.Lpush_r9
821 .ualong .Lpush_r11-.Lpush_r10
827 .ualong .Lpush_r12-.Lpush_r11
833 .ualong .Lpush_r13-.Lpush_r12
839 .ualong .Lpush_pr-.Lpush_r13
845 .ualong .Lalloc-.Lpush_pr
852 .hidden DW.ref.__gcc_personality_v0
853 .weak DW.ref.__gcc_personality_v0
854 .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
856 .type DW.ref.__gcc_personality_v0, @object
857 .size DW.ref.__gcc_personality_v0, 4
858 DW.ref.__gcc_personality_v0:
859 .long __gcc_personality_v0