1 /* Copyright (C) 2002,2003,2004,2005,2006,2007 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 <lowlevelcond.h>
23 #include <tcb-offsets.h>
39 .type __condvar_cleanup, @function
40 .globl __condvar_cleanup
41 .hidden __condvar_cleanup
45 /* Get internal lock. */
54 cmpxchgl %esi, cond_lock(%rdi)
61 callq __lll_mutex_lock_wait
66 1: movl broadcast_seq(%rdi), %edx
70 /* We increment the wakeup_seq counter only if it is lower than
71 total_seq. If this is not the case the thread was woken and
72 then canceled. In this case we ignore the signal. */
73 movq total_seq(%rdi), %rax
74 cmpq wakeup_seq(%rdi), %rax
78 6: incq woken_seq(%rdi)
80 3: subl $(1 << nwaiters_shift), cond_nwaiters(%rdi)
82 /* Wake up a thread which wants to destroy the condvar object. */
84 cmpq $0xffffffffffffffff, total_seq(%rdi)
86 movl cond_nwaiters(%rdi), %eax
87 andl $~((1 << nwaiters_shift) - 1), %eax
90 addq $cond_nwaiters, %rdi
92 movl $FUTEX_WAKE, %esi
95 subq $cond_nwaiters, %rdi
106 addq $cond_lock, %rdi
108 callq __lll_mutex_unlock_wake
110 /* Wake up all waiters to make sure no signal gets lost. */
113 addq $cond_futex, %rdi
114 movl $FUTEX_WAKE, %esi
115 movl $0x7fffffff, %edx
116 movl $SYS_futex, %eax
119 5: movq 16(%r8), %rdi
120 callq __pthread_mutex_cond_lock
125 .size __condvar_cleanup, .-__condvar_cleanup
128 /* int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex) */
129 .globl __pthread_cond_wait
130 .type __pthread_cond_wait, @function
136 #define FRAME_SIZE 64
137 subq $FRAME_SIZE, %rsp
142 +--------------------------+
143 rsp + 32 | cleanup buffer |
144 +--------------------------+
145 rsp + 24 | old wake_seq value |
146 +--------------------------+
147 rsp + 16 | mutex pointer |
148 +--------------------------+
149 rsp + 8 | condvar pointer |
150 +--------------------------+
151 rsp + 4 | old broadcast_seq value |
152 +--------------------------+
153 rsp + 0 | old cancellation mode |
154 +--------------------------+
157 cmpq $-1, dep_mutex(%rdi)
159 /* Prepare structure passed to cancellation handler. */
164 movq %rsi, dep_mutex(%rdi)
166 /* Get internal lock. */
171 cmpxchgl %esi, (%rdi)
173 cmpxchgl %esi, cond_lock(%rdi)
177 /* Unlock the mutex. */
178 2: movq 16(%rsp), %rdi
180 callq __pthread_mutex_unlock_usercnt
187 incl cond_futex(%rdi)
188 addl $(1 << nwaiters_shift), cond_nwaiters(%rdi)
190 /* Install cancellation handler. */
192 leaq __condvar_cleanup(%rip), %rsi
194 leaq __condvar_cleanup, %rsi
198 callq __pthread_cleanup_push
200 /* Get and store current wakeup_seq value. */
202 movq wakeup_seq(%rdi), %r9
203 movl broadcast_seq(%rdi), %edx
208 8: movl cond_futex(%rdi), %r12d
217 4: callq __pthread_enable_asynccancel
223 addq $cond_futex-cond_lock, %rdi
224 movl $SYS_futex, %eax
228 movl $FUTEX_WAIT, %esi
233 callq __pthread_disable_asynccancel
241 cmpxchgl %esi, (%rdi)
243 cmpxchgl %esi, cond_lock(%rdi)
247 6: movl broadcast_seq(%rdi), %edx
249 movq woken_seq(%rdi), %rax
251 movq wakeup_seq(%rdi), %r9
265 16: subl $(1 << nwaiters_shift), cond_nwaiters(%rdi)
267 /* Wake up a thread which wants to destroy the condvar object. */
268 cmpq $0xffffffffffffffff, total_seq(%rdi)
270 movl cond_nwaiters(%rdi), %eax
271 andl $~((1 << nwaiters_shift) - 1), %eax
274 addq $cond_nwaiters, %rdi
275 movl $SYS_futex, %eax
276 movl $FUTEX_WAKE, %esi
279 subq $cond_nwaiters, %rdi
289 /* Remove cancellation handler. */
290 11: movq 32+CLEANUP_PREV(%rsp), %rdx
291 movq %rdx, %fs:CLEANUP
294 callq __pthread_mutex_cond_lock
295 14: addq $FRAME_SIZE, %rsp
301 /* We return the result of the mutex_lock operation. */
304 /* Initial locking failed. */
308 addq $cond_lock, %rdi
310 callq __lll_mutex_lock_wait
313 /* Unlock in loop requires wakeup. */
316 addq $cond_lock, %rdi
318 callq __lll_mutex_unlock_wake
321 /* Locking in loop failed. */
324 addq $cond_lock, %rdi
326 callq __lll_mutex_lock_wait
328 subq $cond_lock, %rdi
332 /* Unlock after loop requires wakeup. */
335 addq $cond_lock, %rdi
337 callq __lll_mutex_unlock_wake
340 /* The initial unlocking of the mutex failed. */
352 addq $cond_lock, %rdi
354 callq __lll_mutex_unlock_wake
359 .size __pthread_cond_wait, .-__pthread_cond_wait
360 versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
364 .section .eh_frame,"a",@progbits
366 .long L(ENDCIE)-L(STARTCIE) # Length of the CIE.
369 .byte 1 # Version number.
371 .string "zR" # NUL-terminated augmentation
374 .ascii "\0" # NUL-terminated augmentation
377 .uleb128 1 # Code alignment factor.
378 .sleb128 -8 # Data alignment factor.
379 .byte 16 # Return address register
382 .uleb128 1 # Augmentation value length.
383 .byte 0x1b # Encoding: DW_EH_PE_pcrel
386 .byte 0x0c # DW_CFA_def_cfa
389 .byte 0x90 # DW_CFA_offset, column 0x8
394 .long .LENDFDE-.LSTARTFDE # Length of the FDE.
396 .long .LSTARTFDE-.LSTARTFRAME # CIE pointer.
398 .long .LSTARTCODE-. # PC-relative start address
401 .long .LSTARTCODE # Start address of the code.
403 .long .LENDCODE-.LSTARTCODE # Length of the code.
405 .uleb128 0 # No augmentation data.
407 .byte 0x40+.Lpush_r12-.LSTARTCODE # DW_CFA_advance_loc+N
408 .byte 14 # DW_CFA_def_cfa_offset
410 .byte 0x8c # DW_CFA_offset %r12
412 .byte 0x40+.Lsubq-.Lpush_r12 # DW_CFA_advance_loc+N
413 .byte 14 # DW_CFA_def_cfa_offset
414 .uleb128 16+FRAME_SIZE
415 .byte 3 # DW_CFA_advance_loc2
417 .byte 14 # DW_CFA_def_cfa_offset
419 .byte 0x40+.Lpop_r12-.Laddq # DW_CFA_advance_loc+N
420 .byte 14 # DW_CFA_def_cfa_offset
422 .byte 0xcc # DW_CFA_restore %r12
423 .byte 0x40+.LSbl1-.Lpop_r12 # DW_CFA_advance_loc+N
424 .byte 14 # DW_CFA_def_cfa_offset
426 .byte 0x8c # DW_CFA_offset %r12