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 <pthread-errnos.h>
31 #define SYS_gettimeofday __NR_gettimeofday
39 /* int pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
40 const struct timespec *abstime) */
41 .globl __pthread_cond_timedwait
42 .type __pthread_cond_timedwait, @function
44 __pthread_cond_timedwait:
58 /* Get internal lock. */
65 cmpxchgl %edx, cond_lock(%ebx)
69 /* Store the reference to the mutex. If there is already a
70 different value in there this is a bad user bug. */
71 2: cmpl $-1, dep_mutex(%ebx)
74 movl %eax, dep_mutex(%ebx)
76 /* Unlock the mutex. */
78 call __pthread_mutex_unlock_usercnt
83 addl $1, total_seq(%ebx)
84 adcl $0, total_seq+4(%ebx)
87 subl $FRAME_SIZE, %esp
90 /* Get and store current wakeup_seq value. */
91 movl wakeup_seq(%ebx), %edi
92 movl wakeup_seq+4(%ebx), %edx
93 movl broadcast_seq(%ebx), %eax
98 /* Get the current time. */
101 #ifdef __NR_clock_gettime
102 /* Get the clock number. Note that the field in the condvar
103 structure stores the number minus 1. */
104 movl cond_clock(%ebx), %ebx
105 /* Only clocks 0 and 1 are allowed. Both are handled in the
108 movl $__NR_clock_gettime, %eax
110 # ifndef __ASSUME_POSIX_TIMERS
117 /* Compute relative timeout. */
123 /* Get the current time. */
126 movl $SYS_gettimeofday, %eax
131 /* Compute relative timeout. */
134 mul %edx /* Milli seconds to nano seconds. */
141 addl $1000000000, %edx
144 movl $-ETIMEDOUT, %esi
147 /* Store relative timeout. */
148 21: movl %ecx, 4(%esp)
156 subl $1, cond_lock(%ebx)
161 4: call __pthread_enable_asynccancel
165 xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */
167 addl $wakeup_seq, %ebx
169 movl $SYS_futex, %eax
171 subl $wakeup_seq, %ebx
176 call __pthread_disable_asynccancel
184 cmpxchgl %edx, (%ebx)
186 cmpxchgl %edx, cond_lock(%ebx)
190 6: movl broadcast_seq(%ebx), %eax
194 movl woken_seq(%ebx), %eax
195 movl woken_seq+4(%ebx), %ecx
197 movl wakeup_seq(%ebx), %edi
198 movl wakeup_seq+4(%ebx), %edx
210 15: cmpl $-ETIMEDOUT, %esi
213 addl $1, wakeup_seq(%ebx)
214 adcl $0, wakeup_seq+4(%ebx)
215 movl $ETIMEDOUT, %esi
222 14: addl $1, woken_seq(%ebx)
223 adcl $0, woken_seq+4(%ebx)
229 subl $1, cond_lock(%ebx)
233 /* Remove cancellation handler. */
234 11: movl 24+FRAME_SIZE(%esp), %eax
235 call __pthread_mutex_cond_lock
236 addl $FRAME_SIZE, %esp
239 /* We return the result of the mutex_lock operation if it failed. */
260 /* Initial locking failed. */
266 leal cond_lock(%ebx), %ecx
268 call __lll_mutex_lock_wait
271 /* Unlock in loop requires wakeup. */
277 leal cond_lock(%ebx), %eax
279 call __lll_mutex_unlock_wake
282 /* Locking in loop failed. */
287 leal cond_lock(%ebx), %ecx
289 call __lll_mutex_lock_wait
292 /* Unlock after loop requires wakeup. */
297 leal cond_lock(%ebx), %eax
299 call __lll_mutex_unlock_wake
302 /* The initial unlocking of the mutex failed. */
309 subl $1, cond_lock(%ebx)
317 leal cond_lock(%ebx), %eax
319 call __lll_mutex_unlock_wake
324 #if defined __NR_clock_gettime && !defined __ASSUME_POSIX_TIMERS
325 /* clock_gettime not available. */
327 19: leal 4(%esp), %ebx
329 movl $SYS_gettimeofday, %eax
333 /* Compute relative timeout. */
336 mul %edx /* Milli seconds to nano seconds. */
342 addl $1000000000, %edx
345 movl $-ETIMEDOUT, %esi
349 .size __pthread_cond_timedwait, .-__pthread_cond_timedwait
350 versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
354 .type __condvar_tw_cleanup3, @function
355 __condvar_tw_cleanup3:
356 movl 20+FRAME_SIZE(%esp), %ebx
358 jmp __condvar_tw_cleanup
359 .size __condvar_tw_cleanup3, .-__condvar_tw_cleanup3
360 .type __condvar_tw_cleanup2, @function
361 __condvar_tw_cleanup2:
362 subl $wakeup_seq, %ebx
363 .size __condvar_tw_cleanup2, .-__condvar_tw_cleanup2
364 .type __condvar_tw_cleanup, @function
365 __condvar_tw_cleanup:
368 /* Get internal lock. */
373 cmpxchgl %edx, (%ebx)
375 cmpxchgl %edx, cond_lock(%ebx)
382 leal cond_lock(%ebx), %ecx
384 call __lll_mutex_lock_wait
386 1: movl broadcast_seq(%ebx), %eax
390 addl $1, wakeup_seq(%ebx)
391 adcl $0, wakeup_seq+4(%ebx)
393 addl $1, woken_seq(%ebx)
394 adcl $0, woken_seq+4(%ebx)
400 subl $1, cond_lock(%ebx)
407 leal cond_lock(%ebx), %eax
409 call __lll_mutex_unlock_wake
411 /* Wake up all waiters to make sure no signal gets lost. */
412 2: addl $wakeup_seq, %ebx
413 movl $FUTEX_WAKE, %ecx
414 movl $SYS_futex, %eax
415 movl $0x7fffffff, %edx
418 movl 24+FRAME_SIZE(%esp), %eax
419 call __pthread_mutex_cond_lock
426 .size __condvar_tw_cleanup, .-__condvar_tw_cleanup
429 .section .gcc_except_table,"a",@progbits
431 .byte 0xff # @LPStart format (omit)
432 .byte 0xff # @TType format (omit)
433 .byte 0x0b # call-site format
435 .uleb128 .Lcstend-.Lcstbegin
437 .long .LcleanupSTART-.LSTARTCODE
438 .long .Ladd_wakeup-.LcleanupSTART
439 .long __condvar_tw_cleanup-.LSTARTCODE
441 .long .LebxmovedUR-.LSTARTCODE
442 .long .LebxbackUR-.LebxmovedUR
443 .long __condvar_tw_cleanup3-.LSTARTCODE
445 .long .LebxmovedUR-.LSTARTCODE
446 .long .Ladd_wakeup-.LebxmovedUR
447 .long __condvar_tw_cleanup-.LSTARTCODE
449 .long .Ladd_wakeup-.LSTARTCODE
450 .long .Lsub_wakeup-.Ladd_wakeup
451 .long __condvar_tw_cleanup2-.LSTARTCODE
453 .long .Lsub_wakeup-.LSTARTCODE
454 .long .LcleanupEND-.Lsub_wakeup
455 .long __condvar_tw_cleanup-.LSTARTCODE
457 .long .LcallUR-.LSTARTCODE
458 .long .LENDCODE-.LcallUR
464 .section .eh_frame,"a",@progbits
466 .long L(ENDCIE)-L(STARTCIE) # Length of the CIE.
469 .byte 1 # Version number.
471 .string "zPLR" # NUL-terminated augmentation
474 .string "zPL" # NUL-terminated augmentation
477 .uleb128 1 # Code alignment factor.
478 .sleb128 -4 # Data alignment factor.
479 .byte 8 # Return address register
482 .uleb128 7 # Augmentation value length.
483 .byte 0x9b # Personality: DW_EH_PE_pcrel
485 # + DW_EH_PE_indirect
486 .long DW.ref.__gcc_personality_v0-.
487 .byte 0x1b # LSDA Encoding: DW_EH_PE_pcrel
489 .byte 0x1b # FDE Encoding: DW_EH_PE_pcrel
492 .uleb128 6 # Augmentation value length.
493 .byte 0x0 # Personality: absolute
494 .long __gcc_personality_v0
495 .byte 0x0 # LSDA Encoding: absolute
497 .byte 0x0c # DW_CFA_def_cfa
500 .byte 0x88 # DW_CFA_offset, column 0x8
505 .long .LENDFDE-.LSTARTFDE # Length of the FDE.
507 .long .LSTARTFDE-.LSTARTFRAME # CIE pointer.
509 .long .LSTARTCODE-. # PC-relative start address
512 .long .LSTARTCODE # Start address of the code.
514 .long .LENDCODE-.LSTARTCODE # Length of the code.
515 .uleb128 4 # Augmentation size
517 .long .LexceptSTART-.
521 .byte 0x40+.Lpush_ebp-.LSTARTCODE # DW_CFA_advance_loc+N
522 .byte 14 # DW_CFA_def_cfa_offset
524 .byte 0x85 # DW_CFA_offset %ebp
526 .byte 0x40+ .Lpush_edi-.Lpush_ebp # DW_CFA_advance_loc+N
527 .byte 14 # DW_CFA_def_cfa_offset
529 .byte 0x87 # DW_CFA_offset %edi
531 .byte 0x40+.Lpush_esi-.Lpush_edi # DW_CFA_advance_loc+N
532 .byte 14 # DW_CFA_def_cfa_offset
534 .byte 0x86 # DW_CFA_offset %esi
536 .byte 0x40+.Lpush_ebx-.Lpush_esi # DW_CFA_advance_loc+N
537 .byte 14 # DW_CFA_def_cfa_offset
539 .byte 0x83 # DW_CFA_offset %ebx
541 .byte 2 # DW_CFA_advance_loc1
542 .byte .Lsubl-.Lpush_ebx
543 .byte 14 # DW_CFA_def_cfa_offset
544 .uleb128 20+FRAME_SIZE
545 .byte 3 # DW_CFA_advance_loc2
547 .byte 14 # DW_CFA_def_cfa_offset
549 .byte 0x40+.Lpop_ebx-.Laddl # DW_CFA_advance_loc+N
550 .byte 14 # DW_CFA_def_cfa_offset
552 .byte 0xc3 # DW_CFA_restore %ebx
553 .byte 0x40+.Lpop_esi-.Lpop_ebx # DW_CFA_advance_loc+N
554 .byte 14 # DW_CFA_def_cfa_offset
556 .byte 0xc6 # DW_CFA_restore %esi
557 .byte 0x40+.Lpop_edi-.Lpop_esi # DW_CFA_advance_loc+N
558 .byte 14 # DW_CFA_def_cfa_offset
560 .byte 0xc7 # DW_CFA_restore %edi
561 .byte 0x40+.Lpop_ebp-.Lpop_edi # DW_CFA_advance_loc+N
562 .byte 14 # DW_CFA_def_cfa_offset
564 .byte 0xc5 # DW_CFA_restore %ebp
565 .byte 0x40+.LSbl1-.Lpop_edi # DW_CFA_advance_loc+N
566 .byte 14 # DW_CFA_def_cfa_offset
568 .byte 0x40+.LSbl2-.LSbl1 # DW_CFA_advance_loc+N
569 .byte 14 # DW_CFA_def_cfa_offset
570 .uleb128 20+FRAME_SIZE
571 .byte 0x85 # DW_CFA_offset %ebp
573 .byte 0x87 # DW_CFA_offset %edi
575 .byte 0x86 # DW_CFA_offset %esi
577 .byte 0x83 # DW_CFA_offset %ebx
579 .byte 0x40+.LSbl3-.LSbl2 # DW_CFA_advance_loc+N
580 .byte 14 # DW_CFA_def_cfa_offset
582 #if defined __NR_clock_gettime && !defined __ASSUME_POSIX_TIMERS
583 .byte 0x40+.LSbl4-.LSbl3 # DW_CFA_advance_loc+N
585 .byte 4 # DW_CFA_advance_loc4
588 .byte 14 # DW_CFA_def_cfa_offset
589 .uleb128 20+FRAME_SIZE
594 .hidden DW.ref.__gcc_personality_v0
595 .weak DW.ref.__gcc_personality_v0
596 .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
598 .type DW.ref.__gcc_personality_v0, @object
599 .size DW.ref.__gcc_personality_v0, 4
600 DW.ref.__gcc_personality_v0:
601 .long __gcc_personality_v0