1 /* Copyright (C) 2002, 2003, 2004, 2006 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 /* We increment the wakeup_seq counter only if it is lower than
301 total_seq. If this is not the case the thread was woken and
302 then canceled. In this case we ignore the signal. */
303 movl total_seq(%ebx), %eax
304 movl total_seq+4(%ebx), %edi
305 cmpl wakeup_seq+4(%ebx), %edi
308 cmpl wakeup_seq(%ebx), %eax
311 6: addl $1, wakeup_seq(%ebx)
312 adcl $0, wakeup_seq+4(%ebx)
313 addl $1, cond_futex(%ebx)
315 7: addl $1, woken_seq(%ebx)
316 adcl $0, woken_seq+4(%ebx)
318 3: subl $(1 << clock_bits), cond_nwaiters(%ebx)
320 /* Wake up a thread which wants to destroy the condvar object. */
322 movl total_seq(%ebx), %eax
323 andl total_seq+4(%ebx), %eax
324 cmpl $0xffffffff, %eax
326 movl cond_nwaiters(%ebx), %eax
327 andl $~((1 << clock_bits) - 1), %eax
330 addl $cond_nwaiters, %ebx
331 movl $SYS_futex, %eax
332 movl $FUTEX_WAKE, %ecx
335 subl $cond_nwaiters, %ebx
342 subl $1, cond_lock(%ebx)
349 leal cond_lock(%ebx), %eax
351 call __lll_mutex_unlock_wake
353 /* Wake up all waiters to make sure no signal gets lost. */
356 addl $cond_futex, %ebx
357 movl $FUTEX_WAKE, %ecx
358 movl $SYS_futex, %eax
359 movl $0x7fffffff, %edx
362 5: movl 20+FRAME_SIZE(%esp), %eax
363 call __pthread_mutex_cond_lock
370 .size __condvar_w_cleanup, .-__condvar_w_cleanup
373 .section .gcc_except_table,"a",@progbits
375 .byte 0xff # @LPStart format (omit)
376 .byte 0xff # @TType format (omit)
377 .byte 0x0b # call-site format
379 .uleb128 .Lcstend-.Lcstbegin
381 .long .LcleanupSTART-.LSTARTCODE
382 .long .Ladd_cond_futex-.LcleanupSTART
383 .long __condvar_w_cleanup-.LSTARTCODE
385 .long .Ladd_cond_futex-.LSTARTCODE
386 .long .Lsub_cond_futex-.Ladd_cond_futex
387 .long __condvar_w_cleanup2-.LSTARTCODE
389 .long .Lsub_cond_futex-.LSTARTCODE
390 .long .LcleanupEND-.Lsub_cond_futex
391 .long __condvar_w_cleanup-.LSTARTCODE
393 .long .LcallUR-.LSTARTCODE
394 .long .LENDCODE-.LcallUR
399 .section .eh_frame,"a",@progbits
401 .long L(ENDCIE)-L(STARTCIE) # Length of the CIE.
404 .byte 1 # Version number.
406 .string "zPLR" # NUL-terminated augmentation
409 .string "zPL" # NUL-terminated augmentation
412 .uleb128 1 # Code alignment factor.
413 .sleb128 -4 # Data alignment factor.
414 .byte 8 # Return address register
417 .uleb128 7 # Augmentation value length.
418 .byte 0x9b # Personality: DW_EH_PE_pcrel
420 # + DW_EH_PE_indirect
421 .long DW.ref.__gcc_personality_v0-.
422 .byte 0x1b # LSDA Encoding: DW_EH_PE_pcrel
424 .byte 0x1b # FDE Encoding: DW_EH_PE_pcrel
427 .uleb128 6 # Augmentation value length.
428 .byte 0x0 # Personality: absolute
429 .long __gcc_personality_v0
430 .byte 0x0 # LSDA Encoding: absolute
432 .byte 0x0c # DW_CFA_def_cfa
435 .byte 0x88 # DW_CFA_offset, column 0x8
440 .long .LENDFDE-.LSTARTFDE # Length of the FDE.
442 .long .LSTARTFDE-.LSTARTFRAME # CIE pointer.
444 .long .LSTARTCODE-. # PC-relative start address
447 .long .LSTARTCODE # Start address of the code.
449 .long .LENDCODE-.LSTARTCODE # Length of the code.
450 .uleb128 4 # Augmentation size
452 .long .LexceptSTART-.
456 .byte 0x40+.Lpush_edi-.LSTARTCODE # DW_CFA_advance_loc+N
457 .byte 14 # DW_CFA_def_cfa_offset
459 .byte 0x87 # DW_CFA_offset %edi
461 .byte 0x40+.Lpush_esi-.Lpush_edi # DW_CFA_advance_loc+N
462 .byte 14 # DW_CFA_def_cfa_offset
464 .byte 0x86 # DW_CFA_offset %esi
466 .byte 0x40+.Lpush_ebx-.Lpush_esi # DW_CFA_advance_loc+N
467 .byte 14 # DW_CFA_def_cfa_offset
469 .byte 0x83 # DW_CFA_offset %ebx
471 .byte 2 # DW_CFA_advance_loc1
472 .byte .Lsubl-.Lpush_ebx
473 .byte 14 # DW_CFA_def_cfa_offset
474 .uleb128 16+FRAME_SIZE
475 .byte 2 # DW_CFA_advance_loc1
477 .byte 14 # DW_CFA_def_cfa_offset
479 .byte 0x40+ .Lpop_ebx-.Laddl # DW_CFA_advance_loc+N
480 .byte 14 # DW_CFA_def_cfa_offset
482 .byte 0xc3 # DW_CFA_restore %ebx
483 .byte 0x40+.Lpop_esi-.Lpop_ebx # DW_CFA_advance_loc+N
484 .byte 14 # DW_CFA_def_cfa_offset
486 .byte 0xc6 # DW_CFA_restore %esi
487 .byte 0x40+.Lpop_edi-.Lpop_esi # DW_CFA_advance_loc+N
488 .byte 14 # DW_CFA_def_cfa_offset
490 .byte 0xc7 # DW_CFA_restore %edi
491 .byte 0x40+.LSbl1-.Lpop_edi # DW_CFA_advance_loc+N
492 .byte 14 # DW_CFA_def_cfa_offset
494 .byte 0x87 # DW_CFA_offset %edi
496 .byte 0x86 # DW_CFA_offset %esi
498 .byte 0x83 # DW_CFA_offset %ebx
500 .byte 0x40+.LSbl2-.LSbl1 # DW_CFA_advance_loc+N
501 .byte 14 # DW_CFA_def_cfa_offset
502 .uleb128 16+FRAME_SIZE
503 .byte 0x40+.LSbl3-.LSbl2 # DW_CFA_advance_loc+N
504 .byte 14 # DW_CFA_def_cfa_offset
506 .byte 0x40+.LSbl4-.LSbl3 # DW_CFA_advance_loc+N
507 .byte 14 # DW_CFA_def_cfa_offset
508 .uleb128 16+FRAME_SIZE
514 .section .gnu.linkonce.t.__i686.get_pc_thunk.cx,"ax",@progbits
515 .globl __i686.get_pc_thunk.cx
516 .hidden __i686.get_pc_thunk.cx
517 .type __i686.get_pc_thunk.cx,@function
518 __i686.get_pc_thunk.cx:
521 .size __i686.get_pc_thunk.cx,.-__i686.get_pc_thunk.cx
525 .hidden DW.ref.__gcc_personality_v0
526 .weak DW.ref.__gcc_personality_v0
527 .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
529 .type DW.ref.__gcc_personality_v0, @object
530 .size DW.ref.__gcc_personality_v0, 4
531 DW.ref.__gcc_personality_v0:
532 .long __gcc_personality_v0