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 <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. */
64 xaddl %eax, 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: movl 24(%esp), %eax
72 movl %eax, dep_mutex(%ebx)
74 /* Unlock the mutex. */
76 call __pthread_mutex_unlock_usercnt
81 addl $1, total_seq(%ebx)
82 adcl $0, total_seq+4(%ebx)
87 /* Get and store current wakeup_seq value. */
88 movl wakeup_seq(%ebx), %edi
89 movl wakeup_seq+4(%ebx), %edx
98 subl $1, cond_lock(%ebx)
103 4: call __pthread_enable_asynccancel
106 /* Get the current time. */
109 #ifdef __NR_clock_gettime
110 /* Get the clock number. Note that the field in the condvar
111 structure stores the number minus 1. */
112 movl cond_clock(%ebx), %ebx
113 /* Only clocks 0 and 1 are allowed. Both are handled in the
116 movl $__NR_clock_gettime, %eax
118 # ifndef __ASSUME_POSIX_TIMERS
125 /* Compute relative timeout. */
131 /* Get the current time. */
134 movl $SYS_gettimeofday, %eax
139 /* Compute relative timeout. */
142 mul %edx /* Milli seconds to nano seconds. */
149 addl $1000000000, %edx
154 /* Store relative timeout. */
155 21: movl %ecx, 4(%esp)
158 xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */
160 addl $wakeup_seq, %ebx
162 movl $SYS_futex, %eax
164 subl $wakeup_seq, %ebx
169 call __pthread_disable_asynccancel
178 xaddl %eax, cond_lock(%ebx)
183 6: movl woken_seq(%ebx), %eax
184 movl woken_seq+4(%ebx), %ecx
186 movl wakeup_seq(%ebx), %edi
187 movl wakeup_seq+4(%ebx), %edx
201 15: cmpl $-ETIMEDOUT, %esi
204 13: addl $1, wakeup_seq(%ebx)
205 adcl $0, wakeup_seq+4(%ebx)
206 movl $ETIMEDOUT, %esi
210 14: addl $1, woken_seq(%ebx)
211 adcl $0, woken_seq+4(%ebx)
217 subl $1, cond_lock(%ebx)
221 /* Remove cancellation handler. */
222 11: movl 44(%esp), %eax
223 call __pthread_mutex_cond_lock
227 /* We return the result of the mutex_lock operation if it failed. */
242 /* Initial locking failed. */
248 leal cond_lock(%ebx), %ecx
250 call __lll_mutex_lock_wait
253 /* Unlock in loop requires waekup. */
259 leal cond_lock(%ebx), %eax
261 call __lll_mutex_unlock_wake
264 /* Locking in loop failed. */
269 leal cond_lock(%ebx), %ecx
271 call __lll_mutex_lock_wait
274 /* Unlock after loop requires waekup. */
279 leal cond_lock(%ebx), %eax
281 call __lll_mutex_unlock_wake
284 /* The initial unlocking of the mutex failed. */
291 subl $1, cond_lock(%ebx)
299 leal cond_lock(%ebx), %eax
301 call __lll_mutex_unlock_wake
306 #if defined __NR_clock_gettime && !defined __ASSUME_POSIX_TIMERS
307 /* clock_gettime not available. */
309 19: leal 4(%esp), %ebx
311 movl $SYS_gettimeofday, %eax
315 /* Compute relative timeout. */
318 mul %edx /* Milli seconds to nano seconds. */
324 addl $1000000000, %edx
330 .size __pthread_cond_timedwait, .-__pthread_cond_timedwait
331 versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
335 .type __condvar_tw_cleanup3, @function
336 __condvar_tw_cleanup3:
339 jmp __condvar_tw_cleanup
340 .size __condvar_tw_cleanup3, .-__condvar_tw_cleanup3
341 .type __condvar_tw_cleanup2, @function
342 __condvar_tw_cleanup2:
343 subl $wakeup_seq, %ebx
344 .size __condvar_tw_cleanup2, .-__condvar_tw_cleanup2
345 .type __condvar_tw_cleanup, @function
346 __condvar_tw_cleanup:
349 /* Get internal lock. */
355 xaddl %eax, cond_lock(%ebx)
363 leal cond_lock(%ebx), %ecx
365 call __lll_mutex_lock_wait
367 1: addl $1, wakeup_seq(%ebx)
368 adcl $0, wakeup_seq+4(%ebx)
370 addl $1, woken_seq(%ebx)
371 adcl $0, woken_seq+4(%ebx)
374 subl $1, cond_lock(%ebx)
380 leal cond_lock(%ebx), %eax
382 call __lll_mutex_unlock_wake
384 /* Wake up all waiters to make sure no signal gets lost. */
385 2: addl $wakeup_seq, %ebx
386 movl $FUTEX_WAKE, %ecx
387 movl $SYS_futex, %eax
388 movl $0x7fffffff, %edx
392 call __pthread_mutex_cond_lock
399 .size __condvar_tw_cleanup, .-__condvar_tw_cleanup
402 .section .gcc_except_table,"a",@progbits
404 .byte 0xff # @LPStart format (omit)
405 .byte 0xff # @TType format (omit)
406 .byte 0x0b # call-site format
408 .uleb128 .Lcstend-.Lcstbegin
410 .long .LcleanupSTART-.LSTARTCODE
411 .long .Ladd_wakeup-.LcleanupSTART
412 .long __condvar_tw_cleanup-.LSTARTCODE
414 .long .LebxmovedUR-.LSTARTCODE
415 .long .LebxbackUR-.LebxmovedUR
416 .long __condvar_tw_cleanup3-.LSTARTCODE
418 .long .LebxmovedUR-.LSTARTCODE
419 .long .Ladd_wakeup-.LebxmovedUR
420 .long __condvar_tw_cleanup-.LSTARTCODE
422 .long .Ladd_wakeup-.LSTARTCODE
423 .long .Lsub_wakeup-.Ladd_wakeup
424 .long __condvar_tw_cleanup2-.LSTARTCODE
426 .long .Lsub_wakeup-.LSTARTCODE
427 .long .LcleanupEND-.Lsub_wakeup
428 .long __condvar_tw_cleanup-.LSTARTCODE
430 .long .LcallUR-.LSTARTCODE
431 .long .LENDCODE-.LcallUR
437 .section .eh_frame,"a",@progbits
439 .long L(ENDCIE)-L(STARTCIE) # Length of the CIE.
442 .byte 1 # Version number.
444 .string "zPLR" # NUL-terminated augmentation
447 .string "zPL" # NUL-terminated augmentation
450 .uleb128 1 # Code alignment factor.
451 .sleb128 -4 # Data alignment factor.
452 .byte 8 # Return address register
455 .uleb128 7 # Augmentation value length.
456 .byte 0x9b # Personality: DW_EH_PE_pcrel
458 # + DW_EH_PE_indirect
459 .long DW.ref.__gcc_personality_v0-.
460 .byte 0x1b # LSDA Encoding: DW_EH_PE_pcrel
462 .byte 0x1b # FDE Encoding: DW_EH_PE_pcrel
465 .uleb128 6 # Augmentation value length.
466 .byte 0x0 # Personality: absolute
467 .long __gcc_personality_v0
468 .byte 0x0 # LSDA Encoding: absolute
470 .byte 0x0c # DW_CFA_def_cfa
473 .byte 0x88 # DW_CFA_offset, column 0x8
478 .long .LENDFDE-.LSTARTFDE # Length of the FDE.
480 .long .LSTARTFDE-.LSTARTFRAME # CIE pointer.
482 .long .LSTARTCODE-. # PC-relative start address
485 .long .LSTARTCODE # Start address of the code.
487 .long .LENDCODE-.LSTARTCODE # Length of the code.
488 .uleb128 4 # Augmentation size
490 .long .LexceptSTART-.
494 .byte 0x40+.Lpush_ebp-.LSTARTCODE # DW_CFA_advance_loc+N
495 .byte 14 # DW_CFA_def_cfa_offset
497 .byte 0x85 # DW_CFA_offset %ebp
499 .byte 0x40+ .Lpush_edi-.Lpush_ebp # DW_CFA_advance_loc+N
500 .byte 14 # DW_CFA_def_cfa_offset
502 .byte 0x87 # DW_CFA_offset %edi
504 .byte 0x40+.Lpush_esi-.Lpush_edi # DW_CFA_advance_loc+N
505 .byte 14 # DW_CFA_def_cfa_offset
507 .byte 0x86 # DW_CFA_offset %esi
509 .byte 0x40+.Lpush_ebx-.Lpush_esi # DW_CFA_advance_loc+N
510 .byte 14 # DW_CFA_def_cfa_offset
512 .byte 0x83 # DW_CFA_offset %ebx
514 .byte 2 # DW_CFA_advance_loc1
515 .byte .Lsubl-.Lpush_ebx
516 .byte 14 # DW_CFA_def_cfa_offset
518 .byte 3 # DW_CFA_advance_loc2
520 .byte 14 # DW_CFA_def_cfa_offset
522 .byte 0x40+.Lpop_ebx-.Laddl # DW_CFA_advance_loc+N
523 .byte 14 # DW_CFA_def_cfa_offset
525 .byte 0xc3 # DW_CFA_restore %ebx
526 .byte 0x40+.Lpop_esi-.Lpop_ebx # DW_CFA_advance_loc+N
527 .byte 14 # DW_CFA_def_cfa_offset
529 .byte 0xc6 # DW_CFA_restore %esi
530 .byte 0x40+.Lpop_edi-.Lpop_esi # DW_CFA_advance_loc+N
531 .byte 14 # DW_CFA_def_cfa_offset
533 .byte 0xc7 # DW_CFA_restore %edi
534 .byte 0x40+.Lpop_ebp-.Lpop_edi # DW_CFA_advance_loc+N
535 .byte 14 # DW_CFA_def_cfa_offset
537 .byte 0xc5 # DW_CFA_restore %ebp
538 .byte 0x40+.LSbl1-.Lpop_edi # DW_CFA_advance_loc+N
539 .byte 14 # DW_CFA_def_cfa_offset
541 .byte 0x40+.LSbl2-.LSbl1 # DW_CFA_advance_loc+N
542 .byte 14 # DW_CFA_def_cfa_offset
544 .byte 0x85 # DW_CFA_offset %ebp
546 .byte 0x87 # DW_CFA_offset %edi
548 .byte 0x86 # DW_CFA_offset %esi
550 .byte 0x83 # DW_CFA_offset %ebx
552 .byte 0x40+.LSbl3-.LSbl2 # DW_CFA_advance_loc+N
553 .byte 14 # DW_CFA_def_cfa_offset
555 #if defined __NR_clock_gettime && !defined __ASSUME_POSIX_TIMERS
556 .byte 0x40+.LSbl4-.LSbl3 # DW_CFA_advance_loc+N
557 .byte 14 # DW_CFA_def_cfa_offset
559 .byte 4 # DW_CFA_advance_loc4
562 .byte 4 # DW_CFA_advance_loc4
565 .byte 14 # DW_CFA_def_cfa_offset
571 .hidden DW.ref.__gcc_personality_v0
572 .weak DW.ref.__gcc_personality_v0
573 .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
575 .type DW.ref.__gcc_personality_v0, @object
576 .size DW.ref.__gcc_personality_v0, 4
577 DW.ref.__gcc_personality_v0:
578 .long __gcc_personality_v0