1 /* Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009
2 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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 <pthread-errnos.h>
22 #include <kernel-features.h>
23 #include <lowlevellock.h>
24 #include "lowlevel-atomic.h"
28 #ifdef __ASSUME_PRIVATE_FUTEX
29 # define LOAD_PRIVATE_FUTEX_WAIT(reg,tmp,tmp2) \
30 mov #(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg; \
32 # define LOAD_PRIVATE_FUTEX_WAKE(reg,tmp,tmp2) \
33 mov #(FUTEX_WAKE | FUTEX_PRIVATE_FLAG), reg; \
35 # define LOAD_FUTEX_WAIT(reg,tmp,tmp2) \
36 mov #(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), tmp; \
39 # define LOAD_FUTEX_WAIT_ABS(reg,tmp,tmp2) \
40 mov #(FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG), tmp; \
42 mov #(FUTEX_CLOCK_REALTIME >> 8), tmp2; \
46 # define LOAD_FUTEX_WAKE(reg,tmp,tmp2) \
47 mov #(FUTEX_WAKE | FUTEX_PRIVATE_FLAG), tmp; \
52 # define LOAD_PRIVATE_FUTEX_WAIT(reg,tmp,tmp2) \
58 99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \
61 # define LOAD_PRIVATE_FUTEX_WAIT(reg,tmp,tmp2) \
67 mov #FUTEX_WAIT, tmp ; \
68 99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \
71 # define LOAD_PRIVATE_FUTEX_WAKE(reg,tmp,tmp2) \
77 mov #FUTEX_WAKE, tmp ; \
78 99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \
81 # define LOAD_FUTEX_WAIT(reg,tmp,tmp2) \
87 mov #FUTEX_PRIVATE_FLAG, tmp ; \
88 99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \
89 98: extu.b tmp, tmp ; \
93 # define LOAD_FUTEX_WAIT(reg,tmp,tmp2) \
99 mov #FUTEX_PRIVATE_FLAG, tmp ; \
100 99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \
101 98: extu.b tmp, tmp ; \
104 mov #FUTEX_WAIT, tmp ; \
106 # define LOAD_FUTEX_WAIT_ABS(reg,tmp,tmp2) \
112 mov #FUTEX_PRIVATE_FLAG, tmp ; \
113 99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \
114 98: extu.b tmp, tmp ; \
117 mov #FUTEX_WAIT_BITSET, tmp ; \
118 mov #(FUTEX_CLOCK_REALTIME >> 8), tmp2; \
123 # define LOAD_FUTEX_WAKE(reg,tmp,tmp2) \
129 mov #FUTEX_PRIVATE_FLAG, tmp ; \
130 99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \
131 98: extu.b tmp, tmp ; \
134 mov #FUTEX_WAKE, tmp ; \
138 .globl __lll_lock_wait_private
139 .type __lll_lock_wait_private,@function
140 .hidden __lll_lock_wait_private
143 __lll_lock_wait_private:
145 cfi_adjust_cfa_offset(4)
146 cfi_rel_offset (r8, 0)
149 mov #0, r7 /* No timeout. */
150 LOAD_PRIVATE_FUTEX_WAIT (r5, r0, r1)
173 .size __lll_lock_wait_private,.-__lll_lock_wait_private
176 .globl __lll_lock_wait
177 .type __lll_lock_wait,@function
178 .hidden __lll_lock_wait
183 cfi_adjust_cfa_offset(4)
184 cfi_rel_offset (r9, 0)
186 cfi_adjust_cfa_offset(4)
187 cfi_rel_offset (r8, 0)
191 mov #0, r7 /* No timeout. */
193 LOAD_FUTEX_WAIT (r5, r0, r1)
217 .size __lll_lock_wait,.-__lll_lock_wait
222 r4 (r10): futex value
224 .globl __lll_timedlock_wait
225 .type __lll_timedlock_wait,@function
226 .hidden __lll_timedlock_wait
229 __lll_timedlock_wait:
231 cfi_adjust_cfa_offset(4)
232 cfi_rel_offset (r12, 0)
234 # ifndef __ASSUME_FUTEX_CLOCK_REALTIME
251 LOAD_FUTEX_WAIT_ABS (r5, r0, r1)
268 XCHG (r2, @r4, r3) /* NB: lock is implied */
274 cmp/eq #-ETIMEDOUT, r0
288 .long _GLOBAL_OFFSET_TABLE_
290 .long __have_futex_clock_realtime@GOTOFF
293 .long __have_futex_clock_realtime
296 # ifndef __ASSUME_FUTEX_CLOCK_REALTIME
298 /* Check for a valid timeout value. */
305 cfi_adjust_cfa_offset(4)
306 cfi_rel_offset (r11, 0)
308 cfi_adjust_cfa_offset(4)
309 cfi_rel_offset (r10, 0)
311 cfi_adjust_cfa_offset(4)
312 cfi_rel_offset (r9, 0)
314 cfi_adjust_cfa_offset(4)
315 cfi_rel_offset (r8, 0)
321 /* Stack frame for the timespec and timeval structs. */
323 cfi_adjust_cfa_offset(8)
332 /* Get current time. */
335 mov #__NR_gettimeofday, r3
339 /* Compute relative timeout. */
342 dmulu.l r0, r1 /* Micro seconds to nano seconds. */
356 bf 2f /* Time is already up. */
358 mov.l r2, @r15 /* Store relative timeout. */
363 LOAD_FUTEX_WAIT (r5, r0, r1)
381 2: mov #ETIMEDOUT, r3
406 .size __lll_timedlock_wait,.-__lll_timedlock_wait
409 .globl __lll_unlock_wake_private
410 .type __lll_unlock_wake_private,@function
411 .hidden __lll_unlock_wake_private
414 __lll_unlock_wake_private:
415 LOAD_PRIVATE_FUTEX_WAKE (r5, r0, r1)
416 mov #1, r6 /* Wake one thread. */
418 mov.l r7, @r4 /* Stores 0. */
426 .size __lll_unlock_wake_private,.-__lll_unlock_wake_private
429 .globl __lll_unlock_wake
430 .type __lll_unlock_wake,@function
431 .hidden __lll_unlock_wake
435 LOAD_FUTEX_WAKE (r5, r0, r1)
436 mov #1, r6 /* Wake one thread. */
438 mov.l r7, @r4 /* Stores 0. */
446 .size __lll_unlock_wake,.-__lll_unlock_wake
448 .globl __lll_timedwait_tid
449 .type __lll_timedwait_tid,@function
450 .hidden __lll_timedwait_tid
455 cfi_adjust_cfa_offset(4)
456 cfi_rel_offset (r9, 0)
458 cfi_adjust_cfa_offset(4)
459 cfi_rel_offset (r8, 0)
463 /* Stack frame for the timespec and timeval structs. */
465 cfi_adjust_cfa_offset(8)
468 /* Get current time. */
471 mov #__NR_gettimeofday, r3
475 /* Compute relative timeout. */
478 dmulu.l r0, r1 /* Micro seconds to nano seconds. */
492 bf 6f /* Time is already up. */
494 mov.l r2, @r15 /* Store relative timeout. */
502 /* XXX The kernel so far uses global futex for the wakeup at
524 /* Check whether the time expired. */
538 .size __lll_timedwait_tid,.-__lll_timedwait_tid