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 <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 cmpl $1000000000, 4(%ebp)
62 /* Get internal lock. */
69 cmpxchgl %edx, cond_lock(%ebx)
73 /* Store the reference to the mutex. If there is already a
74 different value in there this is a bad user bug. */
75 2: cmpl $-1, dep_mutex(%ebx)
78 movl %eax, dep_mutex(%ebx)
80 /* Unlock the mutex. */
82 call __pthread_mutex_unlock_usercnt
87 addl $1, total_seq(%ebx)
88 adcl $0, total_seq+4(%ebx)
89 addl $1, cond_futex(%ebx)
90 addl $(1 << clock_bits), cond_nwaiters(%ebx)
93 subl $FRAME_SIZE, %esp
96 /* Get and store current wakeup_seq value. */
97 movl wakeup_seq(%ebx), %edi
98 movl wakeup_seq+4(%ebx), %edx
99 movl broadcast_seq(%ebx), %eax
104 /* Get the current time. */
106 #ifdef __NR_clock_gettime
107 /* Get the clock number. */
108 movl cond_nwaiters(%ebx), %ebx
109 andl $((1 << clock_bits) - 1), %ebx
110 /* Only clocks 0 and 1 are allowed so far. Both are handled in the
113 movl $__NR_clock_gettime, %eax
115 # ifndef __ASSUME_POSIX_TIMERS
121 /* Compute relative timeout. */
127 /* Get the current time. */
130 movl $SYS_gettimeofday, %eax
134 /* Compute relative timeout. */
137 mul %edx /* Milli seconds to nano seconds. */
144 addl $1000000000, %edx
147 movl $-ETIMEDOUT, %esi
150 /* Store relative timeout. */
151 21: movl %ecx, 4(%esp)
154 movl cond_futex(%ebx), %edi
161 subl $1, cond_lock(%ebx)
166 4: call __pthread_enable_asynccancel
170 xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */
172 addl $cond_futex, %ebx
174 movl $SYS_futex, %eax
176 subl $cond_futex, %ebx
181 call __pthread_disable_asynccancel
189 cmpxchgl %edx, (%ebx)
191 cmpxchgl %edx, cond_lock(%ebx)
195 6: movl broadcast_seq(%ebx), %eax
199 movl woken_seq(%ebx), %eax
200 movl woken_seq+4(%ebx), %ecx
202 movl wakeup_seq(%ebx), %edi
203 movl wakeup_seq+4(%ebx), %edx
215 15: cmpl $-ETIMEDOUT, %esi
218 addl $1, wakeup_seq(%ebx)
219 adcl $0, wakeup_seq+4(%ebx)
220 addl $1, cond_futex(%ebx)
221 movl $ETIMEDOUT, %esi
228 14: addl $1, woken_seq(%ebx)
229 adcl $0, woken_seq+4(%ebx)
231 24: subl $(1 << clock_bits), cond_nwaiters(%ebx)
233 /* Wake up a thread which wants to destroy the condvar object. */
234 movl total_seq(%ebx), %eax
235 andl total_seq+4(%ebx), %eax
236 cmpl $0xffffffff, %eax
238 movl cond_nwaiters(%ebx), %eax
239 andl $~((1 << clock_bits) - 1), %eax
242 addl $cond_nwaiters, %ebx
243 movl $SYS_futex, %eax
244 movl $FUTEX_WAKE, %ecx
247 subl $cond_nwaiters, %ebx
253 subl $1, cond_lock(%ebx)
257 /* Remove cancellation handler. */
258 11: movl 24+FRAME_SIZE(%esp), %eax
259 call __pthread_mutex_cond_lock
260 addl $FRAME_SIZE, %esp
263 /* We return the result of the mutex_lock operation if it failed. */
284 /* Initial locking failed. */
290 leal cond_lock(%ebx), %ecx
292 call __lll_mutex_lock_wait
295 /* Unlock in loop requires wakeup. */
301 leal cond_lock(%ebx), %eax
303 call __lll_mutex_unlock_wake
306 /* Locking in loop failed. */
311 leal cond_lock(%ebx), %ecx
313 call __lll_mutex_lock_wait
316 /* Unlock after loop requires wakeup. */
321 leal cond_lock(%ebx), %eax
323 call __lll_mutex_unlock_wake
326 /* The initial unlocking of the mutex failed. */
333 subl $1, cond_lock(%ebx)
341 leal cond_lock(%ebx), %eax
343 call __lll_mutex_unlock_wake
348 #if defined __NR_clock_gettime && !defined __ASSUME_POSIX_TIMERS
349 /* clock_gettime not available. */
351 19: leal 4(%esp), %ebx
353 movl $SYS_gettimeofday, %eax
357 /* Compute relative timeout. */
360 mul %edx /* Milli seconds to nano seconds. */
366 addl $1000000000, %edx
369 movl $-ETIMEDOUT, %esi
373 .size __pthread_cond_timedwait, .-__pthread_cond_timedwait
374 versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
378 .type __condvar_tw_cleanup2, @function
379 __condvar_tw_cleanup2:
380 subl $cond_futex, %ebx
382 .size __condvar_tw_cleanup2, .-__condvar_tw_cleanup2
383 .type __condvar_tw_cleanup, @function
384 __condvar_tw_cleanup:
387 /* Get internal lock. */
392 cmpxchgl %edx, (%ebx)
394 cmpxchgl %edx, cond_lock(%ebx)
401 leal cond_lock(%ebx), %ecx
403 call __lll_mutex_lock_wait
405 1: movl broadcast_seq(%ebx), %eax
409 /* We increment the wakeup_seq counter only if it is lower than
410 total_seq. If this is not the case the thread was woken and
411 then canceled. In this case we ignore the signal. */
412 movl total_seq(%ebx), %eax
413 movl total_seq+4(%ebx), %edi
414 cmpl wakeup_seq+4(%ebx), %edi
417 cmpl wakeup_seq(%ebx), %eax
420 6: addl $1, wakeup_seq(%ebx)
421 adcl $0, wakeup_seq+4(%ebx)
422 addl $1, cond_futex(%ebx)
424 7: addl $1, woken_seq(%ebx)
425 adcl $0, woken_seq+4(%ebx)
427 3: subl $(1 << clock_bits), cond_nwaiters(%ebx)
429 /* Wake up a thread which wants to destroy the condvar object. */
431 movl total_seq(%ebx), %eax
432 andl total_seq+4(%ebx), %eax
433 cmpl $0xffffffff, %eax
435 movl cond_nwaiters(%ebx), %eax
436 andl $~((1 << clock_bits) - 1), %eax
439 addl $cond_nwaiters, %ebx
440 movl $SYS_futex, %eax
441 movl $FUTEX_WAKE, %ecx
444 subl $cond_nwaiters, %ebx
451 subl $1, cond_lock(%ebx)
458 leal cond_lock(%ebx), %eax
460 call __lll_mutex_unlock_wake
462 /* Wake up all waiters to make sure no signal gets lost. */
465 addl $cond_futex, %ebx
466 movl $FUTEX_WAKE, %ecx
467 movl $SYS_futex, %eax
468 movl $0x7fffffff, %edx
471 5: movl 24+FRAME_SIZE(%esp), %eax
472 call __pthread_mutex_cond_lock
479 .size __condvar_tw_cleanup, .-__condvar_tw_cleanup
482 .section .gcc_except_table,"a",@progbits
484 .byte 0xff # @LPStart format (omit)
485 .byte 0xff # @TType format (omit)
486 .byte 0x0b # call-site format
488 .uleb128 .Lcstend-.Lcstbegin
490 .long .LcleanupSTART-.LSTARTCODE
491 .long .Ladd_cond_futex-.LcleanupSTART
492 .long __condvar_tw_cleanup-.LSTARTCODE
494 .long .Ladd_cond_futex-.LSTARTCODE
495 .long .Lsub_cond_futex-.Ladd_cond_futex
496 .long __condvar_tw_cleanup2-.LSTARTCODE
498 .long .Lsub_cond_futex-.LSTARTCODE
499 .long .LcleanupEND-.Lsub_cond_futex
500 .long __condvar_tw_cleanup-.LSTARTCODE
502 .long .LcallUR-.LSTARTCODE
503 .long .LENDCODE-.LcallUR
509 .section .eh_frame,"a",@progbits
511 .long L(ENDCIE)-L(STARTCIE) # Length of the CIE.
514 .byte 1 # Version number.
516 .string "zPLR" # NUL-terminated augmentation
519 .string "zPL" # NUL-terminated augmentation
522 .uleb128 1 # Code alignment factor.
523 .sleb128 -4 # Data alignment factor.
524 .byte 8 # Return address register
527 .uleb128 7 # Augmentation value length.
528 .byte 0x9b # Personality: DW_EH_PE_pcrel
530 # + DW_EH_PE_indirect
531 .long DW.ref.__gcc_personality_v0-.
532 .byte 0x1b # LSDA Encoding: DW_EH_PE_pcrel
534 .byte 0x1b # FDE Encoding: DW_EH_PE_pcrel
537 .uleb128 6 # Augmentation value length.
538 .byte 0x0 # Personality: absolute
539 .long __gcc_personality_v0
540 .byte 0x0 # LSDA Encoding: absolute
542 .byte 0x0c # DW_CFA_def_cfa
545 .byte 0x88 # DW_CFA_offset, column 0x8
550 .long .LENDFDE-.LSTARTFDE # Length of the FDE.
552 .long .LSTARTFDE-.LSTARTFRAME # CIE pointer.
554 .long .LSTARTCODE-. # PC-relative start address
557 .long .LSTARTCODE # Start address of the code.
559 .long .LENDCODE-.LSTARTCODE # Length of the code.
560 .uleb128 4 # Augmentation size
562 .long .LexceptSTART-.
566 .byte 0x40+.Lpush_ebp-.LSTARTCODE # DW_CFA_advance_loc+N
567 .byte 14 # DW_CFA_def_cfa_offset
569 .byte 0x85 # DW_CFA_offset %ebp
571 .byte 0x40+ .Lpush_edi-.Lpush_ebp # DW_CFA_advance_loc+N
572 .byte 14 # DW_CFA_def_cfa_offset
574 .byte 0x87 # DW_CFA_offset %edi
576 .byte 0x40+.Lpush_esi-.Lpush_edi # DW_CFA_advance_loc+N
577 .byte 14 # DW_CFA_def_cfa_offset
579 .byte 0x86 # DW_CFA_offset %esi
581 .byte 0x40+.Lpush_ebx-.Lpush_esi # DW_CFA_advance_loc+N
582 .byte 14 # DW_CFA_def_cfa_offset
584 .byte 0x83 # DW_CFA_offset %ebx
586 .byte 2 # DW_CFA_advance_loc1
587 .byte .Lsubl-.Lpush_ebx
588 .byte 14 # DW_CFA_def_cfa_offset
589 .uleb128 20+FRAME_SIZE
590 .byte 3 # DW_CFA_advance_loc2
592 .byte 14 # DW_CFA_def_cfa_offset
594 .byte 0x40+.Lpop_ebx-.Laddl # DW_CFA_advance_loc+N
595 .byte 14 # DW_CFA_def_cfa_offset
597 .byte 0xc3 # DW_CFA_restore %ebx
598 .byte 0x40+.Lpop_esi-.Lpop_ebx # DW_CFA_advance_loc+N
599 .byte 14 # DW_CFA_def_cfa_offset
601 .byte 0xc6 # DW_CFA_restore %esi
602 .byte 0x40+.Lpop_edi-.Lpop_esi # DW_CFA_advance_loc+N
603 .byte 14 # DW_CFA_def_cfa_offset
605 .byte 0xc7 # DW_CFA_restore %edi
606 .byte 0x40+.Lpop_ebp-.Lpop_edi # DW_CFA_advance_loc+N
607 .byte 14 # DW_CFA_def_cfa_offset
609 .byte 0xc5 # DW_CFA_restore %ebp
610 .byte 0x40+.LSbl1-.Lpop_edi # DW_CFA_advance_loc+N
611 .byte 14 # DW_CFA_def_cfa_offset
613 .byte 0x40+.LSbl2-.LSbl1 # DW_CFA_advance_loc+N
614 .byte 14 # DW_CFA_def_cfa_offset
615 .uleb128 20+FRAME_SIZE
616 .byte 0x85 # DW_CFA_offset %ebp
618 .byte 0x87 # DW_CFA_offset %edi
620 .byte 0x86 # DW_CFA_offset %esi
622 .byte 0x83 # DW_CFA_offset %ebx
624 .byte 0x40+.LSbl3-.LSbl2 # DW_CFA_advance_loc+N
625 .byte 14 # DW_CFA_def_cfa_offset
627 #if defined __NR_clock_gettime && !defined __ASSUME_POSIX_TIMERS
628 .byte 0x40+.LSbl4-.LSbl3 # DW_CFA_advance_loc+N
630 .byte 4 # DW_CFA_advance_loc4
633 .byte 14 # DW_CFA_def_cfa_offset
634 .uleb128 20+FRAME_SIZE
639 .hidden DW.ref.__gcc_personality_v0
640 .weak DW.ref.__gcc_personality_v0
641 .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
643 .type DW.ref.__gcc_personality_v0, @object
644 .size DW.ref.__gcc_personality_v0, 4
645 DW.ref.__gcc_personality_v0:
646 .long __gcc_personality_v0