1 /* Copyright (C) 2002, 2003, 2004 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
43 /* Get internal lock. */
52 cmpxchgl %esi, cond_lock(%rdi)
59 callq __lll_mutex_lock_wait
64 1: movl broadcast_seq(%rdi), %edx
84 callq __lll_mutex_unlock_wake
86 /* Wake up all waiters to make sure no signal gets lost. */
87 2: addq $cond_futex, %rdi
88 movq $FUTEX_WAKE, %rsi
89 movl $0x7fffffff, %edx
94 callq __pthread_mutex_cond_lock
97 .size __condvar_cleanup, .-__condvar_cleanup
100 /* int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex) */
101 .globl __pthread_cond_wait
102 .type __pthread_cond_wait, @function
108 #define FRAME_SIZE 64
109 subq $FRAME_SIZE, %rsp
114 +--------------------------+
115 rsp + 32 | cleanup buffer |
116 +--------------------------+
117 rsp + 24 | old wake_seq value |
118 +--------------------------+
119 rsp + 16 | mutex pointer |
120 +--------------------------+
121 rsp + 8 | condvar pointer |
122 +--------------------------+
123 rsp + 4 | old broadcast_seq value |
124 +--------------------------+
125 rsp + 0 | old cancellation mode |
126 +--------------------------+
129 cmpq $-1, dep_mutex(%rdi)
131 /* Prepare structure passed to cancellation handler. */
136 movq %rsi, dep_mutex(%rdi)
138 /* Get internal lock. */
143 cmpxchgl %esi, (%rdi)
145 cmpxchgl %esi, cond_lock(%rdi)
149 /* Unlock the mutex. */
150 2: movq 16(%rsp), %rdi
152 callq __pthread_mutex_unlock_usercnt
159 incl cond_futex(%rdi)
161 /* Install cancellation handler. */
163 leaq __condvar_cleanup(%rip), %rsi
165 leaq __condvar_cleanup, %rsi
169 callq __pthread_cleanup_push
171 /* Get and store current wakeup_seq value. */
173 movq wakeup_seq(%rdi), %r9
174 movl broadcast_seq(%rdi), %edx
179 8: movl cond_futex(%rdi), %r12d
188 4: callq __pthread_enable_asynccancel
194 addq $cond_futex-cond_lock, %rdi
195 movq $SYS_futex, %rax
196 movq %r10, %rsi /* movq $FUTEX_WAIT, %rsi */
200 callq __pthread_disable_asynccancel
208 cmpxchgl %esi, (%rdi)
210 cmpxchgl %esi, cond_lock(%rdi)
214 6: movl broadcast_seq(%rdi), %edx
216 movq woken_seq(%rdi), %rax
218 movq wakeup_seq(%rdi), %r9
240 /* Remove cancellation handler. */
241 11: movq 32+CLEANUP_PREV(%rsp), %rdx
242 movq %rdx, %fs:CLEANUP
245 callq __pthread_mutex_cond_lock
246 14: addq $FRAME_SIZE, %rsp
252 /* We return the result of the mutex_lock operation. */
255 /* Initial locking failed. */
259 addq $cond_lock, %rdi
261 callq __lll_mutex_lock_wait
264 /* Unlock in loop requires wakeup. */
267 addq $cond_lock, %rdi
269 callq __lll_mutex_unlock_wake
272 /* Locking in loop failed. */
275 addq $cond_lock, %rdi
277 callq __lll_mutex_lock_wait
279 subq $cond_lock, %rdi
283 /* Unlock after loop requires wakeup. */
286 addq $cond_lock, %rdi
288 callq __lll_mutex_unlock_wake
291 /* The initial unlocking of the mutex failed. */
303 addq $cond_lock, %rdi
305 callq __lll_mutex_unlock_wake
310 .size __pthread_cond_wait, .-__pthread_cond_wait
311 versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
315 .section .eh_frame,"a",@progbits
317 .long L(ENDCIE)-L(STARTCIE) # Length of the CIE.
320 .byte 1 # Version number.
322 .string "zR" # NUL-terminated augmentation
325 .ascii "\0" # NUL-terminated augmentation
328 .uleb128 1 # Code alignment factor.
329 .sleb128 -8 # Data alignment factor.
330 .byte 16 # Return address register
333 .uleb128 1 # Augmentation value length.
334 .byte 0x1b # Encoding: DW_EH_PE_pcrel
337 .byte 0x0c # DW_CFA_def_cfa
340 .byte 0x90 # DW_CFA_offset, column 0x8
345 .long .LENDFDE-.LSTARTFDE # Length of the FDE.
347 .long .LSTARTFDE-.LSTARTFRAME # CIE pointer.
349 .long .LSTARTCODE-. # PC-relative start address
352 .long .LSTARTCODE # Start address of the code.
354 .long .LENDCODE-.LSTARTCODE # Length of the code.
356 .uleb128 0 # No augmentation data.
358 .byte 0x40+.Lpush_r12-.LSTARTCODE # DW_CFA_advance_loc+N
359 .byte 14 # DW_CFA_def_cfa_offset
361 .byte 0x8c # DW_CFA_offset %r12
363 .byte 0x40+.Lsubq-.Lpush_r12 # DW_CFA_advance_loc+N
364 .byte 14 # DW_CFA_def_cfa_offset
365 .uleb128 16+FRAME_SIZE
366 .byte 3 # DW_CFA_advance_loc2
368 .byte 14 # DW_CFA_def_cfa_offset
370 .byte 0x40+.Lpop_r12-.Laddq # DW_CFA_advance_loc+N
371 .byte 14 # DW_CFA_def_cfa_offset
373 .byte 0xcc # DW_CFA_restore %r12
374 .byte 0x40+.LSbl1-.Lpop_r12 # DW_CFA_advance_loc+N
375 .byte 14 # DW_CFA_def_cfa_offset
377 .byte 0x8c # DW_CFA_offset %r12