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
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
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
38 __pthread_cond_timedwait:
72 /* Get internal lock. */
76 CMPXCHG (r3, @(cond_lock,r8), r4, r2)
78 CMPXCHG (r3, @r8, r4, r2)
86 .long _GLOBAL_OFFSET_TABLE_
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
95 mov.l r9, @(dep_mutex,r8)
98 /* Unlock the mutex. */
114 mov.l @(total_seq,r8),r0
115 mov.l @(total_seq+4,r8),r1
118 mov.l r0,@(total_seq,r8)
119 mov.l r1,@(total_seq+4,r8)
120 mov.l @(cond_futex,r8), r0
122 mov.l r0, @(cond_futex,r8)
123 mov #(1 << clock_bits), r2
124 mov.l @(cond_nwaiters,r8), 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
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
141 /* Only clocks 0 and 1 are allowed. Both are handled in the
145 mov.w .L__NR_clock_gettime, r3
148 # ifndef __ASSUME_POSIX_TIMERS
153 /* Compute relative timeout. */
159 .L__NR_clock_gettime:
160 .word __NR_clock_gettime
162 # ifndef __ASSUME_POSIX_TIMERS
167 mov #SYS_gettimeofday, r3
171 /* Compute relative timeout. */
174 dmulu.l r0, r1 /* Micro seconds to nano seconds. */
185 mov #SYS_gettimeofday, r3
189 /* Compute relative timeout. */
192 dmulu.l r0, r1 /* Micro seconds to nano seconds. */
209 bf 6f /* Time is already up. */
211 /* Store relative timeout. */
214 mov.l @(cond_futex,r8), r1
219 DEC (@(cond_lock,r8), r2)
257 CMPXCHG (r3, @(cond_lock,r8), r4, r2)
259 CMPXCHG (r3, @r8, r4, r2)
263 mov.l @(broadcast_seq,r8), r0
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
285 cmp/eq #-ETIMEDOUT, r0
292 mov.l @(wakeup_seq,r8),r0
293 mov.l @(wakeup_seq+4,r8),r1
296 mov.l r0,@(wakeup_seq,r8)
297 mov.l r1,@(wakeup_seq+4,r8)
298 mov.l @(cond_futex,r8),r0
300 mov.l r0,@(cond_futex,r8)
318 mov.l @(woken_seq,r8),r0
319 mov.l @(woken_seq+4,r8),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
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
338 mov #((1 << clock_bits) - 1), r1
340 mov.l @(cond_nwaiters,r8),r0
345 add #cond_nwaiters, r4
356 DEC (@(cond_lock,r8), r2)
370 /* We return the result of the mutex_lock operation if it failed. */
390 .long __pthread_mutex_unlock_usercnt-.Lmunlock1b
392 .long __pthread_enable_asynccancel-.Lenable1b
394 .long __pthread_disable_asynccancel-.Ldisable1b
396 .long __pthread_mutex_cond_lock-.Lmlocki1b
401 /* Initial locking failed. */
414 /* Unlock in loop requires wakeup. */
427 /* Locking in loop failed. */
440 /* Unlock after loop requires wakeup. */
453 /* The initial unlocking of the mutex failed. */
456 DEC (@(cond_lock,r8), r2)
477 .long __lll_mutex_lock_wait-.Lmwait2b
479 .long __lll_mutex_unlock_wake-.Lmwake2b
481 .long __lll_mutex_lock_wait-.Lmwait3b
483 .long __lll_mutex_unlock_wake-.Lmwake3b
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,
491 .type __condvar_tw_cleanup, @function
492 __condvar_tw_cleanup:
495 /* Get internal lock. */
499 CMPXCHG (r3, @(cond_lock,r8), r4, r2)
501 CMPXCHG (r3, @r8, r4, r2)
516 mov.l @(broadcast_seq,r8), r0
525 mov.l @(wakeup_seq,r8),r0
526 mov.l @(wakeup_seq+4,r8),r1
529 mov.l r0,@(wakeup_seq,r8)
530 mov.l r1,@(wakeup_seq+4,r8)
531 mov.l @(cond_futex,r8),r0
533 mov.l r0,@(cond_futex,r8)
536 mov.l @(woken_seq,r8),r0
537 mov.l @(woken_seq+4,r8),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
547 mov.l r0,@(cond_nwaiters,r8)
549 /* Wake up a thread which wants to destroy the condvar object. */
551 mov.l @(total_seq,r8),r0
552 mov.l @(total_seq+4,r8),r1
557 mov #((1 << clock_bits) - 1), r1
559 mov.l @(cond_nwaiters,r8),r0
564 add #cond_nwaiters, r4
576 DEC (@(cond_lock,r8), r2)
593 /* Wake up all waiters to make sure no signal gets lost. */
600 shlr r6 /* r6 = 0x7fffffff */
624 .long __lll_mutex_lock_wait-.Lmwait5b
626 .long __lll_mutex_unlock_wake-.Lmwake5b
628 .long __pthread_mutex_cond_lock-.Lmlocki5b
631 .long _Unwind_Resume@GOTOFF
636 .size __condvar_tw_cleanup, .-__condvar_tw_cleanup
639 .section .gcc_except_table,"a",@progbits
641 .byte 0xff ! @LPStart format (omit)
642 .byte 0xff ! @TType format (omit)
643 .byte 0x0b ! call-site format
645 .uleb128 .Lcstend-.Lcstbegin
647 .ualong .LcleanupSTART-.LSTARTCODE
648 .ualong .LcleanupEND-.LcleanupSTART
649 .ualong __condvar_tw_cleanup-.LSTARTCODE
651 .ualong .LcallUR-.LSTARTCODE
652 .ualong .LENDCODE-.LcallUR
657 .section .eh_frame,"a",@progbits
659 .ualong .LENDCIE-.LSTARTCIE ! Length of the CIE.
662 .byte 1 ! Version number.
664 .string "zPLR" ! NUL-terminated augmentation
667 .string "zPL" ! NUL-terminated augmentation
670 .uleb128 1 ! Code alignment factor.
671 .sleb128 -4 ! Data alignment factor.
672 .byte 0x11 ! Return address register
675 .uleb128 7 ! Augmentation value length.
676 .byte 0x9b ! Personality: DW_EH_PE_pcrel
678 ! + DW_EH_PE_indirect
679 .ualong DW.ref.__gcc_personality_v0-.
680 .byte 0x1b ! LSDA Encoding: DW_EH_PE_pcrel
682 .byte 0x1b ! FDE Encoding: DW_EH_PE_pcrel
685 .uleb128 6 ! Augmentation value length.
686 .byte 0x0 ! Personality: absolute
687 .ualong __gcc_personality_v0
688 .byte 0x0 ! LSDA Encoding: absolute
690 .byte 0x0c ! DW_CFA_def_cfa
696 .ualong .LENDFDE-.LSTARTFDE ! Length of the FDE.
698 .ualong .LSTARTFDE-.LSTARTFRAME ! CIE pointer.
700 .ualong .LSTARTCODE-. ! PC-relative start address
703 .ualong .LSTARTCODE ! Start address of the code.
705 .ualong .LENDCODE-.LSTARTCODE ! Length of the code.
706 .uleb128 4 ! Augmentation size
708 .ualong .LexceptSTART-.
710 .ualong .LexceptSTART
713 .ualong .Lpush_r8-.LSTARTCODE
719 .ualong .Lpush_r9-.Lpush_r8
725 .ualong .Lpush_r10-.Lpush_r9
731 .ualong .Lpush_r11-.Lpush_r10
737 .ualong .Lpush_r12-.Lpush_r11
743 .ualong .Lpush_r13-.Lpush_r12
749 .ualong .Lpush_pr-.Lpush_r13
755 .ualong .Lalloc-.Lpush_pr
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
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