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>
38 /* int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex) */
39 .globl __pthread_cond_wait
40 .type __pthread_cond_wait, @function
55 /* Get internal lock. */
62 cmpxchgl %edx, cond_lock(%ebx)
66 /* Store the reference to the mutex. If there is already a
67 different value in there this is a bad user bug. */
68 2: cmpl $-1, dep_mutex(%ebx)
71 movl %eax, dep_mutex(%ebx)
73 /* Unlock the mutex. */
75 call __pthread_mutex_unlock_usercnt
80 addl $1, total_seq(%ebx)
81 adcl $0, total_seq+4(%ebx)
82 addl $1, cond_futex(%ebx)
83 addl $(1 << clock_bits), cond_nwaiters(%ebx)
86 subl $FRAME_SIZE, %esp
89 /* Get and store current wakeup_seq value. */
90 movl wakeup_seq(%ebx), %edi
91 movl wakeup_seq+4(%ebx), %edx
92 movl broadcast_seq(%ebx), %eax
97 8: movl cond_futex(%ebx), %edi
104 subl $1, cond_lock(%ebx)
109 4: call __pthread_enable_asynccancel
112 movl %esi, %ecx /* movl $FUTEX_WAIT, %ecx */
114 addl $cond_futex, %ebx
116 movl $SYS_futex, %eax
118 subl $cond_futex, %ebx
122 call __pthread_disable_asynccancel
130 cmpxchgl %edx, (%ebx)
132 cmpxchgl %edx, cond_lock(%ebx)
136 6: movl broadcast_seq(%ebx), %eax
140 movl woken_seq(%ebx), %eax
141 movl woken_seq+4(%ebx), %ecx
143 movl wakeup_seq(%ebx), %edi
144 movl wakeup_seq+4(%ebx), %edx
156 9: addl $1, woken_seq(%ebx)
157 adcl $0, woken_seq+4(%ebx)
160 16: subl $(1 << clock_bits), cond_nwaiters(%ebx)
162 /* Wake up a thread which wants to destroy the condvar object. */
163 movl total_seq(%ebx), %eax
164 andl total_seq+4(%ebx), %eax
165 cmpl $0xffffffff, %eax
167 movl cond_nwaiters(%ebx), %eax
168 andl $~((1 << clock_bits) - 1), %eax
171 addl $cond_nwaiters, %ebx
172 movl $SYS_futex, %eax
173 movl $FUTEX_WAKE, %ecx
176 subl $cond_nwaiters, %ebx
182 subl $1, cond_lock(%ebx)
186 11: movl 20+FRAME_SIZE(%esp), %eax
187 call __pthread_mutex_cond_lock
188 addl $FRAME_SIZE, %esp
198 /* We return the result of the mutex_lock operation. */
201 /* Initial locking failed. */
207 leal cond_lock(%ebx), %ecx
209 call __lll_mutex_lock_wait
212 /* Unlock in loop requires waekup. */
218 leal cond_lock(%ebx), %eax
220 call __lll_mutex_unlock_wake
223 /* Locking in loop failed. */
228 leal cond_lock(%ebx), %ecx
230 call __lll_mutex_lock_wait
233 /* Unlock after loop requires wakeup. */
238 leal cond_lock(%ebx), %eax
240 call __lll_mutex_unlock_wake
243 /* The initial unlocking of the mutex failed. */
250 subl $1, cond_lock(%ebx)
258 leal cond_lock(%ebx), %eax
260 call __lll_mutex_unlock_wake
264 .size __pthread_cond_wait, .-__pthread_cond_wait
265 versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
269 .type __condvar_w_cleanup2, @function
270 __condvar_w_cleanup2:
271 subl $cond_futex, %ebx
272 .size __condvar_w_cleanup2, .-__condvar_w_cleanup2
274 .type __condvar_w_cleanup, @function
278 /* Get internal lock. */
283 cmpxchgl %edx, (%ebx)
285 cmpxchgl %edx, cond_lock(%ebx)
292 leal cond_lock(%ebx), %ecx
294 call __lll_mutex_lock_wait
296 1: movl broadcast_seq(%ebx), %eax
300 addl $1, wakeup_seq(%ebx)
301 adcl $0, wakeup_seq+4(%ebx)
303 addl $1, cond_futex(%ebx)
305 addl $1, woken_seq(%ebx)
306 adcl $0, woken_seq+4(%ebx)
308 3: subl $(1 << clock_bits), cond_nwaiters(%ebx)
310 /* Wake up a thread which wants to destroy the condvar object. */
312 movl total_seq(%ebx), %eax
313 andl total_seq+4(%ebx), %eax
314 cmpl $0xffffffff, %eax
316 movl cond_nwaiters(%ebx), %eax
317 andl $~((1 << clock_bits) - 1), %eax
320 addl $cond_nwaiters, %ebx
321 movl $SYS_futex, %eax
322 movl $FUTEX_WAKE, %ecx
325 subl $cond_nwaiters, %ebx
332 subl $1, cond_lock(%ebx)
339 leal cond_lock(%ebx), %eax
341 call __lll_mutex_unlock_wake
343 /* Wake up all waiters to make sure no signal gets lost. */
346 addl $cond_futex, %ebx
347 movl $FUTEX_WAKE, %ecx
348 movl $SYS_futex, %eax
349 movl $0x7fffffff, %edx
352 5: movl 20+FRAME_SIZE(%esp), %eax
353 call __pthread_mutex_cond_lock
360 .size __condvar_w_cleanup, .-__condvar_w_cleanup
363 .section .gcc_except_table,"a",@progbits
365 .byte 0xff # @LPStart format (omit)
366 .byte 0xff # @TType format (omit)
367 .byte 0x0b # call-site format
369 .uleb128 .Lcstend-.Lcstbegin
371 .long .LcleanupSTART-.LSTARTCODE
372 .long .Ladd_cond_futex-.LcleanupSTART
373 .long __condvar_w_cleanup-.LSTARTCODE
375 .long .Ladd_cond_futex-.LSTARTCODE
376 .long .Lsub_cond_futex-.Ladd_cond_futex
377 .long __condvar_w_cleanup2-.LSTARTCODE
379 .long .Lsub_cond_futex-.LSTARTCODE
380 .long .LcleanupEND-.Lsub_cond_futex
381 .long __condvar_w_cleanup-.LSTARTCODE
383 .long .LcallUR-.LSTARTCODE
384 .long .LENDCODE-.LcallUR
389 .section .eh_frame,"a",@progbits
391 .long L(ENDCIE)-L(STARTCIE) # Length of the CIE.
394 .byte 1 # Version number.
396 .string "zPLR" # NUL-terminated augmentation
399 .string "zPL" # NUL-terminated augmentation
402 .uleb128 1 # Code alignment factor.
403 .sleb128 -4 # Data alignment factor.
404 .byte 8 # Return address register
407 .uleb128 7 # Augmentation value length.
408 .byte 0x9b # Personality: DW_EH_PE_pcrel
410 # + DW_EH_PE_indirect
411 .long DW.ref.__gcc_personality_v0-.
412 .byte 0x1b # LSDA Encoding: DW_EH_PE_pcrel
414 .byte 0x1b # FDE Encoding: DW_EH_PE_pcrel
417 .uleb128 6 # Augmentation value length.
418 .byte 0x0 # Personality: absolute
419 .long __gcc_personality_v0
420 .byte 0x0 # LSDA Encoding: absolute
422 .byte 0x0c # DW_CFA_def_cfa
425 .byte 0x88 # DW_CFA_offset, column 0x8
430 .long .LENDFDE-.LSTARTFDE # Length of the FDE.
432 .long .LSTARTFDE-.LSTARTFRAME # CIE pointer.
434 .long .LSTARTCODE-. # PC-relative start address
437 .long .LSTARTCODE # Start address of the code.
439 .long .LENDCODE-.LSTARTCODE # Length of the code.
440 .uleb128 4 # Augmentation size
442 .long .LexceptSTART-.
446 .byte 0x40+.Lpush_edi-.LSTARTCODE # DW_CFA_advance_loc+N
447 .byte 14 # DW_CFA_def_cfa_offset
449 .byte 0x87 # DW_CFA_offset %edi
451 .byte 0x40+.Lpush_esi-.Lpush_edi # DW_CFA_advance_loc+N
452 .byte 14 # DW_CFA_def_cfa_offset
454 .byte 0x86 # DW_CFA_offset %esi
456 .byte 0x40+.Lpush_ebx-.Lpush_esi # DW_CFA_advance_loc+N
457 .byte 14 # DW_CFA_def_cfa_offset
459 .byte 0x83 # DW_CFA_offset %ebx
461 .byte 2 # DW_CFA_advance_loc1
462 .byte .Lsubl-.Lpush_ebx
463 .byte 14 # DW_CFA_def_cfa_offset
464 .uleb128 16+FRAME_SIZE
465 .byte 2 # DW_CFA_advance_loc1
467 .byte 14 # DW_CFA_def_cfa_offset
469 .byte 0x40+ .Lpop_ebx-.Laddl # DW_CFA_advance_loc+N
470 .byte 14 # DW_CFA_def_cfa_offset
472 .byte 0xc3 # DW_CFA_restore %ebx
473 .byte 0x40+.Lpop_esi-.Lpop_ebx # DW_CFA_advance_loc+N
474 .byte 14 # DW_CFA_def_cfa_offset
476 .byte 0xc6 # DW_CFA_restore %esi
477 .byte 0x40+.Lpop_edi-.Lpop_esi # DW_CFA_advance_loc+N
478 .byte 14 # DW_CFA_def_cfa_offset
480 .byte 0xc7 # DW_CFA_restore %edi
481 .byte 0x40+.LSbl1-.Lpop_edi # DW_CFA_advance_loc+N
482 .byte 14 # DW_CFA_def_cfa_offset
484 .byte 0x87 # DW_CFA_offset %edi
486 .byte 0x86 # DW_CFA_offset %esi
488 .byte 0x83 # DW_CFA_offset %ebx
490 .byte 0x40+.LSbl2-.LSbl1 # DW_CFA_advance_loc+N
491 .byte 14 # DW_CFA_def_cfa_offset
492 .uleb128 16+FRAME_SIZE
493 .byte 0x40+.LSbl3-.LSbl2 # DW_CFA_advance_loc+N
494 .byte 14 # DW_CFA_def_cfa_offset
496 .byte 0x40+.LSbl4-.LSbl3 # DW_CFA_advance_loc+N
497 .byte 14 # DW_CFA_def_cfa_offset
498 .uleb128 16+FRAME_SIZE
504 .section .gnu.linkonce.t.__i686.get_pc_thunk.cx,"ax",@progbits
505 .globl __i686.get_pc_thunk.cx
506 .hidden __i686.get_pc_thunk.cx
507 .type __i686.get_pc_thunk.cx,@function
508 __i686.get_pc_thunk.cx:
511 .size __i686.get_pc_thunk.cx,.-__i686.get_pc_thunk.cx
515 .hidden DW.ref.__gcc_personality_v0
516 .weak DW.ref.__gcc_personality_v0
517 .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
519 .type DW.ref.__gcc_personality_v0, @object
520 .size DW.ref.__gcc_personality_v0, 4
521 DW.ref.__gcc_personality_v0:
522 .long __gcc_personality_v0