1 /* Copyright (C) 2002, 2003 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
47 /* Get internal lock. */
54 xaddl %eax, cond_lock(%ebx)
62 leal cond_lock(%ebx), %ecx
64 call __lll_mutex_lock_wait
66 1: addl $wakeup_seq, %ebx
70 addl $1, woken_seq-wakeup_seq(%ebx)
71 adcl $0, woken_seq-wakeup_seq+4(%ebx)
74 subl $1, cond_lock-wakeup_seq(%ebx)
77 leal cond_lock-wakeup_seq(%ebx), %eax
78 call __lll_mutex_unlock_wake
80 /* Wake up all waiters to make sure no signal gets lost. */
81 2: movl $FUTEX_WAKE, %ecx
83 movl $0x7fffffff, %edx
86 /* Lock the mutex unless asynchronous cancellation is in effect. */
91 call __pthread_mutex_lock_internal
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
117 /* Get internal lock. */
123 xaddl %eax, cond_lock(%ebx)
128 /* Unlock the mutex. */
131 call __pthread_mutex_unlock_internal
136 addl $1, total_seq(%ebx)
137 adcl $0, total_seq+4(%ebx)
139 /* Install cancellation handler. */
141 call __i686.get_pc_thunk.cx
142 addl $_GLOBAL_OFFSET_TABLE_, %ecx
143 leal __condvar_cleanup@GOTOFF(%ecx), %eax
145 leal __condvar_cleanup, %eax
153 call __pthread_cleanup_push
155 /* Get and store current wakeup_seq value. */
157 movl wakeup_seq(%ebx), %edi
158 movl wakeup_seq+4(%ebx), %edx
161 /* Prepare structure passed to cancellation handler. */
170 subl $1, cond_lock(%ebx)
174 4: leal 8(%esp), %eax
175 call __pthread_enable_asynccancel_2
177 movl %esi, %ecx /* movl $FUTEX_WAIT, %ecx */
179 addl $wakeup_seq, %ebx
180 movl $SYS_futex, %eax
182 subl $wakeup_seq, %ebx
185 call __pthread_disable_asynccancel
193 xaddl %eax, cond_lock(%ebx)
198 6: movl woken_seq(%ebx), %eax
199 movl woken_seq+4(%ebx), %ecx
201 movl wakeup_seq(%ebx), %edi
202 movl wakeup_seq+4(%ebx), %edx
216 9: addl $1, woken_seq(%ebx)
217 adcl $0, woken_seq+4(%ebx)
223 subl $1, cond_lock(%ebx)
227 /* Remove cancellation handler. */
228 11: movl 20+CLEANUP_PREV(%esp), %edx
229 movl %edx, %gs:CLEANUP
231 /* Trick ahead: (%esp) contains the address of the mutex. */
232 call __pthread_mutex_lock_internal
243 /* We return the result of the mutex_lock operation. */
246 /* Initial locking failed. */
252 leal cond_lock(%ebx), %ecx
254 call __lll_mutex_lock_wait
257 /* Unlock in loop requires waekup. */
263 leal cond_lock(%ebx), %eax
265 call __lll_mutex_unlock_wake
268 /* Locking in loop failed. */
273 leal cond_lock(%ebx), %ecx
275 call __lll_mutex_lock_wait
278 /* Unlock after loop requires wakeup. */
283 leal cond_lock(%ebx), %eax
285 call __lll_mutex_unlock_wake
288 /* The initial unlocking of the mutex failed. */
296 subl $1, cond_lock(%ebx)
303 leal cond_lock(%ebx), %eax
305 call __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 string.
324 .ascii "\0" # NUL-terminated augmentation string.
326 .uleb128 1 # Code alignment factor.
327 .sleb128 -4 # Data alignment factor.
328 .byte 8 # Return address register column.
330 .uleb128 1 # Augmentation value length.
331 .byte 0x1b # Encoding: DW_EH_PE_pcrel
334 .byte 0x0c # DW_CFA_def_cfa
337 .byte 0x88 # DW_CFA_offset, column 0x8
342 .long .LENDFDE-.LSTARTFDE # Length of the FDE.
344 .long .LSTARTFDE-.LSTARTFRAME # CIE pointer.
346 .long .LSTARTCODE-. # PC-relative start address of the code
348 .long .LSTARTCODE # Start address of the code.
350 .long .LENDCODE-.LSTARTCODE # Length of the code.
352 .uleb128 0 # No augmentation data.
354 .byte 4 # DW_CFA_advance_loc4
355 .long .Lpush_edi-.LSTARTCODE
356 .byte 14 # DW_CFA_def_cfa_offset
358 .byte 4 # DW_CFA_advance_loc4
359 .long .Lpush_esi-.Lpush_edi
360 .byte 14 # DW_CFA_def_cfa_offset
362 .byte 4 # DW_CFA_advance_loc4
363 .long .Lpush_ebx-.Lpush_esi
364 .byte 14 # DW_CFA_def_cfa_offset
366 .byte 4 # DW_CFA_advance_loc4
367 .long .Lpush4-.Lpush_ebx
368 .byte 14 # DW_CFA_def_cfa_offset
370 .byte 4 # DW_CFA_advance_loc4
372 .byte 14 # DW_CFA_def_cfa_offset
374 .byte 4 # DW_CFA_advance_loc4
376 .byte 14 # DW_CFA_def_cfa_offset
378 .byte 4 # DW_CFA_advance_loc4
379 .long .Lpop_ebx-.Laddl
380 .byte 14 # DW_CFA_def_cfa_offset
382 .byte 4 # DW_CFA_advance_loc4
383 .long .Lpop_esi-.Lpop_ebx
384 .byte 14 # DW_CFA_def_cfa_offset
386 .byte 4 # DW_CFA_advance_loc4
387 .long .Lpop_edi-.Lpop_esi
388 .byte 14 # DW_CFA_def_cfa_offset
390 .byte 4 # DW_CFA_advance_loc4
391 .long .LSbl1-.Lpop_edi
392 .byte 14 # DW_CFA_def_cfa_offset
394 .byte 4 # DW_CFA_advance_loc4
396 .byte 14 # DW_CFA_def_cfa_offset
398 .byte 4 # DW_CFA_advance_loc4
400 .byte 14 # DW_CFA_def_cfa_offset
407 .section .gnu.linkonce.t.__i686.get_pc_thunk.cx,"ax",@progbits
408 .globl __i686.get_pc_thunk.cx
409 .hidden __i686.get_pc_thunk.cx
410 .type __i686.get_pc_thunk.cx,@function
411 __i686.get_pc_thunk.cx:
414 .size __i686.get_pc_thunk.cx,.-__i686.get_pc_thunk.cx