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, write to the Free
16 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20 #include <lowlevellock.h>
21 #include <lowlevelcond.h>
22 #include <pthread-errnos.h>
23 #include <bits/kernel-features.h>
24 #include <tcb-offsets.h>
25 #include "lowlevel-atomic.h"
29 /* int pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
30 const struct timespec *abstime) */
31 .globl __pthread_cond_timedwait
32 .type __pthread_cond_timedwait, @function
33 .protected __pthread_cond_timedwait
35 __pthread_cond_timedwait:
69 /* Get internal lock. */
73 CMPXCHG (r3, @(cond_lock,r8), r4, r2)
75 CMPXCHG (r3, @r8, r4, r2)
83 .long _GLOBAL_OFFSET_TABLE_
87 /* Store the reference to the mutex. If there is already a
88 different value in there this is a bad user bug. */
89 mov.l @(dep_mutex,r8),r0
92 mov.l r9, @(dep_mutex,r8)
95 /* Unlock the mutex. */
111 mov.l @(total_seq,r8),r0
112 mov.l @(total_seq+4,r8),r1
115 mov.l r0,@(total_seq,r8)
116 mov.l r1,@(total_seq+4,r8)
117 mov.l @(cond_futex,r8), r0
119 mov.l r0, @(cond_futex,r8)
120 mov #(1 << nwaiters_shift), r2
121 mov.l @(cond_nwaiters,r8), r0
123 mov.l r0, @(cond_nwaiters,r8)
125 /* Get and store current wakeup_seq value. */
126 mov.l @(wakeup_seq,r8), r10
127 mov.l @(wakeup_seq+4,r8), r11
128 mov.l @(broadcast_seq,r8), r0
132 /* Get current time. */
133 #ifdef __NR_clock_gettime
134 /* Get the clock number. */
135 mov.l @(cond_nwaiters,r8), r4
136 mov #((1 << nwaiters_shift) - 1), r0
138 /* Only clocks 0 and 1 are allowed. Both are handled in the
142 mov.w .L__NR_clock_gettime, r3
145 # ifndef __ASSUME_POSIX_TIMERS
150 /* Compute relative timeout. */
156 .L__NR_clock_gettime:
157 .word __NR_clock_gettime
159 # ifndef __ASSUME_POSIX_TIMERS
164 mov #__NR_gettimeofday, r3
168 /* Compute relative timeout. */
171 dmulu.l r0, r1 /* Micro seconds to nano seconds. */
182 mov #__NR_gettimeofday, r3
186 /* Compute relative timeout. */
189 dmulu.l r0, r1 /* Micro seconds to nano seconds. */
206 bf 6f /* Time is already up. */
208 /* Store relative timeout. */
211 mov.l @(cond_futex,r8), r1
216 DEC (@(cond_lock,r8), r2)
234 mov.l @(dep_mutex,r8), r0
238 #ifdef __ASSUME_PRIVATE_FUTEX
239 mov #(FUTEX_WAIT|FUTEX_PRIVATE_FLAG), r5
269 CMPXCHG (r3, @(cond_lock,r8), r4, r2)
271 CMPXCHG (r3, @r8, r4, r2)
275 mov.l @(broadcast_seq,r8), r0
280 mov.l @(woken_seq,r8), r0
281 mov.l @(woken_seq+4,r8), r1
283 mov.l @(wakeup_seq,r8), r2
284 mov.l @(wakeup_seq+4,r8), r3
297 cmp/eq #-ETIMEDOUT, r0
304 mov.l @(wakeup_seq,r8),r0
305 mov.l @(wakeup_seq+4,r8),r1
308 mov.l r0,@(wakeup_seq,r8)
309 mov.l r1,@(wakeup_seq+4,r8)
310 mov.l @(cond_futex,r8),r0
312 mov.l r0,@(cond_futex,r8)
330 mov.l @(woken_seq,r8),r0
331 mov.l @(woken_seq+4,r8),r1
334 mov.l r0,@(woken_seq,r8)
335 mov.l r1,@(woken_seq+4,r8)
338 mov #(1 << nwaiters_shift), r2
339 mov.l @(cond_nwaiters,r8),r0
341 mov.l r0,@(cond_nwaiters,r8)
343 /* Wake up a thread which wants to destroy the condvar object. */
344 mov.l @(total_seq,r8),r0
345 mov.l @(total_seq+4,r8),r1
350 mov #((1 << nwaiters_shift) - 1), r1
352 mov.l @(cond_nwaiters,r8),r0
357 add #cond_nwaiters, r4
358 mov.l @(dep_mutex,r8), r0
362 #ifdef __ASSUME_PRIVATE_FUTEX
363 mov #(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), r5
383 DEC (@(cond_lock,r8), r2)
397 /* We return the result of the mutex_lock operation if it failed. */
413 #ifndef __ASSUME_PRIVATE_FUTEX
415 .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE
421 .long __pthread_mutex_unlock_usercnt-.Lmunlock1b
423 .long __pthread_enable_asynccancel-.Lenable1b
425 .long __pthread_disable_asynccancel-.Ldisable1b
427 .long __pthread_mutex_cond_lock-.Lmlocki1b
432 /* Initial locking failed. */
437 mov.l @(dep_mutex,r8), r0
452 /* Unlock in loop requires wakeup. */
457 mov.l @(dep_mutex,r8), r0
471 /* Locking in loop failed. */
476 mov.l @(dep_mutex,r8), r0
491 /* Unlock after loop requires wakeup. */
496 mov.l @(dep_mutex,r8), r0
510 /* The initial unlocking of the mutex failed. */
513 DEC (@(cond_lock,r8), r2)
524 mov.l @(dep_mutex,r8), r0
540 .long __lll_lock_wait-.Lwait2b
542 .long __lll_unlock_wake-.Lmwait2b
544 .long __lll_lock_wait-.Lwait3b
546 .long __lll_unlock_wake-.Lmwait3b
548 .long __lll_unlock_wake-.Lmwait4b
549 .size __pthread_cond_timedwait, .-__pthread_cond_timedwait
550 weak_alias (__pthread_cond_timedwait, pthread_cond_timedwait)
553 .type __condvar_tw_cleanup, @function
554 __condvar_tw_cleanup:
557 /* Get internal lock. */
561 CMPXCHG (r3, @(cond_lock,r8), r4, r2)
563 CMPXCHG (r3, @r8, r4, r2)
572 mov.l @(dep_mutex,r8), r0
585 mov.l @(broadcast_seq,r8), r0
593 /* We increment the wakeup_seq counter only if it is lower than
594 total_seq. If this is not the case the thread was woken and
595 then canceled. In this case we ignore the signal. */
596 mov.l @(total_seq+4,r8), r0
597 mov.l @(wakeup_seq+4,r8), r1
602 mov.l @(total_seq,r8), r0
603 mov.l @(wakeup_seq,r8), r1
609 mov.l @(wakeup_seq,r8),r0
610 mov.l @(wakeup_seq+4,r8),r1
613 mov.l r0,@(wakeup_seq,r8)
614 mov.l r1,@(wakeup_seq+4,r8)
615 mov.l @(cond_futex,r8),r0
617 mov.l r0,@(cond_futex,r8)
621 mov.l @(woken_seq,r8),r0
622 mov.l @(woken_seq+4,r8),r1
625 mov.l r0,@(woken_seq,r8)
626 mov.l r1,@(woken_seq+4,r8)
629 mov #(1 << nwaiters_shift), r2
630 mov.l @(cond_nwaiters,r8),r0
632 mov.l r0,@(cond_nwaiters,r8)
634 /* Wake up a thread which wants to destroy the condvar object. */
636 mov.l @(total_seq,r8),r0
637 mov.l @(total_seq+4,r8),r1
642 mov #((1 << nwaiters_shift) - 1), r1
644 mov.l @(cond_nwaiters,r8),r0
649 add #cond_nwaiters, r4
661 DEC (@(cond_lock,r8), r2)
672 mov.l @(dep_mutex,r8), r0
684 /* Wake up all waiters to make sure no signal gets lost. */
691 shlr r6 /* r6 = 0x7fffffff */
715 .long __lll_lock_wait-.Lwait5b
717 .long __lll_unlock_wake-.Lmwait5b
719 .long __pthread_mutex_cond_lock-.Lmlocki5b
722 .long _Unwind_Resume@GOTOFF
727 .size __condvar_tw_cleanup, .-__condvar_tw_cleanup
730 .section .gcc_except_table,"a",@progbits
732 .byte 0xff ! @LPStart format (omit)
733 .byte 0xff ! @TType format (omit)
734 .byte 0x0b ! call-site format
736 .uleb128 .Lcstend-.Lcstbegin
738 .ualong .LcleanupSTART-.LSTARTCODE
739 .ualong .LcleanupEND-.LcleanupSTART
740 .ualong __condvar_tw_cleanup-.LSTARTCODE
742 .ualong .LcallUR-.LSTARTCODE
743 .ualong .LENDCODE-.LcallUR
748 .section .eh_frame,"a",@progbits
750 .ualong .LENDCIE-.LSTARTCIE ! Length of the CIE.
753 .byte 1 ! Version number.
755 .string "zPLR" ! NUL-terminated augmentation
758 .string "zPL" ! NUL-terminated augmentation
761 .uleb128 1 ! Code alignment factor.
762 .sleb128 -4 ! Data alignment factor.
763 .byte 0x11 ! Return address register
766 .uleb128 7 ! Augmentation value length.
767 .byte 0x9b ! Personality: DW_EH_PE_pcrel
769 ! + DW_EH_PE_indirect
770 .ualong DW.ref.__gcc_personality_v0-.
771 .byte 0x1b ! LSDA Encoding: DW_EH_PE_pcrel
773 .byte 0x1b ! FDE Encoding: DW_EH_PE_pcrel
776 .uleb128 6 ! Augmentation value length.
777 .byte 0x0 ! Personality: absolute
778 .ualong __gcc_personality_v0
779 .byte 0x0 ! LSDA Encoding: absolute
781 .byte 0x0c ! DW_CFA_def_cfa
787 .ualong .LENDFDE-.LSTARTFDE ! Length of the FDE.
789 .ualong .LSTARTFDE-.LSTARTFRAME ! CIE pointer.
791 .ualong .LSTARTCODE-. ! PC-relative start address
794 .ualong .LSTARTCODE ! Start address of the code.
796 .ualong .LENDCODE-.LSTARTCODE ! Length of the code.
797 .uleb128 4 ! Augmentation size
799 .ualong .LexceptSTART-.
801 .ualong .LexceptSTART
804 .ualong .Lpush_r8-.LSTARTCODE
810 .ualong .Lpush_r9-.Lpush_r8
816 .ualong .Lpush_r10-.Lpush_r9
822 .ualong .Lpush_r11-.Lpush_r10
828 .ualong .Lpush_r12-.Lpush_r11
834 .ualong .Lpush_r13-.Lpush_r12
840 .ualong .Lpush_pr-.Lpush_r13
846 .ualong .Lalloc-.Lpush_pr
853 .hidden DW.ref.__gcc_personality_v0
854 .weak DW.ref.__gcc_personality_v0
855 .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
857 .type DW.ref.__gcc_personality_v0, @object
858 .size DW.ref.__gcc_personality_v0, 4
859 DW.ref.__gcc_personality_v0:
860 .long __gcc_personality_v0