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>
29 #define SYS_gettimeofday __NR_gettimeofday
45 .type condvar_cleanup, @function
53 /* Get internal lock. */
59 xaddl %eax, cond_lock(%ebx)
67 leal cond_lock(%ebx), %ecx
69 call __lll_mutex_lock_wait
71 1: addl $1, wakeup_seq(%ebx)
72 adcl $0, wakeup_seq+4(%ebx)
74 addl $1, woken_seq(%ebx)
75 adcl $0, woken_seq+4(%ebx)
83 leal cond_lock(%ebx), %eax
85 call __lll_mutex_unlock_wake
89 .size condvar_cleanup, .-condvar_cleanup
92 /* int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex) */
93 .globl __pthread_cond_wait
94 .type __pthread_cond_wait, @function
105 addl $cond_lock, %ebx
108 /* Get internal lock. */
114 xaddl %eax, cond_lock(%ebx)
119 /* Unlock the mutex. */
121 call __pthread_mutex_unlock_internal
123 addl $1, total_seq(%ebx)
124 adcl $0, total_seq+4(%ebx)
126 /* Install cancellation handler. */
128 call __i686.get_pc_thunk.cx
129 addl $_GLOBAL_OFFSET_TABLE_, %ecx
130 leal condvar_cleanup@GOTOFF(%ecx), %eax
132 leal condvar_cleanup, %eax
139 call _GI_pthread_cleanup_push
141 /* Get and store current wakeup_seq value. */
142 movl wakeup_seq(%ebx), %edi
143 movl wakeup_seq+4(%ebx), %edx
156 4: call __pthread_enable_asynccancel
159 movl %esi, %ecx /* movl $FUTEX_WAIT, %ecx */
161 addl $wakeup_seq-cond_lock, %ebx
162 movl $SYS_futex, %eax
164 subl $wakeup_seq-cond_lock, %ebx
166 call __pthread_disable_asynccancel
174 xaddl %eax, cond_lock(%ebx)
179 6: movl woken_seq(%ebx), %eax
180 movl woken_seq+4(%ebx), %ecx
182 movl wakeup_seq(%ebx), %edi
183 movl wakeup_seq+4(%ebx), %edx
197 9: addl $1, woken_seq(%ebx)
198 adcl $0, woken_seq+4(%ebx)
208 /* Remove cancellation handler. */
209 11: leal 12(%esp), %edx
212 call _GI_pthread_cleanup_pop
216 call __pthread_mutex_lock_internal
223 /* We return the result of the mutex_lock operation. */
226 /* Initial locking failed. */
231 leal cond_lock(%ebx), %ecx
233 call __lll_mutex_lock_wait
236 /* Unlock in loop requires waekup. */
241 leal cond_lock(%ebx), %eax
243 call __lll_mutex_unlock_wake
246 /* Locking in loop failed. */
251 leal cond_lock(%ebx), %ecx
253 call __lll_mutex_lock_wait
256 /* Unlock after loop requires waekup. */
261 leal cond_lock(%ebx), %eax
263 call __lll_mutex_unlock_wake
265 .size __pthread_cond_wait, .-__pthread_cond_wait
266 versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
270 /* int pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
271 const struct timespec *abstime) */
272 .globl __pthread_cond_timedwait
273 .type __pthread_cond_timedwait, @function
275 __pthread_cond_timedwait:
285 addl $cond_lock, %ebx
288 /* Get internal lock. */
294 xaddl %eax, cond_lock(%ebx)
299 /* Unlock the mutex. */
301 call __pthread_mutex_unlock_internal
303 addl $1, total_seq(%ebx)
304 adcl $0, total_seq+4(%ebx)
306 /* Install cancellation handler. */
308 call __i686.get_pc_thunk.cx
309 addl $_GLOBAL_OFFSET_TABLE_, %ecx
310 leal condvar_cleanup@GOTOFF(%ecx), %eax
312 leal condvar_cleanup, %eax
319 call _GI_pthread_cleanup_push
321 /* Get and store current wakeup_seq value. */
322 movl wakeup_seq(%ebx), %edi
323 movl wakeup_seq+4(%ebx), %edx
336 4: call __pthread_enable_asynccancel
339 /* Get the current time. */
343 movl $SYS_gettimeofday, %eax
347 /* Compute relative timeout. */
350 mul %edx /* Milli seconds to nano seconds. */
356 addl $1000000000, %edx
361 /* Store relative timeout. */
365 xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */
367 addl $wakeup_seq-cond_lock, %ebx
368 movl $SYS_futex, %eax
370 subl $wakeup_seq-cond_lock, %ebx
373 call __pthread_disable_asynccancel
381 xaddl %eax, cond_lock(%ebx)
386 6: movl woken_seq(%ebx), %eax
387 movl woken_seq+4(%ebx), %ecx
389 movl wakeup_seq(%ebx), %edi
390 movl wakeup_seq+4(%ebx), %edx
404 15: cmpl $-ETIMEDOUT, %esi
407 13: addl $1, wakeup_seq(%ebx)
408 adcl $0, wakeup_seq+4(%ebx)
409 movl $ETIMEDOUT, %esi
413 14: addl $1, woken_seq(%ebx)
414 adcl $0, woken_seq+4(%ebx)
424 /* Remove cancellation handler. */
425 11: leal 20(%esp), %edx
428 call _GI_pthread_cleanup_pop
432 call __pthread_mutex_lock_internal
442 /* We return the result of the mutex_lock operation. */
445 /* Initial locking failed. */
450 leal cond_lock(%ebx), %ecx
452 call __lll_mutex_lock_wait
455 /* Unlock in loop requires waekup. */
460 leal cond_lock(%ebx), %eax
462 call __lll_mutex_unlock_wake
465 /* Locking in loop failed. */
470 leal cond_lock(%ebx), %ecx
472 call __lll_mutex_lock_wait
475 /* Unlock after loop requires waekup. */
480 leal cond_lock(%ebx), %eax
482 call __lll_mutex_unlock_wake
484 .size __pthread_cond_timedwait, .-__pthread_cond_timedwait
485 versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
489 /* int pthread_cond_signal (pthread_cond_t *cond) */
490 .globl __pthread_cond_signal
491 .type __pthread_cond_signal, @function
493 __pthread_cond_signal:
498 addl $cond_lock, %ebx
503 /* Get internal lock. */
509 xaddl %eax, cond_lock(%ebx)
514 2: movl total_seq+4(%ebx), %eax
515 movl total_seq(%ebx), %ecx
516 cmpl wakeup_seq+4(%ebx), %eax
519 cmpl wakeup_seq(%ebx), %ecx
522 /* Bump the wakeup number. */
523 3: addl $1, wakeup_seq(%ebx)
524 adcl $0, wakeup_seq+4(%ebx)
526 /* Wake up one thread. */
527 addl $wakeup_seq-cond_lock, %ebx
528 movl $FUTEX_WAKE, %ecx
530 movl $SYS_futex, %eax
531 movl %ecx, %edx /* movl $1, %edx */
534 subl $wakeup_seq-cond_lock, %ebx
550 /* Initial locking failed. */
555 leal cond_lock(%ebx), %ecx
557 call __lll_mutex_lock_wait
560 /* Unlock in loop requires waekup. */
565 leal cond_lock(%ebx), %eax
567 call __lll_mutex_unlock_wake
569 .size __pthread_cond_signal, .-__pthread_cond_signal
570 versioned_symbol (libpthread, __pthread_cond_signal, pthread_cond_signal,
574 /* int pthread_cond_broadcast (pthread_cond_t *cond) */
575 .globl __pthread_cond_broadcast
576 .type __pthread_cond_broadcast, @function
578 __pthread_cond_broadcast:
585 addl $cond_lock, %ebx
588 /* Get internal lock. */
594 xaddl %eax, cond_lock(%ebx)
599 2: movl total_seq+4(%ebx), %eax
600 movl total_seq(%ebx), %ecx
601 cmpl wakeup_seq+4(%ebx), %eax
604 cmpl wakeup_seq(%ebx), %ecx
607 /* Case all currently waiting threads to wake up. */
608 3: movl %ecx, wakeup_seq(%ebx)
609 movl %eax, wakeup_seq+4(%ebx)
611 /* Wake up all threads. */
612 addl $wakeup_seq-cond_lock, %ebx
613 movl $FUTEX_WAKE, %ecx
615 movl $SYS_futex, %eax
616 movl $0x7fffffff, %edx
619 subl $wakeup_seq-cond_lock, %ebx
635 /* Initial locking failed. */
640 leal cond_lock(%ebx), %ecx
642 call __lll_mutex_lock_wait
645 /* Unlock in loop requires waekup. */
650 leal cond_lock(%ebx), %eax
652 call __lll_mutex_unlock_wake
654 .size __pthread_cond_broadcast, .-__pthread_cond_broadcast
655 versioned_symbol (libpthread, __pthread_cond_broadcast, pthread_cond_broadcast,
660 .section .gnu.linkonce.t.__i686.get_pc_thunk.cx,"ax",@progbits
661 .globl __i686.get_pc_thunk.cx
662 .hidden __i686.get_pc_thunk.cx
663 .type __i686.get_pc_thunk.cx,@function
664 __i686.get_pc_thunk.cx:
667 .size __i686.get_pc_thunk.cx,.-__i686.get_pc_thunk.cx