1 /* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2009
2 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, write to the Free
18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
22 #include <pthread-errnos.h>
23 #include <lowlevellock.h>
24 #include <lowlevelrobustlock.h>
25 #include <bits/kernel-features.h>
29 #define FUTEX_WAITERS 0x80000000
30 #define FUTEX_OWNER_DIED 0x40000000
32 #ifdef __ASSUME_PRIVATE_FUTEX
33 # define LOAD_FUTEX_WAIT(reg) \
34 xorl $(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg
35 # define LOAD_FUTEX_WAIT_ABS(reg) \
36 xorl $(FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME), reg
39 # define LOAD_FUTEX_WAIT(reg) \
40 xorl $FUTEX_PRIVATE_FLAG, reg ; \
41 andl %fs:PRIVATE_FUTEX, reg
43 # define LOAD_FUTEX_WAIT(reg) \
44 xorl $FUTEX_PRIVATE_FLAG, reg ; \
45 andl %fs:PRIVATE_FUTEX, reg ; \
48 # define LOAD_FUTEX_WAIT_ABS(reg) \
49 xorl $FUTEX_PRIVATE_FLAG, reg ; \
50 andl %fs:PRIVATE_FUTEX, reg ; \
51 orl $FUTEX_WAIT_BITSET | FUTEX_CLOCK_REALTIME, reg
54 /* For the calculation see asm/vsyscall.h. */
55 #define VSYSCALL_ADDR_vgettimeofday 0xffffffffff600000
58 .globl __lll_robust_lock_wait
59 .type __lll_robust_lock_wait,@function
60 .hidden __lll_robust_lock_wait
62 __lll_robust_lock_wait:
65 cfi_adjust_cfa_offset(8)
67 cfi_adjust_cfa_offset(8)
71 xorq %r10, %r10 /* No timeout. */
72 LOAD_FUTEX_WAIT (%esi)
75 orl $FUTEX_WAITERS, %edx
77 testl $FUTEX_OWNER_DIED, %eax
87 1: movl $SYS_futex, %eax
96 orl $FUTEX_WAITERS, %edx
103 cfi_adjust_cfa_offset(-8)
106 cfi_adjust_cfa_offset(-8)
110 .size __lll_robust_lock_wait,.-__lll_robust_lock_wait
113 .globl __lll_robust_timedlock_wait
114 .type __lll_robust_timedlock_wait,@function
115 .hidden __lll_robust_timedlock_wait
117 __lll_robust_timedlock_wait:
119 # ifndef __ASSUME_FUTEX_CLOCK_REALTIME
121 cmpl $0, __have_futex_clock_realtime(%rip)
123 cmpl $0, __have_futex_clock_realtime
129 cfi_adjust_cfa_offset(8)
130 cfi_rel_offset(%r9, 0)
132 movl $0xffffffff, %r9d
133 LOAD_FUTEX_WAIT_ABS (%esi)
135 1: testl $FUTEX_OWNER_DIED, %eax
139 orl $FUTEX_WAITERS, %edx
145 cmpxchgl %edx, (%rdi)
146 movq $0, %rcx /* Must use mov to avoid changing cc. */
149 5: movl $SYS_futex, %eax
159 orl $FUTEX_WAITERS, %edx
161 cmpxchgl %edx, (%rdi)
165 cfi_adjust_cfa_offset(-8)
169 cfi_adjust_cfa_offset(8)
170 cfi_rel_offset(%r9, 0)
171 /* Check whether the time expired. */
172 2: cmpl $-ETIMEDOUT, %ecx
180 cfi_adjust_cfa_offset(-8)
184 # ifndef __ASSUME_FUTEX_CLOCK_REALTIME
186 /* Check for a valid timeout value. */
187 cmpq $1000000000, 8(%rdx)
191 cfi_adjust_cfa_offset(8)
193 cfi_adjust_cfa_offset(8)
195 cfi_adjust_cfa_offset(8)
197 cfi_adjust_cfa_offset(8)
200 cfi_offset(%r12, -32)
201 cfi_offset(%r13, -40)
203 cfi_adjust_cfa_offset(8)
205 /* Stack frame for the timespec and timeval structs. */
207 cfi_adjust_cfa_offset(32)
212 1: movq %rax, 16(%rsp)
214 /* Get current time. */
217 movq $VSYSCALL_ADDR_vgettimeofday, %rax
218 /* This is a regular function call, all caller-save registers
219 might be clobbered. */
222 /* Compute relative timeout. */
225 mul %rdi /* Milli seconds to nano seconds. */
231 addq $1000000000, %rsi
234 js 8f /* Time is already up. */
237 movq %rdi, (%rsp) /* Store relative timeout. */
242 orl $FUTEX_WAITERS, %edx
244 testl $FUTEX_OWNER_DIED, %eax
251 cmpxchgl %edx, (%r12)
252 movq $0, %rcx /* Must use mov to avoid changing cc. */
257 LOAD_FUTEX_WAIT (%esi)
259 movl $SYS_futex, %eax
269 orl $FUTEX_WAITERS, %edx
271 cmpxchgl %edx, (%r12)
275 cfi_adjust_cfa_offset(-40)
277 cfi_adjust_cfa_offset(-8)
280 cfi_adjust_cfa_offset(-8)
283 cfi_adjust_cfa_offset(-8)
286 cfi_adjust_cfa_offset(-8)
290 3: movl $EINVAL, %eax
293 cfi_adjust_cfa_offset(72)
296 cfi_offset(%r12, -32)
297 cfi_offset(%r13, -40)
298 /* Check whether the time expired. */
299 7: cmpl $-ETIMEDOUT, %ecx
302 8: movl $ETIMEDOUT, %eax
306 .size __lll_robust_timedlock_wait,.-__lll_robust_timedlock_wait