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)
106 popl %ecx; nacljmp %ecx
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)
153 popl %ecx; nacljmp %ecx
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)
194 /* Get current time. */
197 movl $__NR_gettimeofday, %eax
200 /* Compute relative timeout. */
203 mul %edx /* Milli seconds to nano seconds. */
209 addl $1000000000, %edx
212 js 2f /* Time is already up. */
214 /* Store relative timeout. */
223 LOAD_FUTEX_WAIT (%ecx)
224 movl $SYS_futex, %eax
233 cmpl $-ETIMEDOUT, %eax
235 2: movl $ETIMEDOUT, %edx
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)
252 popl %ecx; nacljmp %ecx
254 3: movl $EINVAL, %eax
255 popl %ecx; nacljmp %ecx
257 .size __lll_timedlock_wait,.-__lll_timedlock_wait
260 .globl __lll_unlock_wake_private
261 .type __lll_unlock_wake_private,@function
262 .hidden __lll_unlock_wake_private
264 __lll_unlock_wake_private:
267 cfi_adjust_cfa_offset(4)
269 cfi_adjust_cfa_offset(4)
271 cfi_adjust_cfa_offset(4)
273 cfi_offset(%ecx, -12)
274 cfi_offset(%edx, -16)
278 LOAD_PRIVATE_FUTEX_WAKE (%ecx)
279 movl $1, %edx /* Wake one thread. */
280 movl $SYS_futex, %eax
284 cfi_adjust_cfa_offset(-4)
287 cfi_adjust_cfa_offset(-4)
290 cfi_adjust_cfa_offset(-4)
292 popl %ecx; nacljmp %ecx
294 .size __lll_unlock_wake_private,.-__lll_unlock_wake_private
297 .globl __lll_unlock_wake
298 .type __lll_unlock_wake,@function
299 .hidden __lll_unlock_wake
304 cfi_adjust_cfa_offset(4)
306 cfi_adjust_cfa_offset(4)
308 cfi_adjust_cfa_offset(4)
310 cfi_offset(%ecx, -12)
311 cfi_offset(%edx, -16)
315 LOAD_FUTEX_WAKE (%ecx)
316 movl $1, %edx /* Wake one thread. */
317 movl $SYS_futex, %eax
321 cfi_adjust_cfa_offset(-4)
324 cfi_adjust_cfa_offset(-4)
327 cfi_adjust_cfa_offset(-4)
329 popl %ecx; nacljmp %ecx
331 .size __lll_unlock_wake,.-__lll_unlock_wake
333 .globl __lll_timedwait_tid
334 .type __lll_timedwait_tid,@function
335 .hidden __lll_timedwait_tid
347 /* Get current time. */
350 movl $__NR_gettimeofday, %eax
353 /* Compute relative timeout. */
356 mul %edx /* Milli seconds to nano seconds. */
362 addl $1000000000, %edx
365 js 6f /* Time is already up. */
367 movl %ecx, (%esp) /* Store relative timeout. */
375 /* XXX The kernel so far uses global futex for the wakeup at
377 xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */
379 movl $SYS_futex, %eax
391 popl %ecx; nacljmp %ecx
393 1: cmpl $-ETIMEDOUT, %eax
395 6: movl $ETIMEDOUT, %eax
397 .size __lll_timedwait_tid,.-__lll_timedwait_tid