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 <shlib-compat.h>
21 #include <lowlevellock.h>
22 #include <lowlevelcond.h>
23 #include <tcb-offsets.h>
24 #include <kernel-features.h>
25 #include "lowlevel-atomic.h"
29 /* int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex) */
30 .globl __pthread_cond_wait
31 .type __pthread_cond_wait, @function
57 /* Get internal lock. */
61 CMPXCHG (r3, @(cond_lock,r8), r4, r2)
63 CMPXCHG (r3, @r8, r4, r2)
71 .long _GLOBAL_OFFSET_TABLE_
75 /* Store the reference to the mutex. If there is already a
76 different value in there this is a bad user bug. */
77 mov.l @(dep_mutex,r8),r0
80 mov.l r9, @(dep_mutex,r8)
83 /* Unlock the mutex. */
99 mov.l @(total_seq,r8),r0
100 mov.l @(total_seq+4,r8),r1
103 mov.l r0,@(total_seq,r8)
104 mov.l r1,@(total_seq+4,r8)
105 mov.l @(cond_futex,r8),r0
107 mov.l r0,@(cond_futex,r8)
108 mov #(1 << nwaiters_shift), r2
109 mov.l @(cond_nwaiters,r8), r0
111 mov.l r0, @(cond_nwaiters,r8)
113 /* Get and store current wakeup_seq value. */
114 mov.l @(wakeup_seq,r8), r10
115 mov.l @(wakeup_seq+4,r8), r11
116 mov.l @(broadcast_seq,r8), r0
120 mov.l @(cond_futex,r8),r0
125 DEC (@(cond_lock,r8), r2)
140 mov.l @(dep_mutex,r8), r0
144 #ifdef __ASSUME_PRIVATE_FUTEX
145 mov #(FUTEX_WAIT|FUTEX_PRIVATE_FLAG), r5
174 CMPXCHG (r3, @(cond_lock,r8), r4, r2)
176 CMPXCHG (r3, @r8, r4, r2)
180 mov.l @(broadcast_seq,r8), r0
185 mov.l @(woken_seq,r8), r0
186 mov.l @(woken_seq+4,r8), r1
188 mov.l @(wakeup_seq,r8), r2
189 mov.l @(wakeup_seq+4,r8), r3
205 mov.l @(woken_seq,r8),r0
206 mov.l @(woken_seq+4,r8),r1
209 mov.l r0,@(woken_seq,r8)
210 mov.l r1,@(woken_seq+4,r8)
213 mov #(1 << nwaiters_shift), r2
214 mov.l @(cond_nwaiters,r8),r0
216 mov.l r0,@(cond_nwaiters,r8)
218 /* Wake up a thread which wants to destroy the condvar object. */
219 mov.l @(total_seq,r8),r0
220 mov.l @(total_seq+4,r8),r1
225 mov #((1 << nwaiters_shift) - 1), r1
227 mov.l @(cond_nwaiters,r8),r0
232 add #cond_nwaiters, r4
233 mov.l @(dep_mutex,r8), r0
237 #ifdef __ASSUME_PRIVATE_FUTEX
238 mov #(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), r5
258 DEC (@(cond_lock,r8), r2)
270 /* We return the result of the mutex_lock operation. */
282 #ifndef __ASSUME_PRIVATE_FUTEX
284 .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE
288 .long __pthread_mutex_unlock_usercnt-.Lmunlock0b
290 .long __pthread_enable_asynccancel-.Lenable0b
292 .long __pthread_disable_asynccancel-.Ldisable0b
294 .long __pthread_mutex_cond_lock-.Lmlocki0b
297 /* Initial locking failed. */
302 mov.l @(dep_mutex,r8), r0
316 /* Unlock in loop requires waekup. */
321 mov.l @(dep_mutex,r8), r0
335 /* Locking in loop failed. */
340 mov.l @(dep_mutex,r8), r0
355 /* Unlock after loop requires wakeup. */
360 mov.l @(dep_mutex,r8), r0
374 /* The initial unlocking of the mutex failed. */
377 DEC (@(cond_lock,r8), r2)
388 mov.l @(dep_mutex,r8), r0
405 .long __lll_lock_wait-.Lwait0b
407 .long __lll_unlock_wake-.Lwake0b
409 .long __lll_lock_wait-.Lwait1b
411 .long __lll_unlock_wake-.Lwake1b
413 .long __lll_unlock_wake-.Lwake2b
414 .size __pthread_cond_wait, .-__pthread_cond_wait
415 versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
419 .type __condvar_w_cleanup, @function
423 /* Get internal lock. */
427 CMPXCHG (r3, @(cond_lock,r8), r4, r2)
429 CMPXCHG (r3, @r8, r4, r2)
438 mov.l @(dep_mutex,r8), r0
451 mov.l @(broadcast_seq,r8), r0
459 /* We increment the wakeup_seq counter only if it is lower than
460 total_seq. If this is not the case the thread was woken and
461 then canceled. In this case we ignore the signal. */
462 mov.l @(total_seq+4,r8), r0
463 mov.l @(wakeup_seq+4,r8), r1
468 mov.l @(total_seq,r8), r0
469 mov.l @(wakeup_seq,r8), r1
475 mov.l @(wakeup_seq,r8),r0
476 mov.l @(wakeup_seq+4,r8),r1
479 mov.l r0,@(wakeup_seq,r8)
480 mov.l r1,@(wakeup_seq+4,r8)
481 mov.l @(cond_futex,r8),r0
483 mov.l r0,@(cond_futex,r8)
487 mov.l @(woken_seq,r8),r0
488 mov.l @(woken_seq+4,r8),r1
491 mov.l r0,@(woken_seq,r8)
492 mov.l r1,@(woken_seq+4,r8)
495 mov #(1 << nwaiters_shift), r2
496 mov.l @(cond_nwaiters,r8),r0
498 mov.l r0,@(cond_nwaiters,r8)
500 /* Wake up a thread which wants to destroy the condvar object. */
502 mov.l @(total_seq,r8),r0
503 mov.l @(total_seq+4,r8),r1
508 mov #((1 << nwaiters_shift) - 1), r1
510 mov.l @(cond_nwaiters,r8),r0
515 add #cond_nwaiters, r4
516 mov.l @(dep_mutex,r8), r0
520 #ifdef __ASSUME_PRIVATE_FUTEX
521 mov #(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), r5
542 DEC (@(cond_lock,r8), r2)
553 mov.l @(dep_mutex,r8), r0
565 /* Wake up all waiters to make sure no signal gets lost. */
570 mov.l @(dep_mutex,r8), r0
574 #ifdef __ASSUME_PRIVATE_FUTEX
575 mov #(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), r5
587 shlr r6 /* r6 = 0x7fffffff */
609 #ifndef __ASSUME_PRIVATE_FUTEX
611 .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE
615 .long __lll_lock_wait-.Lwait3b
617 .long __lll_unlock_wake-.Lwake3b
619 .long __pthread_mutex_cond_lock-.Lmlocki3b
622 .long _Unwind_Resume@GOTOFF
627 .size __condvar_w_cleanup, .-__condvar_w_cleanup
630 .section .gcc_except_table,"a",@progbits
632 .byte 0xff ! @LPStart format (omit)
633 .byte 0xff ! @TType format (omit)
634 .byte 0x0b ! call-site format
636 .uleb128 .Lcstend-.Lcstbegin
638 .ualong .LcleanupSTART-.LSTARTCODE
639 .ualong .LcleanupEND-.LcleanupSTART
640 .ualong __condvar_w_cleanup-.LSTARTCODE
642 .ualong .LcallUR-.LSTARTCODE
643 .ualong .LENDCODE-.LcallUR
648 .section .eh_frame,"a",@progbits
650 .ualong .LENDCIE-.LSTARTCIE ! Length of the CIE.
653 .byte 1 ! Version number.
655 .string "zPLR" ! NUL-terminated augmentation
658 .string "zPL" ! NUL-terminated augmentation
661 .uleb128 1 ! Code alignment factor.
662 .sleb128 -4 ! Data alignment factor.
663 .byte 0x11 ! Return address register
666 .uleb128 7 ! Augmentation value length.
667 .byte 0x9b ! Personality: DW_EH_PE_pcrel
669 ! + DW_EH_PE_indirect
670 .ualong DW.ref.__gcc_personality_v0-.
671 .byte 0x1b ! LSDA Encoding: DW_EH_PE_pcrel
673 .byte 0x1b ! FDE Encoding: DW_EH_PE_pcrel
676 .uleb128 6 ! Augmentation value length.
677 .byte 0x0 ! Personality: absolute
678 .ualong __gcc_personality_v0
679 .byte 0x0 ! LSDA Encoding: absolute
681 .byte 0x0c ! DW_CFA_def_cfa
687 .ualong .LENDFDE-.LSTARTFDE ! Length of the FDE.
689 .ualong .LSTARTFDE-.LSTARTFRAME ! CIE pointer.
691 .ualong .LSTARTCODE-. ! PC-relative start address
694 .ualong .LSTARTCODE ! Start address of the code.
696 .ualong .LENDCODE-.LSTARTCODE ! Length of the code.
697 .uleb128 4 ! Augmentation size
699 .ualong .LexceptSTART-.
701 .ualong .LexceptSTART
704 .ualong .Lpush_r8-.LSTARTCODE
710 .ualong .Lpush_r9-.Lpush_r8
716 .ualong .Lpush_r10-.Lpush_r9
722 .ualong .Lpush_r11-.Lpush_r10
728 .ualong .Lpush_r12-.Lpush_r11
734 .ualong .Lpush_pr-.Lpush_r12
740 .ualong .Lalloc-.Lpush_pr
747 .hidden DW.ref.__gcc_personality_v0
748 .weak DW.ref.__gcc_personality_v0
749 .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
751 .type DW.ref.__gcc_personality_v0, @object
752 .size DW.ref.__gcc_personality_v0, 4
753 DW.ref.__gcc_personality_v0:
754 .long __gcc_personality_v0