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:
54 /* Get internal lock. */
60 xaddl %eax, cond_lock(%ebx)
65 /* Unlock the mutex. */
67 call __pthread_mutex_unlock_internal
72 addl $1, total_seq(%ebx)
73 adcl $0, total_seq+4(%ebx)
75 /* Install cancellation handler. */
77 call __i686.get_pc_thunk.cx
78 addl $_GLOBAL_OFFSET_TABLE_, %ecx
79 leal __condvar_cleanup@GOTOFF(%ecx), %eax
81 leal __condvar_cleanup, %eax
88 call __pthread_cleanup_push
90 /* Address of the mutex. */
92 /* Get and store current wakeup_seq value. */
93 movl wakeup_seq(%ebx), %edi
94 movl wakeup_seq+4(%ebx), %edx
97 /* Prepare structure passed to cancellation handler. */
106 subl $1, cond_lock(%ebx)
110 4: leal 8(%esp), %eax
111 call __pthread_enable_asynccancel_2
113 /* Get the current time. */
115 #ifdef __NR_clock_gettime
116 /* Get the clock number. Note that the field in the condvar
117 structure stores the number minus 1. */
118 movl cond_clock(%ebx), %ebx
119 /* Only clocks 0 and 1 are allowed. Both are handled in the
122 movl $__NR_clock_gettime, %eax
124 # ifndef __ASSUME_POSIX_TIMERS
130 /* Compute relative timeout. */
136 /* Get the current time. */
139 movl $SYS_gettimeofday, %eax
143 /* Compute relative timeout. */
146 mul %edx /* Milli seconds to nano seconds. */
153 addl $1000000000, %edx
158 /* Store relative timeout. */
159 21: movl %ecx, 12(%esp)
162 xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */
164 addl $wakeup_seq, %ebx
165 movl $SYS_futex, %eax
167 subl $wakeup_seq, %ebx
171 call __pthread_disable_asynccancel
179 xaddl %eax, cond_lock(%ebx)
184 6: movl woken_seq(%ebx), %eax
185 movl woken_seq+4(%ebx), %ecx
187 movl wakeup_seq(%ebx), %edi
188 movl wakeup_seq+4(%ebx), %edx
202 15: cmpl $-ETIMEDOUT, %esi
205 13: addl $1, wakeup_seq(%ebx)
206 adcl $0, wakeup_seq+4(%ebx)
207 movl $ETIMEDOUT, %esi
211 14: addl $1, woken_seq(%ebx)
212 adcl $0, woken_seq+4(%ebx)
218 subl $1, cond_lock(%ebx)
222 /* Remove cancellation handler. */
223 11: movl 28+CLEANUP_PREV(%esp), %edx
224 movl %edx, %gs:CLEANUP
226 /* Trick ahead: (%esp) contains the address of the mutex. */
227 call __pthread_mutex_lock_internal
230 /* We return the result of the mutex_lock operation if it failed. */
241 /* Initial locking failed. */
246 leal cond_lock(%ebx), %ecx
248 call __lll_mutex_lock_wait
251 /* Unlock in loop requires waekup. */
256 leal cond_lock(%ebx), %eax
258 call __lll_mutex_unlock_wake
261 /* Locking in loop failed. */
266 leal cond_lock(%ebx), %ecx
268 call __lll_mutex_lock_wait
271 /* Unlock after loop requires waekup. */
276 leal cond_lock(%ebx), %eax
278 call __lll_mutex_unlock_wake
281 /* The initial unlocking of the mutex failed. */
282 16: movl %eax, (%esp)
287 subl $1, cond_lock(%ebx)
294 leal cond_lock(%ebx), %eax
296 call __lll_mutex_unlock_wake
301 #if defined __NR_clock_gettime && !defined __ASSUME_POSIX_TIMERS
302 /* clock_gettime not available. */
303 19: leal 12(%esp), %ebx
305 movl $SYS_gettimeofday, %eax
309 /* Compute relative timeout. */
312 mul %edx /* Milli seconds to nano seconds. */
318 addl $1000000000, %edx
324 .size __pthread_cond_timedwait, .-__pthread_cond_timedwait
325 versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,