1 /* Copyright (C) 2003-2014 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <http://www.gnu.org/licenses/>. */
19 #include <pthread-errnos.h>
20 #include <kernel-features.h>
21 #include <lowlevellock.h>
22 #include "lowlevel-atomic.h"
26 #ifdef __ASSUME_PRIVATE_FUTEX
27 # define LOAD_PRIVATE_FUTEX_WAIT(reg,tmp,tmp2) \
28 mov #(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg; \
30 # define LOAD_PRIVATE_FUTEX_WAKE(reg,tmp,tmp2) \
31 mov #(FUTEX_WAKE | FUTEX_PRIVATE_FLAG), reg; \
33 # define LOAD_FUTEX_WAIT(reg,tmp,tmp2) \
34 mov #(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), tmp; \
37 # define LOAD_FUTEX_WAIT_ABS(reg,tmp,tmp2) \
38 mov #(FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG), tmp; \
40 mov #(FUTEX_CLOCK_REALTIME >> 8), tmp2; \
44 # define LOAD_FUTEX_WAKE(reg,tmp,tmp2) \
45 mov #(FUTEX_WAKE | FUTEX_PRIVATE_FLAG), tmp; \
50 # define LOAD_PRIVATE_FUTEX_WAIT(reg,tmp,tmp2) \
56 99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \
59 # define LOAD_PRIVATE_FUTEX_WAIT(reg,tmp,tmp2) \
65 mov #FUTEX_WAIT, tmp ; \
66 99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \
69 # define LOAD_PRIVATE_FUTEX_WAKE(reg,tmp,tmp2) \
75 mov #FUTEX_WAKE, tmp ; \
76 99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \
79 # define LOAD_FUTEX_WAIT(reg,tmp,tmp2) \
85 mov #FUTEX_PRIVATE_FLAG, tmp ; \
86 99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \
87 98: extu.b tmp, tmp ; \
91 # define LOAD_FUTEX_WAIT(reg,tmp,tmp2) \
97 mov #FUTEX_PRIVATE_FLAG, tmp ; \
98 99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \
99 98: extu.b tmp, tmp ; \
102 mov #FUTEX_WAIT, tmp ; \
105 # define LOAD_FUTEX_WAIT_ABS(reg,tmp,tmp2) \
111 mov #FUTEX_PRIVATE_FLAG, tmp ; \
112 99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \
113 98: extu.b tmp, tmp ; \
116 mov #FUTEX_WAIT_BITSET, tmp ; \
117 mov #(FUTEX_CLOCK_REALTIME >> 8), tmp2; \
121 # define LOAD_FUTEX_WAKE(reg,tmp,tmp2) \
127 mov #FUTEX_PRIVATE_FLAG, tmp ; \
128 99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \
129 98: extu.b tmp, tmp ; \
132 mov #FUTEX_WAKE, tmp ; \
136 .globl __lll_lock_wait_private
137 .type __lll_lock_wait_private,@function
138 .hidden __lll_lock_wait_private
141 __lll_lock_wait_private:
143 cfi_adjust_cfa_offset(4)
144 cfi_rel_offset (r8, 0)
147 mov #0, r7 /* No timeout. */
148 LOAD_PRIVATE_FUTEX_WAIT (r5, r0, r1)
168 cfi_adjust_cfa_offset (-4)
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)
213 cfi_adjust_cfa_offset (-4)
216 cfi_adjust_cfa_offset (-4)
221 .size __lll_lock_wait,.-__lll_lock_wait
226 r4 (r10): futex value
228 .globl __lll_timedlock_wait
229 .type __lll_timedlock_wait,@function
230 .hidden __lll_timedlock_wait
233 __lll_timedlock_wait:
235 cfi_adjust_cfa_offset(4)
236 cfi_rel_offset (r12, 0)
238 # ifndef __ASSUME_FUTEX_CLOCK_REALTIME
251 /* if (timeout->tv_sec < 0) return ETIMEDOUT; */
261 LOAD_FUTEX_WAIT_ABS (r5, r0, r1)
278 XCHG (r2, @r4, r3) /* NB: lock is implied */
284 cmp/eq #-ETIMEDOUT, r0
295 /* Omit CFI for restore in delay slot. */
297 # ifndef __ASSUME_FUTEX_CLOCK_REALTIME
301 .long _GLOBAL_OFFSET_TABLE_
303 .long __have_futex_clock_realtime@GOTOFF
306 .long __have_futex_clock_realtime
310 /* Check for a valid timeout value. */
319 cfi_adjust_cfa_offset(4)
320 cfi_rel_offset (r11, 0)
322 cfi_adjust_cfa_offset(4)
323 cfi_rel_offset (r10, 0)
325 cfi_adjust_cfa_offset(4)
326 cfi_rel_offset (r9, 0)
328 cfi_adjust_cfa_offset(4)
329 cfi_rel_offset (r8, 0)
335 /* Stack frame for the timespec and timeval structs. */
337 cfi_adjust_cfa_offset(8)
346 /* Get current time. */
349 mov #__NR_gettimeofday, r3
353 /* Compute relative timeout. */
356 dmulu.l r0, r1 /* Micro seconds to nano seconds. */
370 bf 2f /* Time is already up. */
372 mov.l r2, @r15 /* Store relative timeout. */
377 LOAD_FUTEX_WAIT (r5, r0, r1)
395 2: mov #ETIMEDOUT, r3
399 cfi_adjust_cfa_offset (-8)
401 cfi_adjust_cfa_offset (-4)
404 cfi_adjust_cfa_offset (-4)
407 cfi_adjust_cfa_offset (-4)
410 cfi_adjust_cfa_offset (-4)
413 cfi_adjust_cfa_offset (-4)
422 cfi_adjust_cfa_offset (-4)
435 .size __lll_timedlock_wait,.-__lll_timedlock_wait
438 .globl __lll_unlock_wake_private
439 .type __lll_unlock_wake_private,@function
440 .hidden __lll_unlock_wake_private
443 __lll_unlock_wake_private:
444 LOAD_PRIVATE_FUTEX_WAKE (r5, r0, r1)
445 mov #1, r6 /* Wake one thread. */
447 mov.l r7, @r4 /* Stores 0. */
455 .size __lll_unlock_wake_private,.-__lll_unlock_wake_private
458 .globl __lll_unlock_wake
459 .type __lll_unlock_wake,@function
460 .hidden __lll_unlock_wake
464 LOAD_FUTEX_WAKE (r5, r0, r1)
465 mov #1, r6 /* Wake one thread. */
467 mov.l r7, @r4 /* Stores 0. */
475 .size __lll_unlock_wake,.-__lll_unlock_wake
477 .globl __lll_timedwait_tid
478 .type __lll_timedwait_tid,@function
479 .hidden __lll_timedwait_tid
484 cfi_adjust_cfa_offset(4)
485 cfi_rel_offset (r9, 0)
487 cfi_adjust_cfa_offset(4)
488 cfi_rel_offset (r8, 0)
492 /* Stack frame for the timespec and timeval structs. */
494 cfi_adjust_cfa_offset(8)
497 /* Get current time. */
500 mov #__NR_gettimeofday, r3
504 /* Compute relative timeout. */
507 dmulu.l r0, r1 /* Micro seconds to nano seconds. */
521 bf 6f /* Time is already up. */
523 mov.l r2, @r15 /* Store relative timeout. */
531 /* XXX The kernel so far uses global futex for the wakeup at
550 cfi_adjust_cfa_offset (-8)
552 cfi_adjust_cfa_offset (-4)
556 /* Omit CFI for restore in delay slot. */
559 /* Check whether the time expired. */
573 .size __lll_timedwait_tid,.-__lll_timedwait_tid