1 /* Copyright (C) 2002, 2003, 2004, 2006, 2007 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, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21 #include <pthread-errnos.h>
22 #include <kernel-features.h>
23 #include <lowlevellock.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_WAKE(reg) \
35 xorl $(FUTEX_WAKE | FUTEX_PRIVATE_FLAG), reg
38 # define LOAD_PRIVATE_FUTEX_WAIT(reg) \
39 movl %gs:PRIVATE_FUTEX, reg
41 # define LOAD_PRIVATE_FUTEX_WAIT(reg) \
42 movl %gs:PRIVATE_FUTEX, reg ; \
45 # define LOAD_PRIVATE_FUTEX_WAKE(reg) \
46 movl %gs:PRIVATE_FUTEX, reg ; \
49 # define LOAD_FUTEX_WAIT(reg) \
50 xorl $FUTEX_PRIVATE_FLAG, reg ; \
51 andl %gs:PRIVATE_FUTEX, reg
53 # define LOAD_FUTEX_WAIT(reg) \
54 xorl $FUTEX_PRIVATE_FLAG, reg ; \
55 andl %gs:PRIVATE_FUTEX, reg ; \
58 # define LOAD_FUTEX_WAKE(reg) \
59 xorl $FUTEX_PRIVATE_FLAG, reg ; \
60 andl %gs:PRIVATE_FUTEX, reg ; \
64 .globl __lll_lock_wait_private
65 .type __lll_lock_wait_private,@function
66 .hidden __lll_lock_wait_private
68 __lll_lock_wait_private:
71 cfi_adjust_cfa_offset(4)
73 cfi_adjust_cfa_offset(4)
75 cfi_adjust_cfa_offset(4)
82 xorl %esi, %esi /* No timeout. */
83 LOAD_PRIVATE_FUTEX_WAIT (%ecx)
85 cmpl %edx, %eax /* NB: %edx == 2 */
88 1: movl $SYS_futex, %eax
92 xchgl %eax, (%ebx) /* NB: lock is implied */
98 cfi_adjust_cfa_offset(-4)
101 cfi_adjust_cfa_offset(-4)
104 cfi_adjust_cfa_offset(-4)
108 .size __lll_lock_wait_private,.-__lll_lock_wait_private
111 .globl __lll_lock_wait
112 .type __lll_lock_wait,@function
113 .hidden __lll_lock_wait
118 cfi_adjust_cfa_offset(4)
120 cfi_adjust_cfa_offset(4)
122 cfi_adjust_cfa_offset(4)
124 cfi_offset(%ebx, -12)
125 cfi_offset(%esi, -16)
129 xorl %esi, %esi /* No timeout. */
130 LOAD_FUTEX_WAIT (%ecx)
132 cmpl %edx, %eax /* NB: %edx == 2 */
135 1: movl $SYS_futex, %eax
139 xchgl %eax, (%ebx) /* NB: lock is implied */
145 cfi_adjust_cfa_offset(-4)
148 cfi_adjust_cfa_offset(-4)
151 cfi_adjust_cfa_offset(-4)
155 .size __lll_lock_wait,.-__lll_lock_wait
157 .globl __lll_timedlock_wait
158 .type __lll_timedlock_wait,@function
159 .hidden __lll_timedlock_wait
161 __lll_timedlock_wait:
163 /* Check for a valid timeout value. */
164 cmpl $1000000000, 4(%edx)
168 cfi_adjust_cfa_offset(4)
170 cfi_adjust_cfa_offset(4)
172 cfi_adjust_cfa_offset(4)
174 cfi_adjust_cfa_offset(4)
176 cfi_offset(%esi, -12)
177 cfi_offset(%ebx, -16)
178 cfi_offset(%ebp, -20)
180 /* Stack frame for the timespec and timeval structs. */
182 cfi_adjust_cfa_offset(8)
188 /* Get current time. */
191 movl $__NR_gettimeofday, %eax
194 /* Compute relative timeout. */
197 mul %edx /* Milli seconds to nano seconds. */
203 addl $1000000000, %edx
206 js 5f /* Time is already up. */
208 /* Store relative timeout. */
217 cmpxchgl %edx, (%ebx)
225 LOAD_FUTEX_WAIT (%ecx)
226 movl $SYS_futex, %eax
230 8: /* NB: %edx == 2 */
233 cmpxchgl %edx, (%ebx)
238 cfi_adjust_cfa_offset(-8)
240 cfi_adjust_cfa_offset(-4)
243 cfi_adjust_cfa_offset(-4)
246 cfi_adjust_cfa_offset(-4)
249 cfi_adjust_cfa_offset(-4)
253 3: movl $EINVAL, %eax
256 cfi_adjust_cfa_offset(24)
258 cfi_offset(%esi, -12)
259 cfi_offset(%ebx, -16)
260 cfi_offset(%ebp, -20)
261 /* Check whether the time expired. */
262 7: cmpl $-ETIMEDOUT, %ecx
265 /* Make sure the current holder knows we are going to sleep. */
272 5: movl $ETIMEDOUT, %eax
275 .size __lll_timedlock_wait,.-__lll_timedlock_wait
278 .globl __lll_unlock_wake_private
279 .type __lll_unlock_wake_private,@function
280 .hidden __lll_unlock_wake_private
282 __lll_unlock_wake_private:
285 cfi_adjust_cfa_offset(4)
287 cfi_adjust_cfa_offset(4)
289 cfi_adjust_cfa_offset(4)
291 cfi_offset(%ecx, -12)
292 cfi_offset(%edx, -16)
296 LOAD_PRIVATE_FUTEX_WAKE (%ecx)
297 movl $1, %edx /* Wake one thread. */
298 movl $SYS_futex, %eax
302 cfi_adjust_cfa_offset(-4)
305 cfi_adjust_cfa_offset(-4)
308 cfi_adjust_cfa_offset(-4)
312 .size __lll_unlock_wake_private,.-__lll_unlock_wake_private
315 .globl __lll_unlock_wake
316 .type __lll_unlock_wake,@function
317 .hidden __lll_unlock_wake
322 cfi_adjust_cfa_offset(4)
324 cfi_adjust_cfa_offset(4)
326 cfi_adjust_cfa_offset(4)
328 cfi_offset(%ecx, -12)
329 cfi_offset(%edx, -16)
333 LOAD_FUTEX_WAKE (%ecx)
334 movl $1, %edx /* Wake one thread. */
335 movl $SYS_futex, %eax
339 cfi_adjust_cfa_offset(-4)
342 cfi_adjust_cfa_offset(-4)
345 cfi_adjust_cfa_offset(-4)
349 .size __lll_unlock_wake,.-__lll_unlock_wake
351 .globl __lll_timedwait_tid
352 .type __lll_timedwait_tid,@function
353 .hidden __lll_timedwait_tid
365 /* Get current time. */
368 movl $__NR_gettimeofday, %eax
371 /* Compute relative timeout. */
374 mul %edx /* Milli seconds to nano seconds. */
380 addl $1000000000, %edx
383 js 6f /* Time is already up. */
385 movl %ecx, (%esp) /* Store relative timeout. */
393 /* XXX The kernel so far uses global futex for the wakeup at
395 xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */
397 movl $SYS_futex, %eax
411 1: cmpl $-ETIMEDOUT, %eax
413 6: movl $ETIMEDOUT, %eax
415 .size __lll_timedwait_tid,.-__lll_timedwait_tid