1 /* Copyright (C) 2002-2004, 2006, 2007, 2009 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 <bits/kernel-features.h>
22 #include <lowlevellock.h>
23 #include <tcb-offsets.h>
27 #ifdef __ASSUME_PRIVATE_FUTEX
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
40 # define LOAD_PRIVATE_FUTEX_WAIT(reg) \
41 movl %gs:PRIVATE_FUTEX, reg
43 # define LOAD_PRIVATE_FUTEX_WAIT(reg) \
44 movl %gs:PRIVATE_FUTEX, reg ; \
47 # define LOAD_PRIVATE_FUTEX_WAKE(reg) \
48 movl %gs:PRIVATE_FUTEX, reg ; \
51 # define LOAD_FUTEX_WAIT(reg) \
52 xorl $FUTEX_PRIVATE_FLAG, reg ; \
53 andl %gs:PRIVATE_FUTEX, reg
55 # define LOAD_FUTEX_WAIT(reg) \
56 xorl $FUTEX_PRIVATE_FLAG, reg ; \
57 andl %gs:PRIVATE_FUTEX, reg ; \
60 # define LOAD_FUTEX_WAIT_ABS(reg) \
61 xorl $FUTEX_PRIVATE_FLAG, reg ; \
62 andl %gs:PRIVATE_FUTEX, reg ; \
63 orl $FUTEX_WAIT_BITSET | FUTEX_CLOCK_REALTIME, reg
64 # define LOAD_FUTEX_WAKE(reg) \
65 xorl $FUTEX_PRIVATE_FLAG, reg ; \
66 andl %gs:PRIVATE_FUTEX, reg ; \
70 .globl __lll_lock_wait_private
71 .type __lll_lock_wait_private,@function
72 .hidden __lll_lock_wait_private
74 __lll_lock_wait_private:
77 cfi_adjust_cfa_offset(4)
79 cfi_adjust_cfa_offset(4)
81 cfi_adjust_cfa_offset(4)
88 xorl %esi, %esi /* No timeout. */
89 LOAD_PRIVATE_FUTEX_WAIT (%ecx)
91 cmpl %edx, %eax /* NB: %edx == 2 */
94 1: movl $SYS_futex, %eax
98 xchgl %eax, (%ebx) /* NB: lock is implied */
104 cfi_adjust_cfa_offset(-4)
107 cfi_adjust_cfa_offset(-4)
110 cfi_adjust_cfa_offset(-4)
114 .size __lll_lock_wait_private,.-__lll_lock_wait_private
117 .globl __lll_lock_wait
118 .type __lll_lock_wait,@function
119 .hidden __lll_lock_wait
124 cfi_adjust_cfa_offset(4)
126 cfi_adjust_cfa_offset(4)
128 cfi_adjust_cfa_offset(4)
130 cfi_offset(%ebx, -12)
131 cfi_offset(%esi, -16)
135 xorl %esi, %esi /* No timeout. */
136 LOAD_FUTEX_WAIT (%ecx)
138 cmpl %edx, %eax /* NB: %edx == 2 */
141 1: movl $SYS_futex, %eax
145 xchgl %eax, (%ebx) /* NB: lock is implied */
151 cfi_adjust_cfa_offset(-4)
154 cfi_adjust_cfa_offset(-4)
157 cfi_adjust_cfa_offset(-4)
161 .size __lll_lock_wait,.-__lll_lock_wait
168 .globl __lll_timedlock_wait
169 .type __lll_timedlock_wait,@function
170 .hidden __lll_timedlock_wait
172 __lll_timedlock_wait:
175 cfi_adjust_cfa_offset(4)
176 cfi_rel_offset(%ebp, 0)
178 cfi_adjust_cfa_offset(4)
179 cfi_rel_offset(%ebx, 0)
181 # ifndef __ASSUME_FUTEX_CLOCK_REALTIME
184 cmpl $0, __have_futex_clock_realtime@GOTOFF(%ebx)
186 cmpl $0, __have_futex_clock_realtime
194 movl $0xffffffff, %ebp
195 LOAD_FUTEX_WAIT_ABS (%ecx)
201 1: movl $SYS_futex, %eax
205 2: xchgl %edx, (%ebx) /* NB: lock is implied */
210 cmpl $-ETIMEDOUT, %eax
219 cfi_adjust_cfa_offset(-4)
222 cfi_adjust_cfa_offset(-4)
226 # ifndef __ASSUME_FUTEX_CLOCK_REALTIME
228 /* Check for a valid timeout value. */
229 cmpl $1000000000, 4(%edx)
233 cfi_adjust_cfa_offset(4)
234 cfi_rel_offset(%esi, 0)
236 cfi_adjust_cfa_offset(4)
237 cfi_rel_offset(%edi, 0)
239 /* Stack frame for the timespec and timeval structs. */
241 cfi_adjust_cfa_offset(8)
253 /* Get current time. */
256 movl $__NR_gettimeofday, %eax
259 /* Compute relative timeout. */
262 mul %edx /* Milli seconds to nano seconds. */
268 addl $1000000000, %edx
271 js 2f /* Time is already up. */
273 /* Store relative timeout. */
282 LOAD_FUTEX_WAIT (%ecx)
283 movl $SYS_futex, %eax
292 cmpl $-ETIMEDOUT, %eax
294 2: movl $ETIMEDOUT, %edx
297 cfi_adjust_cfa_offset(-8)
299 cfi_adjust_cfa_offset(-4)
302 cfi_adjust_cfa_offset(-4)
305 cfi_adjust_cfa_offset(-4)
308 cfi_adjust_cfa_offset(-4)
313 3: movl $EINVAL, %edx
317 .size __lll_timedlock_wait,.-__lll_timedlock_wait
320 .globl __lll_unlock_wake_private
321 .type __lll_unlock_wake_private,@function
322 .hidden __lll_unlock_wake_private
324 __lll_unlock_wake_private:
327 cfi_adjust_cfa_offset(4)
329 cfi_adjust_cfa_offset(4)
331 cfi_adjust_cfa_offset(4)
333 cfi_offset(%ecx, -12)
334 cfi_offset(%edx, -16)
338 LOAD_PRIVATE_FUTEX_WAKE (%ecx)
339 movl $1, %edx /* Wake one thread. */
340 movl $SYS_futex, %eax
344 cfi_adjust_cfa_offset(-4)
347 cfi_adjust_cfa_offset(-4)
350 cfi_adjust_cfa_offset(-4)
354 .size __lll_unlock_wake_private,.-__lll_unlock_wake_private
357 .globl __lll_unlock_wake
358 .type __lll_unlock_wake,@function
359 .hidden __lll_unlock_wake
364 cfi_adjust_cfa_offset(4)
366 cfi_adjust_cfa_offset(4)
368 cfi_adjust_cfa_offset(4)
370 cfi_offset(%ecx, -12)
371 cfi_offset(%edx, -16)
375 LOAD_FUTEX_WAKE (%ecx)
376 movl $1, %edx /* Wake one thread. */
377 movl $SYS_futex, %eax
381 cfi_adjust_cfa_offset(-4)
384 cfi_adjust_cfa_offset(-4)
387 cfi_adjust_cfa_offset(-4)
391 .size __lll_unlock_wake,.-__lll_unlock_wake
393 .globl __lll_timedwait_tid
394 .type __lll_timedwait_tid,@function
395 .hidden __lll_timedwait_tid
407 /* Get current time. */
410 movl $__NR_gettimeofday, %eax
413 /* Compute relative timeout. */
416 mul %edx /* Milli seconds to nano seconds. */
422 addl $1000000000, %edx
425 js 6f /* Time is already up. */
427 movl %ecx, (%esp) /* Store relative timeout. */
435 /* XXX The kernel so far uses global futex for the wakeup at
437 xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */
439 movl $SYS_futex, %eax
453 1: cmpl $-ETIMEDOUT, %eax
455 6: movl $ETIMEDOUT, %eax
457 .size __lll_timedwait_tid,.-__lll_timedwait_tid