1 /* Copyright (C) 2002, 2003, 2004, 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 <lowlevellock.h>
23 #include <lowlevelcond.h>
24 #include <tcb-offsets.h>
25 #include <kernel-features.h>
30 /* int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex) */
31 .globl __pthread_cond_wait
32 .type __pthread_cond_wait, @function
47 /* Get internal lock. */
54 cmpxchgl %edx, cond_lock(%ebx)
58 /* Store the reference to the mutex. If there is already a
59 different value in there this is a bad user bug. */
60 2: cmpl $-1, dep_mutex(%ebx)
63 movl %eax, dep_mutex(%ebx)
65 /* Unlock the mutex. */
67 call __pthread_mutex_unlock_usercnt
72 addl $1, total_seq(%ebx)
73 adcl $0, total_seq+4(%ebx)
74 addl $1, cond_futex(%ebx)
75 addl $(1 << nwaiters_shift), cond_nwaiters(%ebx)
78 subl $FRAME_SIZE, %esp
81 /* Get and store current wakeup_seq value. */
82 movl wakeup_seq(%ebx), %edi
83 movl wakeup_seq+4(%ebx), %edx
84 movl broadcast_seq(%ebx), %eax
89 8: movl cond_futex(%ebx), %edi
96 subl $1, cond_lock(%ebx)
101 4: call __pthread_enable_asynccancel
104 #if FUTEX_PRIVATE_FLAG > 255
107 cmpl $-1, dep_mutex(%ebx)
110 #ifdef __ASSUME_PRIVATE_FUTEX
111 andl $FUTEX_PRIVATE_FLAG, %ecx
113 andl %gs:PRIVATE_FUTEX, %ecx
116 addl $FUTEX_WAIT, %ecx
119 addl $cond_futex, %ebx
121 movl $SYS_futex, %eax
123 subl $cond_futex, %ebx
127 call __pthread_disable_asynccancel
135 cmpxchgl %edx, (%ebx)
137 cmpxchgl %edx, cond_lock(%ebx)
141 6: movl broadcast_seq(%ebx), %eax
145 movl woken_seq(%ebx), %eax
146 movl woken_seq+4(%ebx), %ecx
148 movl wakeup_seq(%ebx), %edi
149 movl wakeup_seq+4(%ebx), %edx
161 9: addl $1, woken_seq(%ebx)
162 adcl $0, woken_seq+4(%ebx)
165 16: subl $(1 << nwaiters_shift), cond_nwaiters(%ebx)
167 /* Wake up a thread which wants to destroy the condvar object. */
168 movl total_seq(%ebx), %eax
169 andl total_seq+4(%ebx), %eax
170 cmpl $0xffffffff, %eax
172 movl cond_nwaiters(%ebx), %eax
173 andl $~((1 << nwaiters_shift) - 1), %eax
176 addl $cond_nwaiters, %ebx
177 movl $SYS_futex, %eax
178 #if FUTEX_PRIVATE_FLAG > 255
181 cmpl $-1, dep_mutex-cond_nwaiters(%ebx)
184 #ifdef __ASSUME_PRIVATE_FUTEX
185 andl $FUTEX_PRIVATE_FLAG, %ecx
187 andl %gs:PRIVATE_FUTEX, %ecx
189 addl $FUTEX_WAKE, %ecx
192 subl $cond_nwaiters, %ebx
198 subl $1, cond_lock(%ebx)
202 11: movl 20+FRAME_SIZE(%esp), %eax
203 call __pthread_mutex_cond_lock
204 addl $FRAME_SIZE, %esp
214 /* We return the result of the mutex_lock operation. */
217 /* Initial locking failed. */
223 leal cond_lock(%ebx), %edx
225 #if (LLL_SHARED-LLL_PRIVATE) > 255
228 cmpl $-1, dep_mutex(%ebx)
231 andl $(LLL_SHARED-LLL_PRIVATE), %ecx
233 addl $LLL_PRIVATE, %ecx
238 /* Unlock in loop requires waekup. */
244 leal cond_lock(%ebx), %eax
246 #if (LLL_SHARED-LLL_PRIVATE) > 255
249 cmpl $-1, dep_mutex(%ebx)
252 andl $(LLL_SHARED-LLL_PRIVATE), %ecx
254 addl $LLL_PRIVATE, %ecx
256 call __lll_unlock_wake
259 /* Locking in loop failed. */
264 leal cond_lock(%ebx), %edx
266 #if (LLL_SHARED-LLL_PRIVATE) > 255
269 cmpl $-1, dep_mutex(%ebx)
272 andl $(LLL_SHARED-LLL_PRIVATE), %ecx
274 addl $LLL_PRIVATE, %ecx
279 /* Unlock after loop requires wakeup. */
284 leal cond_lock(%ebx), %eax
286 #if (LLL_SHARED-LLL_PRIVATE) > 255
289 cmpl $-1, dep_mutex(%ebx)
292 andl $(LLL_SHARED-LLL_PRIVATE), %ecx
294 addl $LLL_PRIVATE, %ecx
296 call __lll_unlock_wake
299 /* The initial unlocking of the mutex failed. */
306 subl $1, cond_lock(%ebx)
314 leal cond_lock(%ebx), %eax
316 #if (LLL_SHARED-LLL_PRIVATE) > 255
319 cmpl $-1, dep_mutex(%ebx)
322 andl $(LLL_SHARED-LLL_PRIVATE), %ecx
324 addl $LLL_PRIVATE, %ecx
326 call __lll_unlock_wake
330 .size __pthread_cond_wait, .-__pthread_cond_wait
331 versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
335 .type __condvar_w_cleanup2, @function
336 __condvar_w_cleanup2:
337 subl $cond_futex, %ebx
338 .size __condvar_w_cleanup2, .-__condvar_w_cleanup2
340 .type __condvar_w_cleanup, @function
344 /* Get internal lock. */
349 cmpxchgl %edx, (%ebx)
351 cmpxchgl %edx, cond_lock(%ebx)
358 leal cond_lock(%ebx), %edx
360 #if (LLL_SHARED-LLL_PRIVATE) > 255
363 cmpl $-1, dep_mutex(%ebx)
366 andl $(LLL_SHARED-LLL_PRIVATE), %ecx
368 addl $LLL_PRIVATE, %ecx
372 1: movl broadcast_seq(%ebx), %eax
376 /* We increment the wakeup_seq counter only if it is lower than
377 total_seq. If this is not the case the thread was woken and
378 then canceled. In this case we ignore the signal. */
379 movl total_seq(%ebx), %eax
380 movl total_seq+4(%ebx), %edi
381 cmpl wakeup_seq+4(%ebx), %edi
384 cmpl wakeup_seq(%ebx), %eax
387 6: addl $1, wakeup_seq(%ebx)
388 adcl $0, wakeup_seq+4(%ebx)
389 addl $1, cond_futex(%ebx)
391 7: addl $1, woken_seq(%ebx)
392 adcl $0, woken_seq+4(%ebx)
394 3: subl $(1 << nwaiters_shift), cond_nwaiters(%ebx)
396 /* Wake up a thread which wants to destroy the condvar object. */
398 movl total_seq(%ebx), %eax
399 andl total_seq+4(%ebx), %eax
400 cmpl $0xffffffff, %eax
402 movl cond_nwaiters(%ebx), %eax
403 andl $~((1 << nwaiters_shift) - 1), %eax
406 addl $cond_nwaiters, %ebx
407 movl $SYS_futex, %eax
408 #if FUTEX_PRIVATE_FLAG > 255
411 cmpl $-1, dep_mutex-cond_nwaiters(%ebx)
414 #ifdef __ASSUME_PRIVATE_FUTEX
415 andl $FUTEX_PRIVATE_FLAG, %ecx
417 andl %gs:PRIVATE_FUTEX, %ecx
419 addl $FUTEX_WAKE, %ecx
422 subl $cond_nwaiters, %ebx
429 subl $1, cond_lock(%ebx)
436 leal cond_lock(%ebx), %eax
438 #if (LLL_SHARED-LLL_PRIVATE) > 255
441 cmpl $-1, dep_mutex(%ebx)
444 andl $(LLL_SHARED-LLL_PRIVATE), %ecx
446 addl $LLL_PRIVATE, %ecx
448 call __lll_unlock_wake
450 /* Wake up all waiters to make sure no signal gets lost. */
453 addl $cond_futex, %ebx
454 #if FUTEX_PRIVATE_FLAG > 255
457 cmpl $-1, dep_mutex-cond_futex(%ebx)
460 #ifdef __ASSUME_PRIVATE_FUTEX
461 andl $FUTEX_PRIVATE_FLAG, %ecx
463 andl %gs:PRIVATE_FUTEX, %ecx
465 addl $FUTEX_WAKE, %ecx
466 movl $SYS_futex, %eax
467 movl $0x7fffffff, %edx
470 5: movl 20+FRAME_SIZE(%esp), %eax
471 call __pthread_mutex_cond_lock
478 .size __condvar_w_cleanup, .-__condvar_w_cleanup
481 .section .gcc_except_table,"a",@progbits
483 .byte 0xff # @LPStart format (omit)
484 .byte 0xff # @TType format (omit)
485 .byte 0x0b # call-site format
487 .uleb128 .Lcstend-.Lcstbegin
489 .long .LcleanupSTART-.LSTARTCODE
490 .long .Ladd_cond_futex-.LcleanupSTART
491 .long __condvar_w_cleanup-.LSTARTCODE
493 .long .Ladd_cond_futex-.LSTARTCODE
494 .long .Lsub_cond_futex-.Ladd_cond_futex
495 .long __condvar_w_cleanup2-.LSTARTCODE
497 .long .Lsub_cond_futex-.LSTARTCODE
498 .long .LcleanupEND-.Lsub_cond_futex
499 .long __condvar_w_cleanup-.LSTARTCODE
501 .long .LcallUR-.LSTARTCODE
502 .long .LENDCODE-.LcallUR
507 .section .eh_frame,"a",@progbits
509 .long L(ENDCIE)-L(STARTCIE) # Length of the CIE.
512 .byte 1 # Version number.
514 .string "zPLR" # NUL-terminated augmentation
517 .string "zPL" # NUL-terminated augmentation
520 .uleb128 1 # Code alignment factor.
521 .sleb128 -4 # Data alignment factor.
522 .byte 8 # Return address register
525 .uleb128 7 # Augmentation value length.
526 .byte 0x9b # Personality: DW_EH_PE_pcrel
528 # + DW_EH_PE_indirect
529 .long DW.ref.__gcc_personality_v0-.
530 .byte 0x1b # LSDA Encoding: DW_EH_PE_pcrel
532 .byte 0x1b # FDE Encoding: DW_EH_PE_pcrel
535 .uleb128 6 # Augmentation value length.
536 .byte 0x0 # Personality: absolute
537 .long __gcc_personality_v0
538 .byte 0x0 # LSDA Encoding: absolute
540 .byte 0x0c # DW_CFA_def_cfa
543 .byte 0x88 # DW_CFA_offset, column 0x8
548 .long .LENDFDE-.LSTARTFDE # Length of the FDE.
550 .long .LSTARTFDE-.LSTARTFRAME # CIE pointer.
552 .long .LSTARTCODE-. # PC-relative start address
555 .long .LSTARTCODE # Start address of the code.
557 .long .LENDCODE-.LSTARTCODE # Length of the code.
558 .uleb128 4 # Augmentation size
560 .long .LexceptSTART-.
564 .byte 0x40+.Lpush_edi-.LSTARTCODE # DW_CFA_advance_loc+N
565 .byte 14 # DW_CFA_def_cfa_offset
567 .byte 0x87 # DW_CFA_offset %edi
569 .byte 0x40+.Lpush_esi-.Lpush_edi # DW_CFA_advance_loc+N
570 .byte 14 # DW_CFA_def_cfa_offset
572 .byte 0x86 # DW_CFA_offset %esi
574 .byte 0x40+.Lpush_ebx-.Lpush_esi # DW_CFA_advance_loc+N
575 .byte 14 # DW_CFA_def_cfa_offset
577 .byte 0x83 # DW_CFA_offset %ebx
579 .byte 4 # DW_CFA_advance_loc4
580 .4byte .Lsubl-.Lpush_ebx
581 .byte 14 # DW_CFA_def_cfa_offset
582 .uleb128 16+FRAME_SIZE
583 .byte 4 # DW_CFA_advance_loc4
585 .byte 14 # DW_CFA_def_cfa_offset
587 .byte 0x40+ .Lpop_ebx-.Laddl # DW_CFA_advance_loc+N
588 .byte 14 # DW_CFA_def_cfa_offset
590 .byte 0xc3 # DW_CFA_restore %ebx
591 .byte 0x40+.Lpop_esi-.Lpop_ebx # DW_CFA_advance_loc+N
592 .byte 14 # DW_CFA_def_cfa_offset
594 .byte 0xc6 # DW_CFA_restore %esi
595 .byte 0x40+.Lpop_edi-.Lpop_esi # DW_CFA_advance_loc+N
596 .byte 14 # DW_CFA_def_cfa_offset
598 .byte 0xc7 # DW_CFA_restore %edi
599 .byte 0x40+.LSbl1-.Lpop_edi # DW_CFA_advance_loc+N
600 .byte 14 # DW_CFA_def_cfa_offset
602 .byte 0x87 # DW_CFA_offset %edi
604 .byte 0x86 # DW_CFA_offset %esi
606 .byte 0x83 # DW_CFA_offset %ebx
608 .byte 4 # DW_CFA_advance_loc4
610 .byte 14 # DW_CFA_def_cfa_offset
611 .uleb128 16+FRAME_SIZE
612 .byte 4 # DW_CFA_advance_loc4
614 .byte 14 # DW_CFA_def_cfa_offset
616 .byte 4 # DW_CFA_advance_loc4
618 .byte 14 # DW_CFA_def_cfa_offset
619 .uleb128 16+FRAME_SIZE
625 .section .gnu.linkonce.t.__i686.get_pc_thunk.cx,"ax",@progbits
626 .globl __i686.get_pc_thunk.cx
627 .hidden __i686.get_pc_thunk.cx
628 .type __i686.get_pc_thunk.cx,@function
629 __i686.get_pc_thunk.cx:
632 .size __i686.get_pc_thunk.cx,.-__i686.get_pc_thunk.cx
636 .hidden DW.ref.__gcc_personality_v0
637 .weak DW.ref.__gcc_personality_v0
638 .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
640 .type DW.ref.__gcc_personality_v0, @object
641 .size DW.ref.__gcc_personality_v0, 4
642 DW.ref.__gcc_personality_v0:
643 .long __gcc_personality_v0