1 /* Copyright (C) 2002-2007, 2009 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21 #include <shlib-compat.h>
22 #include <lowlevellock.h>
23 #include <lowlevelcond.h>
24 #include <tcb-offsets.h>
25 #include <pthread-pi-defines.h>
27 #include <kernel-features.h>
32 /* int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex) */
33 .globl __pthread_cond_wait
34 .type __pthread_cond_wait, @function
40 cfi_personality(DW_EH_PE_pcrel | DW_EH_PE_sdata4 | DW_EH_PE_indirect,
41 DW.ref.__gcc_personality_v0)
42 cfi_lsda(DW_EH_PE_pcrel | DW_EH_PE_sdata4, .LexceptSTART)
44 cfi_personality(DW_EH_PE_udata4, __gcc_personality_v0)
45 cfi_lsda(DW_EH_PE_udata4, .LexceptSTART)
49 cfi_adjust_cfa_offset(8)
50 cfi_rel_offset(%r12, 0)
52 cfi_adjust_cfa_offset(8)
53 cfi_rel_offset(%r13, 0)
55 subq $FRAME_SIZE, %rsp
56 cfi_adjust_cfa_offset(FRAME_SIZE)
61 +--------------------------+
62 rsp + 24 | old wake_seq value |
63 +--------------------------+
64 rsp + 16 | mutex pointer |
65 +--------------------------+
66 rsp + 8 | condvar pointer |
67 +--------------------------+
68 rsp + 4 | old broadcast_seq value |
69 +--------------------------+
70 rsp + 0 | old cancellation mode |
71 +--------------------------+
74 cmpq $-1, dep_mutex(%rdi)
76 /* Prepare structure passed to cancellation handler. */
81 movq %rsi, dep_mutex(%rdi)
83 /* Get internal lock. */
90 cmpxchgl %esi, cond_lock(%rdi)
94 /* Unlock the mutex. */
95 2: movq 16(%rsp), %rdi
97 callq __pthread_mutex_unlock_usercnt
104 incl cond_futex(%rdi)
105 addl $(1 << nwaiters_shift), cond_nwaiters(%rdi)
107 /* Get and store current wakeup_seq value. */
109 movq wakeup_seq(%rdi), %r9
110 movl broadcast_seq(%rdi), %edx
115 8: movl cond_futex(%rdi), %r12d
125 4: callq __pthread_enable_asynccancel
132 addq $cond_futex, %rdi
133 cmpq $-1, dep_mutex-cond_futex(%rdi)
134 #ifdef __ASSUME_PRIVATE_FUTEX
135 movl $FUTEX_WAIT, %eax
136 movl $(FUTEX_WAIT|FUTEX_PRIVATE_FLAG), %esi
140 movl %fs:PRIVATE_FUTEX, %esi
143 # error "cc destroyed by following orl"
144 orl $FUTEX_WAIT, %esi
149 movq dep_mutex-cond_futex(%rdi), %r8
150 /* Requeue to a PI mutex if the PI bit is set. */
151 testl $PI_BIT, MUTEX_KIND(%r8)
154 movl $(FUTEX_WAIT_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %esi
155 movl $SYS_futex, %eax
159 #ifdef __ASSUME_REQUEUE_PI
165 movl $(FUTEX_WAIT|FUTEX_PRIVATE_FLAG), %esi
168 60: xorl %r13d, %r13d
169 movl $SYS_futex, %eax
172 62: movl (%rsp), %edi
173 callq __pthread_disable_asynccancel
182 cmpxchgl %esi, (%rdi)
184 cmpxchgl %esi, cond_lock(%rdi)
188 6: movl broadcast_seq(%rdi), %edx
190 movq woken_seq(%rdi), %rax
192 movq wakeup_seq(%rdi), %r9
206 16: subl $(1 << nwaiters_shift), cond_nwaiters(%rdi)
208 /* Wake up a thread which wants to destroy the condvar object. */
209 cmpq $0xffffffffffffffff, total_seq(%rdi)
211 movl cond_nwaiters(%rdi), %eax
212 andl $~((1 << nwaiters_shift) - 1), %eax
215 addq $cond_nwaiters, %rdi
216 cmpq $-1, dep_mutex-cond_nwaiters(%rdi)
218 #ifdef __ASSUME_PRIVATE_FUTEX
219 movl $FUTEX_WAKE, %eax
220 movl $(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi
224 movl %fs:PRIVATE_FUTEX, %esi
226 orl $FUTEX_WAKE, %esi
228 movl $SYS_futex, %eax
230 subq $cond_nwaiters, %rdi
240 /* If requeue_pi is used the kernel performs the locking of the
247 callq __pthread_mutex_cond_lock
249 14: addq $FRAME_SIZE, %rsp
250 cfi_adjust_cfa_offset(-FRAME_SIZE)
253 cfi_adjust_cfa_offset(-8)
256 cfi_adjust_cfa_offset(-8)
259 /* We return the result of the mutex_lock operation. */
262 /* Initial locking failed. */
264 cfi_adjust_cfa_offset(16 + FRAME_SIZE)
265 cfi_rel_offset(%r12, FRAME_SIZE + 8)
266 cfi_rel_offset(%r13, FRAME_SIZE)
268 addq $cond_lock, %rdi
270 cmpq $-1, dep_mutex-cond_lock(%rdi)
271 movl $LLL_PRIVATE, %eax
272 movl $LLL_SHARED, %esi
274 callq __lll_lock_wait
277 /* Unlock in loop requires wakeup. */
280 addq $cond_lock, %rdi
282 cmpq $-1, dep_mutex-cond_lock(%rdi)
283 movl $LLL_PRIVATE, %eax
284 movl $LLL_SHARED, %esi
286 callq __lll_unlock_wake
289 /* Locking in loop failed. */
292 addq $cond_lock, %rdi
294 cmpq $-1, dep_mutex-cond_lock(%rdi)
295 movl $LLL_PRIVATE, %eax
296 movl $LLL_SHARED, %esi
298 callq __lll_lock_wait
300 subq $cond_lock, %rdi
304 /* Unlock after loop requires wakeup. */
307 addq $cond_lock, %rdi
309 cmpq $-1, dep_mutex-cond_lock(%rdi)
310 movl $LLL_PRIVATE, %eax
311 movl $LLL_SHARED, %esi
313 callq __lll_unlock_wake
316 /* The initial unlocking of the mutex failed. */
328 addq $cond_lock, %rdi
330 cmpq $-1, dep_mutex-cond_lock(%rdi)
331 movl $LLL_PRIVATE, %eax
332 movl $LLL_SHARED, %esi
334 callq __lll_unlock_wake
338 .size __pthread_cond_wait, .-__pthread_cond_wait
339 versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
344 .type __condvar_cleanup1, @function
345 .globl __condvar_cleanup1
346 .hidden __condvar_cleanup1
351 +--------------------------+
353 +--------------------------+
355 +--------------------------+
357 +--------------------------+
358 rsp + 16 | mutex pointer |
359 +--------------------------+
360 rsp + 8 | condvar pointer |
361 +--------------------------+
362 rsp + 4 | old broadcast_seq value |
363 +--------------------------+
364 rsp + 0 | old cancellation mode |
365 +--------------------------+
370 /* Get internal lock. */
376 cmpxchgl %esi, (%rdi)
378 cmpxchgl %esi, cond_lock(%rdi)
383 addq $cond_lock, %rdi
385 cmpq $-1, dep_mutex-cond_lock(%rdi)
386 movl $LLL_PRIVATE, %eax
387 movl $LLL_SHARED, %esi
389 callq __lll_lock_wait
391 subq $cond_lock, %rdi
394 1: movl broadcast_seq(%rdi), %edx
398 /* We increment the wakeup_seq counter only if it is lower than
399 total_seq. If this is not the case the thread was woken and
400 then canceled. In this case we ignore the signal. */
401 movq total_seq(%rdi), %rax
402 cmpq wakeup_seq(%rdi), %rax
404 incq wakeup_seq(%rdi)
405 incl cond_futex(%rdi)
406 6: incq woken_seq(%rdi)
408 3: subl $(1 << nwaiters_shift), cond_nwaiters(%rdi)
410 /* Wake up a thread which wants to destroy the condvar object. */
412 cmpq $0xffffffffffffffff, total_seq(%rdi)
414 movl cond_nwaiters(%rdi), %eax
415 andl $~((1 << nwaiters_shift) - 1), %eax
418 cmpq $-1, dep_mutex(%rdi)
419 leaq cond_nwaiters(%rdi), %rdi
421 #ifdef __ASSUME_PRIVATE_FUTEX
422 movl $FUTEX_WAKE, %eax
423 movl $(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi
427 movl %fs:PRIVATE_FUTEX, %esi
429 orl $FUTEX_WAKE, %esi
431 movl $SYS_futex, %eax
433 subq $cond_nwaiters, %rdi
444 addq $cond_lock, %rdi
446 cmpq $-1, dep_mutex-cond_lock(%rdi)
447 movl $LLL_PRIVATE, %eax
448 movl $LLL_SHARED, %esi
450 callq __lll_unlock_wake
452 /* Wake up all waiters to make sure no signal gets lost. */
455 addq $cond_futex, %rdi
456 cmpq $-1, dep_mutex-cond_futex(%rdi)
457 movl $0x7fffffff, %edx
458 #ifdef __ASSUME_PRIVATE_FUTEX
459 movl $FUTEX_WAKE, %eax
460 movl $(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi
464 movl %fs:PRIVATE_FUTEX, %esi
466 orl $FUTEX_WAKE, %esi
468 movl $SYS_futex, %eax
471 5: movq 16(%rsp), %rdi
472 callq __pthread_mutex_cond_lock
478 call _Unwind_Resume@PLT
482 .size __condvar_cleanup1, .-__condvar_cleanup1
485 .section .gcc_except_table,"a",@progbits
487 .byte DW_EH_PE_omit # @LPStart format
488 .byte DW_EH_PE_omit # @TType format
489 .byte DW_EH_PE_uleb128 # call-site format
490 .uleb128 .Lcstend-.Lcstbegin
492 .uleb128 .LcleanupSTART-.LSTARTCODE
493 .uleb128 .LcleanupEND-.LcleanupSTART
494 .uleb128 __condvar_cleanup1-.LSTARTCODE
496 .uleb128 .LcallUR-.LSTARTCODE
497 .uleb128 .LENDCODE-.LcallUR
504 .hidden DW.ref.__gcc_personality_v0
505 .weak DW.ref.__gcc_personality_v0
506 .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
508 .type DW.ref.__gcc_personality_v0, @object
509 .size DW.ref.__gcc_personality_v0, 8
510 DW.ref.__gcc_personality_v0:
511 .quad __gcc_personality_v0