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 <tcb-offsets.h>
22 #include <bits/kernel-features.h>
23 #include "lowlevel-atomic.h"
27 /* int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex) */
28 .globl __pthread_cond_wait
29 .type __pthread_cond_wait, @function
30 .protected __pthread_cond_wait
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 weak_alias (__pthread_cond_wait, pthread_cond_wait)
417 .type __condvar_w_cleanup, @function
421 /* Get internal lock. */
425 CMPXCHG (r3, @(cond_lock,r8), r4, r2)
427 CMPXCHG (r3, @r8, r4, r2)
436 mov.l @(dep_mutex,r8), r0
449 mov.l @(broadcast_seq,r8), r0
457 /* We increment the wakeup_seq counter only if it is lower than
458 total_seq. If this is not the case the thread was woken and
459 then canceled. In this case we ignore the signal. */
460 mov.l @(total_seq+4,r8), r0
461 mov.l @(wakeup_seq+4,r8), r1
466 mov.l @(total_seq,r8), r0
467 mov.l @(wakeup_seq,r8), r1
473 mov.l @(wakeup_seq,r8),r0
474 mov.l @(wakeup_seq+4,r8),r1
477 mov.l r0,@(wakeup_seq,r8)
478 mov.l r1,@(wakeup_seq+4,r8)
479 mov.l @(cond_futex,r8),r0
481 mov.l r0,@(cond_futex,r8)
485 mov.l @(woken_seq,r8),r0
486 mov.l @(woken_seq+4,r8),r1
489 mov.l r0,@(woken_seq,r8)
490 mov.l r1,@(woken_seq+4,r8)
493 mov #(1 << nwaiters_shift), r2
494 mov.l @(cond_nwaiters,r8),r0
496 mov.l r0,@(cond_nwaiters,r8)
498 /* Wake up a thread which wants to destroy the condvar object. */
500 mov.l @(total_seq,r8),r0
501 mov.l @(total_seq+4,r8),r1
506 mov #((1 << nwaiters_shift) - 1), r1
508 mov.l @(cond_nwaiters,r8),r0
513 add #cond_nwaiters, r4
514 mov.l @(dep_mutex,r8), r0
518 #ifdef __ASSUME_PRIVATE_FUTEX
519 mov #(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), r5
540 DEC (@(cond_lock,r8), r2)
551 mov.l @(dep_mutex,r8), r0
563 /* Wake up all waiters to make sure no signal gets lost. */
568 mov.l @(dep_mutex,r8), r0
572 #ifdef __ASSUME_PRIVATE_FUTEX
573 mov #(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), r5
585 shlr r6 /* r6 = 0x7fffffff */
607 #ifndef __ASSUME_PRIVATE_FUTEX
609 .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE
613 .long __lll_lock_wait-.Lwait3b
615 .long __lll_unlock_wake-.Lwake3b
617 .long __pthread_mutex_cond_lock-.Lmlocki3b
620 .long _Unwind_Resume@GOTOFF
625 .size __condvar_w_cleanup, .-__condvar_w_cleanup
628 .section .gcc_except_table,"a",@progbits
630 .byte 0xff ! @LPStart format (omit)
631 .byte 0xff ! @TType format (omit)
632 .byte 0x0b ! call-site format
634 .uleb128 .Lcstend-.Lcstbegin
636 .ualong .LcleanupSTART-.LSTARTCODE
637 .ualong .LcleanupEND-.LcleanupSTART
638 .ualong __condvar_w_cleanup-.LSTARTCODE
640 .ualong .LcallUR-.LSTARTCODE
641 .ualong .LENDCODE-.LcallUR
646 .section .eh_frame,"a",@progbits
648 .ualong .LENDCIE-.LSTARTCIE ! Length of the CIE.
651 .byte 1 ! Version number.
653 .string "zPLR" ! NUL-terminated augmentation
656 .string "zPL" ! NUL-terminated augmentation
659 .uleb128 1 ! Code alignment factor.
660 .sleb128 -4 ! Data alignment factor.
661 .byte 0x11 ! Return address register
664 .uleb128 7 ! Augmentation value length.
665 .byte 0x9b ! Personality: DW_EH_PE_pcrel
667 ! + DW_EH_PE_indirect
668 .ualong DW.ref.__gcc_personality_v0-.
669 .byte 0x1b ! LSDA Encoding: DW_EH_PE_pcrel
671 .byte 0x1b ! FDE Encoding: DW_EH_PE_pcrel
674 .uleb128 6 ! Augmentation value length.
675 .byte 0x0 ! Personality: absolute
676 .ualong __gcc_personality_v0
677 .byte 0x0 ! LSDA Encoding: absolute
679 .byte 0x0c ! DW_CFA_def_cfa
685 .ualong .LENDFDE-.LSTARTFDE ! Length of the FDE.
687 .ualong .LSTARTFDE-.LSTARTFRAME ! CIE pointer.
689 .ualong .LSTARTCODE-. ! PC-relative start address
692 .ualong .LSTARTCODE ! Start address of the code.
694 .ualong .LENDCODE-.LSTARTCODE ! Length of the code.
695 .uleb128 4 ! Augmentation size
697 .ualong .LexceptSTART-.
699 .ualong .LexceptSTART
702 .ualong .Lpush_r8-.LSTARTCODE
708 .ualong .Lpush_r9-.Lpush_r8
714 .ualong .Lpush_r10-.Lpush_r9
720 .ualong .Lpush_r11-.Lpush_r10
726 .ualong .Lpush_r12-.Lpush_r11
732 .ualong .Lpush_pr-.Lpush_r12
738 .ualong .Lalloc-.Lpush_pr
745 .hidden DW.ref.__gcc_personality_v0
746 .weak DW.ref.__gcc_personality_v0
747 .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
749 .type DW.ref.__gcc_personality_v0, @object
750 .size DW.ref.__gcc_personality_v0, 4
751 DW.ref.__gcc_personality_v0:
752 .long __gcc_personality_v0