1 /* Copyright (C) 2002-2018 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 <kernel-features.h>
22 #include <lowlevellock.h>
24 #include <stap-probe.h>
28 #define LOAD_PRIVATE_FUTEX_WAIT(reg) \
29 movl $(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg
30 #define LOAD_PRIVATE_FUTEX_WAKE(reg) \
31 movl $(FUTEX_WAKE | FUTEX_PRIVATE_FLAG), reg
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
36 #define LOAD_FUTEX_WAKE(reg) \
37 xorl $(FUTEX_WAKE | FUTEX_PRIVATE_FLAG), reg
39 .globl __lll_lock_wait_private
40 .type __lll_lock_wait_private,@function
41 .hidden __lll_lock_wait_private
43 __lll_lock_wait_private:
46 cfi_adjust_cfa_offset(4)
48 cfi_adjust_cfa_offset(4)
50 cfi_adjust_cfa_offset(4)
57 xorl %esi, %esi /* No timeout. */
58 LOAD_PRIVATE_FUTEX_WAIT (%ecx)
60 cmpl %edx, %eax /* NB: %edx == 2 */
63 1: LIBC_PROBE (lll_lock_wait_private, 1, %ebx)
68 xchgl %eax, (%ebx) /* NB: lock is implied */
74 cfi_adjust_cfa_offset(-4)
77 cfi_adjust_cfa_offset(-4)
80 cfi_adjust_cfa_offset(-4)
84 .size __lll_lock_wait_private,.-__lll_lock_wait_private
87 .globl __lll_lock_wait
88 .type __lll_lock_wait,@function
89 .hidden __lll_lock_wait
94 cfi_adjust_cfa_offset(4)
96 cfi_adjust_cfa_offset(4)
98 cfi_adjust_cfa_offset(4)
100 cfi_offset(%ebx, -12)
101 cfi_offset(%esi, -16)
105 xorl %esi, %esi /* No timeout. */
106 LOAD_FUTEX_WAIT (%ecx)
108 cmpl %edx, %eax /* NB: %edx == 2 */
111 1: movl $SYS_futex, %eax
115 xchgl %eax, (%ebx) /* NB: lock is implied */
121 cfi_adjust_cfa_offset(-4)
124 cfi_adjust_cfa_offset(-4)
127 cfi_adjust_cfa_offset(-4)
131 .size __lll_lock_wait,.-__lll_lock_wait
138 .globl __lll_timedlock_wait
139 .type __lll_timedlock_wait,@function
140 .hidden __lll_timedlock_wait
142 __lll_timedlock_wait:
145 cfi_adjust_cfa_offset(4)
146 cfi_rel_offset(%ebp, 0)
148 cfi_adjust_cfa_offset(4)
149 cfi_rel_offset(%ebx, 0)
151 # ifndef __ASSUME_FUTEX_CLOCK_REALTIME
154 cmpl $0, __have_futex_clock_realtime@GOTOFF(%ebx)
156 cmpl $0, __have_futex_clock_realtime
167 movl $0xffffffff, %ebp
168 LOAD_FUTEX_WAIT_ABS (%ecx)
174 1: movl $SYS_futex, %eax
178 2: xchgl %edx, (%ebx) /* NB: lock is implied */
183 cmpl $-ETIMEDOUT, %eax
192 cfi_adjust_cfa_offset(-4)
195 cfi_adjust_cfa_offset(-4)
199 8: movl $ETIMEDOUT, %eax
202 # ifndef __ASSUME_FUTEX_CLOCK_REALTIME
204 /* Check for a valid timeout value. */
205 cmpl $1000000000, 4(%edx)
209 cfi_adjust_cfa_offset(4)
210 cfi_rel_offset(%esi, 0)
212 cfi_adjust_cfa_offset(4)
213 cfi_rel_offset(%edi, 0)
215 /* Stack frame for the timespec and timeval structs. */
217 cfi_adjust_cfa_offset(8)
229 /* Get current time. */
232 movl $__NR_gettimeofday, %eax
235 /* Compute relative timeout. */
238 mul %edx /* Milli seconds to nano seconds. */
244 addl $1000000000, %edx
247 js 2f /* Time is already up. */
249 /* Store relative timeout. */
258 LOAD_FUTEX_WAIT (%ecx)
259 movl $SYS_futex, %eax
268 cmpl $-ETIMEDOUT, %eax
270 2: movl $ETIMEDOUT, %edx
273 cfi_adjust_cfa_offset(-8)
275 cfi_adjust_cfa_offset(-4)
278 cfi_adjust_cfa_offset(-4)
281 cfi_adjust_cfa_offset(-4)
284 cfi_adjust_cfa_offset(-4)
289 3: movl $EINVAL, %edx
293 .size __lll_timedlock_wait,.-__lll_timedlock_wait
296 .globl __lll_unlock_wake_private
297 .type __lll_unlock_wake_private,@function
298 .hidden __lll_unlock_wake_private
300 __lll_unlock_wake_private:
303 cfi_adjust_cfa_offset(4)
305 cfi_adjust_cfa_offset(4)
307 cfi_adjust_cfa_offset(4)
309 cfi_offset(%ecx, -12)
310 cfi_offset(%edx, -16)
314 LOAD_PRIVATE_FUTEX_WAKE (%ecx)
315 movl $1, %edx /* Wake one thread. */
316 movl $SYS_futex, %eax
320 cfi_adjust_cfa_offset(-4)
323 cfi_adjust_cfa_offset(-4)
326 cfi_adjust_cfa_offset(-4)
330 .size __lll_unlock_wake_private,.-__lll_unlock_wake_private
333 .globl __lll_unlock_wake
334 .type __lll_unlock_wake,@function
335 .hidden __lll_unlock_wake
340 cfi_adjust_cfa_offset(4)
342 cfi_adjust_cfa_offset(4)
344 cfi_adjust_cfa_offset(4)
346 cfi_offset(%ecx, -12)
347 cfi_offset(%edx, -16)
351 LOAD_FUTEX_WAKE (%ecx)
352 movl $1, %edx /* Wake one thread. */
353 movl $SYS_futex, %eax
357 cfi_adjust_cfa_offset(-4)
360 cfi_adjust_cfa_offset(-4)
363 cfi_adjust_cfa_offset(-4)
367 .size __lll_unlock_wake,.-__lll_unlock_wake
369 .globl __lll_timedwait_tid
370 .type __lll_timedwait_tid,@function
371 .hidden __lll_timedwait_tid
383 /* Get current time. */
386 movl $__NR_gettimeofday, %eax
389 /* Compute relative timeout. */
392 mul %edx /* Milli seconds to nano seconds. */
398 addl $1000000000, %edx
401 js 6f /* Time is already up. */
403 movl %ecx, (%esp) /* Store relative timeout. */
411 /* XXX The kernel so far uses global futex for the wakeup at
413 xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */
415 movl $SYS_futex, %eax
429 1: cmpl $-ETIMEDOUT, %eax
431 6: movl $ETIMEDOUT, %eax
433 .size __lll_timedwait_tid,.-__lll_timedwait_tid