1 /* Copyright (C) 2002-2016 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
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, see
17 <http://www.gnu.org/licenses/>. */
20 #include <pthread-errnos.h>
21 #include <lowlevellock.h>
22 #include <lowlevelrobustlock.h>
23 #include <kernel-features.h>
27 #define FUTEX_WAITERS 0x80000000
28 #define FUTEX_OWNER_DIED 0x40000000
30 #ifdef __ASSUME_PRIVATE_FUTEX
31 # define LOAD_FUTEX_WAIT(reg) \
32 xorl $(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg
33 # define LOAD_FUTEX_WAIT_ABS(reg) \
34 xorl $(FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME), reg
37 # define LOAD_FUTEX_WAIT(reg) \
38 xorl $FUTEX_PRIVATE_FLAG, reg ; \
39 andl %fs:PRIVATE_FUTEX, reg
41 # define LOAD_FUTEX_WAIT(reg) \
42 xorl $FUTEX_PRIVATE_FLAG, reg ; \
43 andl %fs:PRIVATE_FUTEX, reg ; \
46 # define LOAD_FUTEX_WAIT_ABS(reg) \
47 xorl $FUTEX_PRIVATE_FLAG, reg ; \
48 andl %fs:PRIVATE_FUTEX, reg ; \
49 orl $FUTEX_WAIT_BITSET | FUTEX_CLOCK_REALTIME, reg
53 .globl __lll_robust_lock_wait
54 .type __lll_robust_lock_wait,@function
55 .hidden __lll_robust_lock_wait
57 __lll_robust_lock_wait:
60 cfi_adjust_cfa_offset(8)
62 cfi_adjust_cfa_offset(8)
66 xorq %r10, %r10 /* No timeout. */
67 LOAD_FUTEX_WAIT (%esi)
70 orl $FUTEX_WAITERS, %edx
72 testl $FUTEX_OWNER_DIED, %eax
82 1: movl $SYS_futex, %eax
91 orl $FUTEX_WAITERS, %edx
98 cfi_adjust_cfa_offset(-8)
101 cfi_adjust_cfa_offset(-8)
105 .size __lll_robust_lock_wait,.-__lll_robust_lock_wait
108 .globl __lll_robust_timedlock_wait
109 .type __lll_robust_timedlock_wait,@function
110 .hidden __lll_robust_timedlock_wait
112 __lll_robust_timedlock_wait:
114 # ifndef __ASSUME_FUTEX_CLOCK_REALTIME
116 cmpl $0, __have_futex_clock_realtime(%rip)
118 cmpl $0, __have_futex_clock_realtime
127 cfi_adjust_cfa_offset(8)
128 cfi_rel_offset(%r9, 0)
130 movl $0xffffffff, %r9d
131 LOAD_FUTEX_WAIT_ABS (%esi)
133 1: testl $FUTEX_OWNER_DIED, %eax
137 orl $FUTEX_WAITERS, %edx
143 cmpxchgl %edx, (%rdi)
144 movq $0, %rcx /* Must use mov to avoid changing cc. */
147 5: movl $SYS_futex, %eax
157 orl $FUTEX_WAITERS, %edx
159 cmpxchgl %edx, (%rdi)
163 cfi_adjust_cfa_offset(-8)
167 cfi_adjust_cfa_offset(8)
168 cfi_rel_offset(%r9, 0)
169 /* Check whether the time expired. */
170 2: cmpl $-ETIMEDOUT, %ecx
178 cfi_adjust_cfa_offset(-8)
181 7: movl $ETIMEDOUT, %eax
185 # ifndef __ASSUME_FUTEX_CLOCK_REALTIME
187 /* Check for a valid timeout value. */
188 cmpq $1000000000, 8(%rdx)
192 cfi_adjust_cfa_offset(8)
194 cfi_adjust_cfa_offset(8)
196 cfi_adjust_cfa_offset(8)
198 cfi_adjust_cfa_offset(8)
201 cfi_offset(%r12, -32)
202 cfi_offset(%r13, -40)
204 cfi_adjust_cfa_offset(8)
206 /* Stack frame for the timespec and timeval structs. */
208 cfi_adjust_cfa_offset(32)
213 1: movq %rax, 16(%rsp)
215 /* Get current time. */
218 /* This call works because we directly jump to a system call entry
219 which preserves all the registers. */
220 call JUMPTARGET(__gettimeofday)
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