1 /* Copyright (C) 2003, 2004, 2005, 2007, 2008
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_WAKE(reg,tmp,tmp2) \
40 mov #(FUTEX_WAKE | FUTEX_PRIVATE_FLAG), tmp; \
45 # define LOAD_PRIVATE_FUTEX_WAIT(reg,tmp,tmp2) \
51 99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \
54 # define LOAD_PRIVATE_FUTEX_WAIT(reg,tmp,tmp2) \
60 mov #FUTEX_WAIT, tmp ; \
61 99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \
64 # define LOAD_PRIVATE_FUTEX_WAKE(reg,tmp,tmp2) \
70 mov #FUTEX_WAKE, tmp ; \
71 99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \
74 # define LOAD_FUTEX_WAIT(reg,tmp,tmp2) \
80 mov #FUTEX_PRIVATE_FLAG, tmp ; \
81 99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \
82 98: extu.b tmp, tmp ; \
86 # define LOAD_FUTEX_WAIT(reg,tmp,tmp2) \
92 mov #FUTEX_PRIVATE_FLAG, tmp ; \
93 99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \
94 98: extu.b tmp, tmp ; \
97 mov #FUTEX_WAIT, tmp ; \
100 # define LOAD_FUTEX_WAKE(reg,tmp,tmp2) \
106 mov #FUTEX_PRIVATE_FLAG, tmp ; \
107 99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \
108 98: extu.b tmp, tmp ; \
111 mov #FUTEX_WAKE, tmp ; \
115 .globl __lll_lock_wait_private
116 .type __lll_lock_wait_private,@function
117 .hidden __lll_lock_wait_private
120 __lll_lock_wait_private:
122 cfi_adjust_cfa_offset(4)
123 cfi_rel_offset (r8, 0)
126 mov #0, r7 /* No timeout. */
127 LOAD_PRIVATE_FUTEX_WAIT (r5, r0, r1)
150 .size __lll_lock_wait_private,.-__lll_lock_wait_private
153 .globl __lll_lock_wait
154 .type __lll_lock_wait,@function
155 .hidden __lll_lock_wait
160 cfi_adjust_cfa_offset(4)
161 cfi_rel_offset (r9, 0)
163 cfi_adjust_cfa_offset(4)
164 cfi_rel_offset (r8, 0)
168 mov #0, r7 /* No timeout. */
170 LOAD_FUTEX_WAIT (r5, r0, r1)
194 .size __lll_lock_wait,.-__lll_lock_wait
196 .globl __lll_timedlock_wait
197 .type __lll_timedlock_wait,@function
198 .hidden __lll_timedlock_wait
201 __lll_timedlock_wait:
202 /* Check for a valid timeout value. */
209 cfi_adjust_cfa_offset(4)
210 cfi_rel_offset (r11, 0)
212 cfi_adjust_cfa_offset(4)
213 cfi_rel_offset (r10, 0)
215 cfi_adjust_cfa_offset(4)
216 cfi_rel_offset (r9, 0)
218 cfi_adjust_cfa_offset(4)
219 cfi_rel_offset (r8, 0)
225 /* Stack frame for the timespec and timeval structs. */
227 cfi_adjust_cfa_offset(8)
236 /* Get current time. */
239 mov #__NR_gettimeofday, r3
243 /* Compute relative timeout. */
246 dmulu.l r0, r1 /* Micro seconds to nano seconds. */
260 bf 2f /* Time is already up. */
262 mov.l r2, @r15 /* Store relative timeout. */
267 LOAD_FUTEX_WAIT (r5, r0, r1)
285 2: mov #ETIMEDOUT, r3
307 .size __lll_timedlock_wait,.-__lll_timedlock_wait
310 .globl __lll_unlock_wake_private
311 .type __lll_unlock_wake_private,@function
312 .hidden __lll_unlock_wake_private
315 __lll_unlock_wake_private:
316 LOAD_PRIVATE_FUTEX_WAKE (r5, r0, r1)
317 mov #1, r6 /* Wake one thread. */
319 mov.l r7, @r4 /* Stores 0. */
327 .size __lll_unlock_wake_private,.-__lll_unlock_wake_private
330 .globl __lll_unlock_wake
331 .type __lll_unlock_wake,@function
332 .hidden __lll_unlock_wake
336 LOAD_FUTEX_WAKE (r5, r0, r1)
337 mov #1, r6 /* Wake one thread. */
339 mov.l r7, @r4 /* Stores 0. */
347 .size __lll_unlock_wake,.-__lll_unlock_wake
349 .globl __lll_timedwait_tid
350 .type __lll_timedwait_tid,@function
351 .hidden __lll_timedwait_tid
356 cfi_adjust_cfa_offset(4)
357 cfi_rel_offset (r9, 0)
359 cfi_adjust_cfa_offset(4)
360 cfi_rel_offset (r8, 0)
364 /* Stack frame for the timespec and timeval structs. */
366 cfi_adjust_cfa_offset(8)
369 /* Get current time. */
372 mov #__NR_gettimeofday, r3
376 /* Compute relative timeout. */
379 dmulu.l r0, r1 /* Micro seconds to nano seconds. */
393 bf 6f /* Time is already up. */
395 mov.l r2, @r15 /* Store relative timeout. */
403 /* XXX The kernel so far uses global futex for the wakeup at
425 /* Check whether the time expired. */
439 .size __lll_timedwait_tid,.-__lll_timedwait_tid