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>
30 #define SYS_gettimeofday __NR_gettimeofday
40 /* int pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
41 const struct timespec *abstime) */
42 .globl __pthread_cond_timedwait
43 .type __pthread_cond_timedwait, @function
45 __pthread_cond_timedwait:
58 /* Get internal lock. */
64 xaddl %eax, cond_lock(%ebx)
69 /* Unlock the mutex. */
71 call __pthread_mutex_unlock_internal
73 addl $1, total_seq(%ebx)
74 adcl $0, total_seq+4(%ebx)
76 /* Install cancellation handler. */
78 call __i686.get_pc_thunk.cx
79 addl $_GLOBAL_OFFSET_TABLE_, %ecx
80 leal __condvar_cleanup@GOTOFF(%ecx), %eax
82 leal __condvar_cleanup, %eax
89 call __pthread_cleanup_push
91 /* Get and store current wakeup_seq value. */
92 movl wakeup_seq(%ebx), %edi
93 movl wakeup_seq+4(%ebx), %edx
106 4: call __pthread_enable_asynccancel
109 /* Get the current time. */
113 movl $SYS_gettimeofday, %eax
117 /* Compute relative timeout. */
120 mul %edx /* Milli seconds to nano seconds. */
126 addl $1000000000, %edx
131 /* Store relative timeout. */
135 xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */
137 addl $wakeup_seq-cond_lock, %ebx
138 movl $SYS_futex, %eax
140 subl $wakeup_seq-cond_lock, %ebx
143 call __pthread_disable_asynccancel
151 xaddl %eax, cond_lock(%ebx)
156 6: movl woken_seq(%ebx), %eax
157 movl woken_seq+4(%ebx), %ecx
159 movl wakeup_seq(%ebx), %edi
160 movl wakeup_seq+4(%ebx), %edx
174 15: cmpl $-ETIMEDOUT, %esi
177 13: addl $1, wakeup_seq(%ebx)
178 adcl $0, wakeup_seq+4(%ebx)
179 movl $ETIMEDOUT, %esi
183 14: addl $1, woken_seq(%ebx)
184 adcl $0, woken_seq+4(%ebx)
194 /* Remove cancellation handler. */
195 11: leal 20(%esp), %edx
198 call __pthread_cleanup_pop
202 call __pthread_mutex_lock_internal
212 /* We return the result of the mutex_lock operation. */
215 /* Initial locking failed. */
220 leal cond_lock(%ebx), %ecx
222 call __lll_mutex_lock_wait
225 /* Unlock in loop requires waekup. */
230 leal cond_lock(%ebx), %eax
232 call __lll_mutex_unlock_wake
235 /* Locking in loop failed. */
240 leal cond_lock(%ebx), %ecx
242 call __lll_mutex_lock_wait
245 /* Unlock after loop requires waekup. */
250 leal cond_lock(%ebx), %eax
252 call __lll_mutex_unlock_wake
254 .size __pthread_cond_timedwait, .-__pthread_cond_timedwait
255 versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,