OSDN Git Service

Merge remote branch 'origin/master' into nptl
[uclinux-h8/uClibc.git] / libpthread / nptl / sysdeps / unix / sysv / linux / x86_64 / lowlevelrobustlock.S
1 /* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2009
2    Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, write to the Free
18    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19    02111-1307 USA.  */
20
21 #include <sysdep.h>
22 #include <pthread-errnos.h>
23 #include <lowlevellock.h>
24 #include <lowlevelrobustlock.h>
25 #include <bits/kernel-features.h>
26
27         .text
28
29 #define FUTEX_WAITERS           0x80000000
30 #define FUTEX_OWNER_DIED        0x40000000
31
32 #ifdef __ASSUME_PRIVATE_FUTEX
33 # define LOAD_FUTEX_WAIT(reg) \
34         xorl    $(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg
35 # define LOAD_FUTEX_WAIT_ABS(reg) \
36         xorl    $(FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME), reg
37 #else
38 # if FUTEX_WAIT == 0
39 #  define LOAD_FUTEX_WAIT(reg) \
40         xorl    $FUTEX_PRIVATE_FLAG, reg ; \
41         andl    %fs:PRIVATE_FUTEX, reg
42 # else
43 #  define LOAD_FUTEX_WAIT(reg) \
44         xorl    $FUTEX_PRIVATE_FLAG, reg ; \
45         andl    %fs:PRIVATE_FUTEX, reg ; \
46         orl     $FUTEX_WAIT, reg
47 # endif
48 # define LOAD_FUTEX_WAIT_ABS(reg) \
49         xorl    $FUTEX_PRIVATE_FLAG, reg ; \
50         andl    %fs:PRIVATE_FUTEX, reg ; \
51         orl     $FUTEX_WAIT_BITSET | FUTEX_CLOCK_REALTIME, reg
52 #endif
53
54 /* For the calculation see asm/vsyscall.h.  */
55 #define VSYSCALL_ADDR_vgettimeofday     0xffffffffff600000
56
57
58         .globl  __lll_robust_lock_wait
59         .type   __lll_robust_lock_wait,@function
60         .hidden __lll_robust_lock_wait
61         .align  16
62 __lll_robust_lock_wait:
63         cfi_startproc
64         pushq   %r10
65         cfi_adjust_cfa_offset(8)
66         pushq   %rdx
67         cfi_adjust_cfa_offset(8)
68         cfi_offset(%r10, -16)
69         cfi_offset(%rdx, -24)
70
71         xorq    %r10, %r10      /* No timeout.  */
72         LOAD_FUTEX_WAIT (%esi)
73
74 4:      movl    %eax, %edx
75         orl     $FUTEX_WAITERS, %edx
76
77         testl   $FUTEX_OWNER_DIED, %eax
78         jnz     3f
79
80         cmpl    %edx, %eax
81         je      1f
82
83         LOCK
84         cmpxchgl %edx, (%rdi)
85         jnz     2f
86
87 1:      movl    $SYS_futex, %eax
88         syscall
89
90         movl    (%rdi), %eax
91
92 2:      testl   %eax, %eax
93         jne     4b
94
95         movl    %fs:TID, %edx
96         orl     $FUTEX_WAITERS, %edx
97         LOCK
98         cmpxchgl %edx, (%rdi)
99         jnz     4b
100         /* NB:   %rax == 0 */
101
102 3:      popq    %rdx
103         cfi_adjust_cfa_offset(-8)
104         cfi_restore(%rdx)
105         popq    %r10
106         cfi_adjust_cfa_offset(-8)
107         cfi_restore(%r10)
108         retq
109         cfi_endproc
110         .size   __lll_robust_lock_wait,.-__lll_robust_lock_wait
111
112
113         .globl  __lll_robust_timedlock_wait
114         .type   __lll_robust_timedlock_wait,@function
115         .hidden __lll_robust_timedlock_wait
116         .align  16
117 __lll_robust_timedlock_wait:
118         cfi_startproc
119 # ifndef __ASSUME_FUTEX_CLOCK_REALTIME
120 #  ifdef __PIC__
121         cmpl    $0, __have_futex_clock_realtime(%rip)
122 #  else
123         cmpl    $0, __have_futex_clock_realtime
124 #  endif
125         je      .Lreltmo
126 # endif
127
128         pushq   %r9
129         cfi_adjust_cfa_offset(8)
130         cfi_rel_offset(%r9, 0)
131         movq    %rdx, %r10
132         movl    $0xffffffff, %r9d
133         LOAD_FUTEX_WAIT_ABS (%esi)
134
135 1:      testl   $FUTEX_OWNER_DIED, %eax
136         jnz     3f
137
138         movl    %eax, %edx
139         orl     $FUTEX_WAITERS, %edx
140
141         cmpl    %eax, %edx
142         je      5f
143
144         LOCK
145         cmpxchgl %edx, (%rdi)
146         movq    $0, %rcx        /* Must use mov to avoid changing cc.  */
147         jnz     6f
148
149 5:      movl    $SYS_futex, %eax
150         syscall
151         movl    %eax, %ecx
152
153         movl    (%rdi), %eax
154
155 6:      testl   %eax, %eax
156         jne     2f
157
158         movl    %fs:TID, %edx
159         orl     $FUTEX_WAITERS, %edx
160         LOCK
161         cmpxchgl %edx, (%rdi)
162         jnz     2f
163
164 3:      popq    %r9
165         cfi_adjust_cfa_offset(-8)
166         cfi_restore(%r9)
167         retq
168
169         cfi_adjust_cfa_offset(8)
170         cfi_rel_offset(%r9, 0)
171         /* Check whether the time expired.  */
172 2:      cmpl    $-ETIMEDOUT, %ecx
173         je      4f
174         cmpl    $-EINVAL, %ecx
175         jne     1b
176
177 4:      movl    %ecx, %eax
178         negl    %eax
179         jmp     3b
180         cfi_adjust_cfa_offset(-8)
181         cfi_restore(%r9)
182
183
184 # ifndef __ASSUME_FUTEX_CLOCK_REALTIME
185 .Lreltmo:
186         /* Check for a valid timeout value.  */
187         cmpq    $1000000000, 8(%rdx)
188         jae     3f
189
190         pushq   %r8
191         cfi_adjust_cfa_offset(8)
192         pushq   %r9
193         cfi_adjust_cfa_offset(8)
194         pushq   %r12
195         cfi_adjust_cfa_offset(8)
196         pushq   %r13
197         cfi_adjust_cfa_offset(8)
198         cfi_offset(%r8, -16)
199         cfi_offset(%r9, -24)
200         cfi_offset(%r12, -32)
201         cfi_offset(%r13, -40)
202         pushq   %rsi
203         cfi_adjust_cfa_offset(8)
204
205         /* Stack frame for the timespec and timeval structs.  */
206         subq    $32, %rsp
207         cfi_adjust_cfa_offset(32)
208
209         movq    %rdi, %r12
210         movq    %rdx, %r13
211
212 1:      movq    %rax, 16(%rsp)
213
214         /* Get current time.  */
215         movq    %rsp, %rdi
216         xorl    %esi, %esi
217         movq    $VSYSCALL_ADDR_vgettimeofday, %rax
218         /* This is a regular function call, all caller-save registers
219            might be clobbered.  */
220         callq   *%rax
221
222         /* Compute relative timeout.  */
223         movq    8(%rsp), %rax
224         movl    $1000, %edi
225         mul     %rdi            /* Milli seconds to nano seconds.  */
226         movq    (%r13), %rdi
227         movq    8(%r13), %rsi
228         subq    (%rsp), %rdi
229         subq    %rax, %rsi
230         jns     4f
231         addq    $1000000000, %rsi
232         decq    %rdi
233 4:      testq   %rdi, %rdi
234         js      8f              /* Time is already up.  */
235
236         /* Futex call.  */
237         movq    %rdi, (%rsp)    /* Store relative timeout.  */
238         movq    %rsi, 8(%rsp)
239
240         movq    16(%rsp), %rdx
241         movl    %edx, %eax
242         orl     $FUTEX_WAITERS, %edx
243
244         testl   $FUTEX_OWNER_DIED, %eax
245         jnz     6f
246
247         cmpl    %eax, %edx
248         je      2f
249
250         LOCK
251         cmpxchgl %edx, (%r12)
252         movq    $0, %rcx        /* Must use mov to avoid changing cc.  */
253         jnz     5f
254
255 2:      movq    %rsp, %r10
256         movl    32(%rsp), %esi
257         LOAD_FUTEX_WAIT (%esi)
258         movq    %r12, %rdi
259         movl    $SYS_futex, %eax
260         syscall
261         movq    %rax, %rcx
262
263         movl    (%r12), %eax
264
265 5:      testl   %eax, %eax
266         jne     7f
267
268         movl    %fs:TID, %edx
269         orl     $FUTEX_WAITERS, %edx
270         LOCK
271         cmpxchgl %edx, (%r12)
272         jnz     7f
273
274 6:      addq    $40, %rsp
275         cfi_adjust_cfa_offset(-40)
276         popq    %r13
277         cfi_adjust_cfa_offset(-8)
278         cfi_restore(%r13)
279         popq    %r12
280         cfi_adjust_cfa_offset(-8)
281         cfi_restore(%r12)
282         popq    %r9
283         cfi_adjust_cfa_offset(-8)
284         cfi_restore(%r9)
285         popq    %r8
286         cfi_adjust_cfa_offset(-8)
287         cfi_restore(%r8)
288         retq
289
290 3:      movl    $EINVAL, %eax
291         retq
292
293         cfi_adjust_cfa_offset(72)
294         cfi_offset(%r8, -16)
295         cfi_offset(%r9, -24)
296         cfi_offset(%r12, -32)
297         cfi_offset(%r13, -40)
298         /* Check whether the time expired.  */
299 7:      cmpl    $-ETIMEDOUT, %ecx
300         jne     1b
301
302 8:      movl    $ETIMEDOUT, %eax
303         jmp     6b
304 #endif
305         cfi_endproc
306         .size   __lll_robust_timedlock_wait,.-__lll_robust_timedlock_wait