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, see
18 <http://www.gnu.org/licenses/>. */
21 #include <pthread-errnos.h>
22 #include <lowlevellock.h>
23 #include <lowlevelrobustlock.h>
24 #include <bits/kernel-features.h>
28 #define FUTEX_WAITERS 0x80000000
29 #define FUTEX_OWNER_DIED 0x40000000
31 #ifdef __ASSUME_PRIVATE_FUTEX
32 # define LOAD_FUTEX_WAIT(reg) \
33 xorl $(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg
34 # define LOAD_FUTEX_WAIT_ABS(reg) \
35 xorl $(FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME), reg
38 # define LOAD_FUTEX_WAIT(reg) \
39 xorl $FUTEX_PRIVATE_FLAG, reg ; \
40 andl %fs:PRIVATE_FUTEX, reg
42 # define LOAD_FUTEX_WAIT(reg) \
43 xorl $FUTEX_PRIVATE_FLAG, reg ; \
44 andl %fs:PRIVATE_FUTEX, reg ; \
47 # define LOAD_FUTEX_WAIT_ABS(reg) \
48 xorl $FUTEX_PRIVATE_FLAG, reg ; \
49 andl %fs:PRIVATE_FUTEX, reg ; \
50 orl $FUTEX_WAIT_BITSET | FUTEX_CLOCK_REALTIME, reg
53 /* For the calculation see asm/vsyscall.h. */
54 #define VSYSCALL_ADDR_vgettimeofday 0xffffffffff600000
57 .globl __lll_robust_lock_wait
58 .type __lll_robust_lock_wait,@function
59 .hidden __lll_robust_lock_wait
61 __lll_robust_lock_wait:
64 cfi_adjust_cfa_offset(8)
66 cfi_adjust_cfa_offset(8)
70 xorq %r10, %r10 /* No timeout. */
71 LOAD_FUTEX_WAIT (%esi)
74 orl $FUTEX_WAITERS, %edx
76 testl $FUTEX_OWNER_DIED, %eax
86 1: movl $SYS_futex, %eax
95 orl $FUTEX_WAITERS, %edx
102 cfi_adjust_cfa_offset(-8)
105 cfi_adjust_cfa_offset(-8)
109 .size __lll_robust_lock_wait,.-__lll_robust_lock_wait
112 .globl __lll_robust_timedlock_wait
113 .type __lll_robust_timedlock_wait,@function
114 .hidden __lll_robust_timedlock_wait
116 __lll_robust_timedlock_wait:
118 # ifndef __ASSUME_FUTEX_CLOCK_REALTIME
120 cmpl $0, __have_futex_clock_realtime@GOTOFF(%rip)
122 cmpl $0, __have_futex_clock_realtime
128 cfi_adjust_cfa_offset(8)
129 cfi_rel_offset(%r9, 0)
131 movl $0xffffffff, %r9d
132 LOAD_FUTEX_WAIT_ABS (%esi)
134 1: testl $FUTEX_OWNER_DIED, %eax
138 orl $FUTEX_WAITERS, %edx
144 cmpxchgl %edx, (%rdi)
145 movq $0, %rcx /* Must use mov to avoid changing cc. */
148 5: movl $SYS_futex, %eax
158 orl $FUTEX_WAITERS, %edx
160 cmpxchgl %edx, (%rdi)
164 cfi_adjust_cfa_offset(-8)
168 cfi_adjust_cfa_offset(8)
169 cfi_rel_offset(%r9, 0)
170 /* Check whether the time expired. */
171 2: cmpl $-ETIMEDOUT, %ecx
179 cfi_adjust_cfa_offset(-8)
183 # ifndef __ASSUME_FUTEX_CLOCK_REALTIME
185 /* Check for a valid timeout value. */
186 cmpq $1000000000, 8(%rdx)
190 cfi_adjust_cfa_offset(8)
192 cfi_adjust_cfa_offset(8)
194 cfi_adjust_cfa_offset(8)
196 cfi_adjust_cfa_offset(8)
199 cfi_offset(%r12, -32)
200 cfi_offset(%r13, -40)
202 cfi_adjust_cfa_offset(8)
204 /* Stack frame for the timespec and timeval structs. */
206 cfi_adjust_cfa_offset(32)
211 1: movq %rax, 16(%rsp)
213 /* Get current time. */
216 movq $VSYSCALL_ADDR_vgettimeofday, %rax
217 /* This is a regular function call, all caller-save registers
218 might be clobbered. */
221 /* Compute relative timeout. */
224 mul %rdi /* Milli seconds to nano seconds. */
230 addq $1000000000, %rsi
233 js 8f /* Time is already up. */
236 movq %rdi, (%rsp) /* Store relative timeout. */
241 orl $FUTEX_WAITERS, %edx
243 testl $FUTEX_OWNER_DIED, %eax
250 cmpxchgl %edx, (%r12)
251 movq $0, %rcx /* Must use mov to avoid changing cc. */
256 LOAD_FUTEX_WAIT (%esi)
258 movl $SYS_futex, %eax
268 orl $FUTEX_WAITERS, %edx
270 cmpxchgl %edx, (%r12)
274 cfi_adjust_cfa_offset(-40)
276 cfi_adjust_cfa_offset(-8)
279 cfi_adjust_cfa_offset(-8)
282 cfi_adjust_cfa_offset(-8)
285 cfi_adjust_cfa_offset(-8)
289 3: movl $EINVAL, %eax
292 cfi_adjust_cfa_offset(72)
295 cfi_offset(%r12, -32)
296 cfi_offset(%r13, -40)
297 /* Check whether the time expired. */
298 7: cmpl $-ETIMEDOUT, %ecx
301 8: movl $ETIMEDOUT, %eax
305 .size __lll_robust_timedlock_wait,.-__lll_robust_timedlock_wait