OSDN Git Service

fc6fd2d4a53a6b70cb9852a2764da96484b9cb6c
[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, see
18    <http://www.gnu.org/licenses/>.  */
19
20 #include <sysdep.h>
21 #include <pthread-errnos.h>
22 #include <lowlevellock.h>
23 #include <lowlevelrobustlock.h>
24 #include <bits/kernel-features.h>
25
26         .text
27
28 #define FUTEX_WAITERS           0x80000000
29 #define FUTEX_OWNER_DIED        0x40000000
30
31 #ifdef __ASSUME_PRIVATE_FUTEX
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 #else
37 # if FUTEX_WAIT == 0
38 #  define LOAD_FUTEX_WAIT(reg) \
39         xorl    $FUTEX_PRIVATE_FLAG, reg ; \
40         andl    %fs:PRIVATE_FUTEX, reg
41 # else
42 #  define LOAD_FUTEX_WAIT(reg) \
43         xorl    $FUTEX_PRIVATE_FLAG, reg ; \
44         andl    %fs:PRIVATE_FUTEX, reg ; \
45         orl     $FUTEX_WAIT, reg
46 # endif
47 # define LOAD_FUTEX_WAIT_ABS(reg) \
48         xorl    $FUTEX_PRIVATE_FLAG, reg ; \
49         andl    %fs:PRIVATE_FUTEX, reg ; \
50         orl     $FUTEX_WAIT_BITSET | FUTEX_CLOCK_REALTIME, reg
51 #endif
52
53 /* For the calculation see asm/vsyscall.h.  */
54 #define VSYSCALL_ADDR_vgettimeofday     0xffffffffff600000
55
56
57         .globl  __lll_robust_lock_wait
58         .type   __lll_robust_lock_wait,@function
59         .hidden __lll_robust_lock_wait
60         .align  16
61 __lll_robust_lock_wait:
62         cfi_startproc
63         pushq   %r10
64         cfi_adjust_cfa_offset(8)
65         pushq   %rdx
66         cfi_adjust_cfa_offset(8)
67         cfi_offset(%r10, -16)
68         cfi_offset(%rdx, -24)
69
70         xorq    %r10, %r10      /* No timeout.  */
71         LOAD_FUTEX_WAIT (%esi)
72
73 4:      movl    %eax, %edx
74         orl     $FUTEX_WAITERS, %edx
75
76         testl   $FUTEX_OWNER_DIED, %eax
77         jnz     3f
78
79         cmpl    %edx, %eax
80         je      1f
81
82         LOCK
83         cmpxchgl %edx, (%rdi)
84         jnz     2f
85
86 1:      movl    $SYS_futex, %eax
87         syscall
88
89         movl    (%rdi), %eax
90
91 2:      testl   %eax, %eax
92         jne     4b
93
94         movl    %fs:TID, %edx
95         orl     $FUTEX_WAITERS, %edx
96         LOCK
97         cmpxchgl %edx, (%rdi)
98         jnz     4b
99         /* NB:   %rax == 0 */
100
101 3:      popq    %rdx
102         cfi_adjust_cfa_offset(-8)
103         cfi_restore(%rdx)
104         popq    %r10
105         cfi_adjust_cfa_offset(-8)
106         cfi_restore(%r10)
107         retq
108         cfi_endproc
109         .size   __lll_robust_lock_wait,.-__lll_robust_lock_wait
110
111
112         .globl  __lll_robust_timedlock_wait
113         .type   __lll_robust_timedlock_wait,@function
114         .hidden __lll_robust_timedlock_wait
115         .align  16
116 __lll_robust_timedlock_wait:
117         cfi_startproc
118 # ifndef __ASSUME_FUTEX_CLOCK_REALTIME
119 #  ifdef __PIC__
120         cmpl    $0, __have_futex_clock_realtime@GOTOFF(%rip)
121 #  else
122         cmpl    $0, __have_futex_clock_realtime
123 #  endif
124         je      .Lreltmo
125 # endif
126
127         pushq   %r9
128         cfi_adjust_cfa_offset(8)
129         cfi_rel_offset(%r9, 0)
130         movq    %rdx, %r10
131         movl    $0xffffffff, %r9d
132         LOAD_FUTEX_WAIT_ABS (%esi)
133
134 1:      testl   $FUTEX_OWNER_DIED, %eax
135         jnz     3f
136
137         movl    %eax, %edx
138         orl     $FUTEX_WAITERS, %edx
139
140         cmpl    %eax, %edx
141         je      5f
142
143         LOCK
144         cmpxchgl %edx, (%rdi)
145         movq    $0, %rcx        /* Must use mov to avoid changing cc.  */
146         jnz     6f
147
148 5:      movl    $SYS_futex, %eax
149         syscall
150         movl    %eax, %ecx
151
152         movl    (%rdi), %eax
153
154 6:      testl   %eax, %eax
155         jne     2f
156
157         movl    %fs:TID, %edx
158         orl     $FUTEX_WAITERS, %edx
159         LOCK
160         cmpxchgl %edx, (%rdi)
161         jnz     2f
162
163 3:      popq    %r9
164         cfi_adjust_cfa_offset(-8)
165         cfi_restore(%r9)
166         retq
167
168         cfi_adjust_cfa_offset(8)
169         cfi_rel_offset(%r9, 0)
170         /* Check whether the time expired.  */
171 2:      cmpl    $-ETIMEDOUT, %ecx
172         je      4f
173         cmpl    $-EINVAL, %ecx
174         jne     1b
175
176 4:      movl    %ecx, %eax
177         negl    %eax
178         jmp     3b
179         cfi_adjust_cfa_offset(-8)
180         cfi_restore(%r9)
181
182
183 # ifndef __ASSUME_FUTEX_CLOCK_REALTIME
184 .Lreltmo:
185         /* Check for a valid timeout value.  */
186         cmpq    $1000000000, 8(%rdx)
187         jae     3f
188
189         pushq   %r8
190         cfi_adjust_cfa_offset(8)
191         pushq   %r9
192         cfi_adjust_cfa_offset(8)
193         pushq   %r12
194         cfi_adjust_cfa_offset(8)
195         pushq   %r13
196         cfi_adjust_cfa_offset(8)
197         cfi_offset(%r8, -16)
198         cfi_offset(%r9, -24)
199         cfi_offset(%r12, -32)
200         cfi_offset(%r13, -40)
201         pushq   %rsi
202         cfi_adjust_cfa_offset(8)
203
204         /* Stack frame for the timespec and timeval structs.  */
205         subq    $32, %rsp
206         cfi_adjust_cfa_offset(32)
207
208         movq    %rdi, %r12
209         movq    %rdx, %r13
210
211 1:      movq    %rax, 16(%rsp)
212
213         /* Get current time.  */
214         movq    %rsp, %rdi
215         xorl    %esi, %esi
216         movq    $VSYSCALL_ADDR_vgettimeofday, %rax
217         /* This is a regular function call, all caller-save registers
218            might be clobbered.  */
219         callq   *%rax
220
221         /* Compute relative timeout.  */
222         movq    8(%rsp), %rax
223         movl    $1000, %edi
224         mul     %rdi            /* Milli seconds to nano seconds.  */
225         movq    (%r13), %rdi
226         movq    8(%r13), %rsi
227         subq    (%rsp), %rdi
228         subq    %rax, %rsi
229         jns     4f
230         addq    $1000000000, %rsi
231         decq    %rdi
232 4:      testq   %rdi, %rdi
233         js      8f              /* Time is already up.  */
234
235         /* Futex call.  */
236         movq    %rdi, (%rsp)    /* Store relative timeout.  */
237         movq    %rsi, 8(%rsp)
238
239         movq    16(%rsp), %rdx
240         movl    %edx, %eax
241         orl     $FUTEX_WAITERS, %edx
242
243         testl   $FUTEX_OWNER_DIED, %eax
244         jnz     6f
245
246         cmpl    %eax, %edx
247         je      2f
248
249         LOCK
250         cmpxchgl %edx, (%r12)
251         movq    $0, %rcx        /* Must use mov to avoid changing cc.  */
252         jnz     5f
253
254 2:      movq    %rsp, %r10
255         movl    32(%rsp), %esi
256         LOAD_FUTEX_WAIT (%esi)
257         movq    %r12, %rdi
258         movl    $SYS_futex, %eax
259         syscall
260         movq    %rax, %rcx
261
262         movl    (%r12), %eax
263
264 5:      testl   %eax, %eax
265         jne     7f
266
267         movl    %fs:TID, %edx
268         orl     $FUTEX_WAITERS, %edx
269         LOCK
270         cmpxchgl %edx, (%r12)
271         jnz     7f
272
273 6:      addq    $40, %rsp
274         cfi_adjust_cfa_offset(-40)
275         popq    %r13
276         cfi_adjust_cfa_offset(-8)
277         cfi_restore(%r13)
278         popq    %r12
279         cfi_adjust_cfa_offset(-8)
280         cfi_restore(%r12)
281         popq    %r9
282         cfi_adjust_cfa_offset(-8)
283         cfi_restore(%r9)
284         popq    %r8
285         cfi_adjust_cfa_offset(-8)
286         cfi_restore(%r8)
287         retq
288
289 3:      movl    $EINVAL, %eax
290         retq
291
292         cfi_adjust_cfa_offset(72)
293         cfi_offset(%r8, -16)
294         cfi_offset(%r9, -24)
295         cfi_offset(%r12, -32)
296         cfi_offset(%r13, -40)
297         /* Check whether the time expired.  */
298 7:      cmpl    $-ETIMEDOUT, %ecx
299         jne     1b
300
301 8:      movl    $ETIMEDOUT, %eax
302         jmp     6b
303 #endif
304         cfi_endproc
305         .size   __lll_robust_timedlock_wait,.-__lll_robust_timedlock_wait