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 <shlib-compat.h>
20 #include <lowlevellock.h>
21 #include <lowlevelcond.h>
22 #include <tcb-offsets.h>
23 #include <kernel-features.h>
24 #include "lowlevel-atomic.h"
28 /* int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex) */
29 .globl __pthread_cond_wait
30 .type __pthread_cond_wait, @function
56 /* Get internal lock. */
60 CMPXCHG (r3, @(cond_lock,r8), r4, r2)
62 CMPXCHG (r3, @r8, r4, r2)
70 .long _GLOBAL_OFFSET_TABLE_
74 /* Store the reference to the mutex. If there is already a
75 different value in there this is a bad user bug. */
76 mov.l @(dep_mutex,r8),r0
79 mov.l r9, @(dep_mutex,r8)
82 /* Unlock the mutex. */
98 mov.l @(total_seq,r8),r0
99 mov.l @(total_seq+4,r8),r1
102 mov.l r0,@(total_seq,r8)
103 mov.l r1,@(total_seq+4,r8)
104 mov.l @(cond_futex,r8),r0
106 mov.l r0,@(cond_futex,r8)
107 mov #(1 << nwaiters_shift), r2
108 mov.l @(cond_nwaiters,r8), r0
110 mov.l r0, @(cond_nwaiters,r8)
112 /* Get and store current wakeup_seq value. */
113 mov.l @(wakeup_seq,r8), r10
114 mov.l @(wakeup_seq+4,r8), r11
115 mov.l @(broadcast_seq,r8), r0
119 mov.l @(cond_futex,r8),r0
124 DEC (@(cond_lock,r8), r2)
139 mov.l @(dep_mutex,r8), r0
143 #ifdef __ASSUME_PRIVATE_FUTEX
144 mov #(FUTEX_WAIT|FUTEX_PRIVATE_FLAG), r5
173 CMPXCHG (r3, @(cond_lock,r8), r4, r2)
175 CMPXCHG (r3, @r8, r4, r2)
179 mov.l @(broadcast_seq,r8), r0
184 mov.l @(woken_seq,r8), r0
185 mov.l @(woken_seq+4,r8), r1
187 mov.l @(wakeup_seq,r8), r2
188 mov.l @(wakeup_seq+4,r8), r3
204 mov.l @(woken_seq,r8),r0
205 mov.l @(woken_seq+4,r8),r1
208 mov.l r0,@(woken_seq,r8)
209 mov.l r1,@(woken_seq+4,r8)
212 mov #(1 << nwaiters_shift), r2
213 mov.l @(cond_nwaiters,r8),r0
215 mov.l r0,@(cond_nwaiters,r8)
217 /* Wake up a thread which wants to destroy the condvar object. */
218 mov.l @(total_seq,r8),r0
219 mov.l @(total_seq+4,r8),r1
224 mov #((1 << nwaiters_shift) - 1), r1
226 mov.l @(cond_nwaiters,r8),r0
231 add #cond_nwaiters, r4
232 mov.l @(dep_mutex,r8), r0
236 #ifdef __ASSUME_PRIVATE_FUTEX
237 mov #(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), r5
257 DEC (@(cond_lock,r8), r2)
269 /* We return the result of the mutex_lock operation. */
281 #ifndef __ASSUME_PRIVATE_FUTEX
283 .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE
287 .long __pthread_mutex_unlock_usercnt-.Lmunlock0b
289 .long __pthread_enable_asynccancel-.Lenable0b
291 .long __pthread_disable_asynccancel-.Ldisable0b
293 .long __pthread_mutex_cond_lock-.Lmlocki0b
296 /* Initial locking failed. */
301 mov.l @(dep_mutex,r8), r0
315 /* Unlock in loop requires waekup. */
320 mov.l @(dep_mutex,r8), r0
334 /* Locking in loop failed. */
339 mov.l @(dep_mutex,r8), r0
354 /* Unlock after loop requires wakeup. */
359 mov.l @(dep_mutex,r8), r0
373 /* The initial unlocking of the mutex failed. */
376 DEC (@(cond_lock,r8), r2)
387 mov.l @(dep_mutex,r8), r0
404 .long __lll_lock_wait-.Lwait0b
406 .long __lll_unlock_wake-.Lwake0b
408 .long __lll_lock_wait-.Lwait1b
410 .long __lll_unlock_wake-.Lwake1b
412 .long __lll_unlock_wake-.Lwake2b
413 .size __pthread_cond_wait, .-__pthread_cond_wait
414 versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
418 .type __condvar_w_cleanup, @function
422 /* Get internal lock. */
426 CMPXCHG (r3, @(cond_lock,r8), r4, r2)
428 CMPXCHG (r3, @r8, r4, r2)
437 mov.l @(dep_mutex,r8), r0
450 mov.l @(broadcast_seq,r8), r0
458 /* We increment the wakeup_seq counter only if it is lower than
459 total_seq. If this is not the case the thread was woken and
460 then canceled. In this case we ignore the signal. */
461 mov.l @(total_seq+4,r8), r0
462 mov.l @(wakeup_seq+4,r8), r1
467 mov.l @(total_seq,r8), r0
468 mov.l @(wakeup_seq,r8), r1
474 mov.l @(wakeup_seq,r8),r0
475 mov.l @(wakeup_seq+4,r8),r1
478 mov.l r0,@(wakeup_seq,r8)
479 mov.l r1,@(wakeup_seq+4,r8)
480 mov.l @(cond_futex,r8),r0
482 mov.l r0,@(cond_futex,r8)
486 mov.l @(woken_seq,r8),r0
487 mov.l @(woken_seq+4,r8),r1
490 mov.l r0,@(woken_seq,r8)
491 mov.l r1,@(woken_seq+4,r8)
494 mov #(1 << nwaiters_shift), r2
495 mov.l @(cond_nwaiters,r8),r0
497 mov.l r0,@(cond_nwaiters,r8)
499 /* Wake up a thread which wants to destroy the condvar object. */
501 mov.l @(total_seq,r8),r0
502 mov.l @(total_seq+4,r8),r1
507 mov #((1 << nwaiters_shift) - 1), r1
509 mov.l @(cond_nwaiters,r8),r0
514 add #cond_nwaiters, r4
515 mov.l @(dep_mutex,r8), r0
519 #ifdef __ASSUME_PRIVATE_FUTEX
520 mov #(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), r5
541 DEC (@(cond_lock,r8), r2)
552 mov.l @(dep_mutex,r8), r0
564 /* Wake up all waiters to make sure no signal gets lost. */
569 mov.l @(dep_mutex,r8), r0
573 #ifdef __ASSUME_PRIVATE_FUTEX
574 mov #(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), r5
586 shlr r6 /* r6 = 0x7fffffff */
608 #ifndef __ASSUME_PRIVATE_FUTEX
610 .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE
614 .long __lll_lock_wait-.Lwait3b
616 .long __lll_unlock_wake-.Lwake3b
618 .long __pthread_mutex_cond_lock-.Lmlocki3b
621 .long _Unwind_Resume@GOTOFF
626 .size __condvar_w_cleanup, .-__condvar_w_cleanup
629 .section .gcc_except_table,"a",@progbits
631 .byte 0xff ! @LPStart format (omit)
632 .byte 0xff ! @TType format (omit)
633 .byte 0x0b ! call-site format
635 .uleb128 .Lcstend-.Lcstbegin
637 .ualong .LcleanupSTART-.LSTARTCODE
638 .ualong .LcleanupEND-.LcleanupSTART
639 .ualong __condvar_w_cleanup-.LSTARTCODE
641 .ualong .LcallUR-.LSTARTCODE
642 .ualong .LENDCODE-.LcallUR
647 .section .eh_frame,"a",@progbits
649 .ualong .LENDCIE-.LSTARTCIE ! Length of the CIE.
652 .byte 1 ! Version number.
654 .string "zPLR" ! NUL-terminated augmentation
657 .string "zPL" ! NUL-terminated augmentation
660 .uleb128 1 ! Code alignment factor.
661 .sleb128 -4 ! Data alignment factor.
662 .byte 0x11 ! Return address register
665 .uleb128 7 ! Augmentation value length.
666 .byte 0x9b ! Personality: DW_EH_PE_pcrel
668 ! + DW_EH_PE_indirect
669 .ualong DW.ref.__gcc_personality_v0-.
670 .byte 0x1b ! LSDA Encoding: DW_EH_PE_pcrel
672 .byte 0x1b ! FDE Encoding: DW_EH_PE_pcrel
675 .uleb128 6 ! Augmentation value length.
676 .byte 0x0 ! Personality: absolute
677 .ualong __gcc_personality_v0
678 .byte 0x0 ! LSDA Encoding: absolute
680 .byte 0x0c ! DW_CFA_def_cfa
686 .ualong .LENDFDE-.LSTARTFDE ! Length of the FDE.
688 .ualong .LSTARTFDE-.LSTARTFRAME ! CIE pointer.
690 .ualong .LSTARTCODE-. ! PC-relative start address
693 .ualong .LSTARTCODE ! Start address of the code.
695 .ualong .LENDCODE-.LSTARTCODE ! Length of the code.
696 .uleb128 4 ! Augmentation size
698 .ualong .LexceptSTART-.
700 .ualong .LexceptSTART
703 .ualong .Lpush_r8-.LSTARTCODE
709 .ualong .Lpush_r9-.Lpush_r8
715 .ualong .Lpush_r10-.Lpush_r9
721 .ualong .Lpush_r11-.Lpush_r10
727 .ualong .Lpush_r12-.Lpush_r11
733 .ualong .Lpush_pr-.Lpush_r12
739 .ualong .Lalloc-.Lpush_pr
746 .hidden DW.ref.__gcc_personality_v0
747 .weak DW.ref.__gcc_personality_v0
748 .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
750 .type DW.ref.__gcc_personality_v0, @object
751 .size DW.ref.__gcc_personality_v0, 4
752 DW.ref.__gcc_personality_v0:
753 .long __gcc_personality_v0