2.5-18.1
[glibc.git] / nptl / sysdeps / unix / sysv / linux / x86_64 / lowlevelrobustlock.S
blob69243950d735acbe4476100d292ae8684d176e57
1 /* Copyright (C) 2002, 2003, 2004, 2005, 2006 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
18    02111-1307 USA.  */
20 #include <sysdep.h>
21 #include <pthread-errnos.h>
22 #include <lowlevelrobustlock.h>
24         .text
26 #ifndef LOCK
27 # ifdef UP
28 #  define LOCK
29 # else
30 #  define LOCK lock
31 # endif
32 #endif
34 #define SYS_futex               202
35 #define FUTEX_WAIT              0
36 #define FUTEX_WAKE              1
37 #define FUTEX_WAITERS           0x80000000
38 #define FUTEX_OWNER_DIED        0x40000000
40 /* For the calculation see asm/vsyscall.h.  */
41 #define VSYSCALL_ADDR_vgettimeofday     0xffffffffff600000
44         .globl  __lll_robust_mutex_lock_wait
45         .type   __lll_robust_mutex_lock_wait,@function
46         .hidden __lll_robust_mutex_lock_wait
47         .align  16
48 __lll_robust_mutex_lock_wait:
49         cfi_startproc
50         pushq   %r10
51         cfi_adjust_cfa_offset(8)
52         pushq   %rdx
53         cfi_adjust_cfa_offset(8)
54         cfi_offset(%r10, -16)
55         cfi_offset(%rdx, -24)
57         xorq    %r10, %r10      /* No timeout.  */
58 #if FUTEX_WAIT == 0
59         xorl    %esi, %esi
60 #else
61         movl    $FUTEX_WAIT, %esi
62 #endif
64 4:      movl    %eax, %edx
65         orl     $FUTEX_WAITERS, %edx
67         testl   $FUTEX_OWNER_DIED, %eax
68         jnz     3f
70         cmpl    %edx, %eax
71         je      1f
73         LOCK
74         cmpxchgl %edx, (%rdi)
75         jnz     2f
77 1:      movl    $SYS_futex, %eax
78         syscall
80         movl    (%rdi), %eax
82 2:      testl   %eax, %eax
83         jne     4b
85         movl    %fs:TID, %edx
86         orl     $FUTEX_WAITERS, %edx
87         LOCK
88         cmpxchgl %edx, (%rdi)
89         jnz     4b
90         /* NB:   %rax == 0 */
92 3:      popq    %rdx
93         cfi_adjust_cfa_offset(-8)
94         cfi_restore(%rdx)
95         popq    %r10
96         cfi_adjust_cfa_offset(-8)
97         cfi_restore(%r10)
98         retq
99         cfi_endproc
100         .size   __lll_robust_mutex_lock_wait,.-__lll_robust_mutex_lock_wait
103         .globl  __lll_robust_mutex_timedlock_wait
104         .type   __lll_robust_mutex_timedlock_wait,@function
105         .hidden __lll_robust_mutex_timedlock_wait
106         .align  16
107 __lll_robust_mutex_timedlock_wait:
108         cfi_startproc
109         /* Check for a valid timeout value.  */
110         cmpq    $1000000000, 8(%rdx)
111         jae     3f
113         pushq   %r8
114         cfi_adjust_cfa_offset(8)
115         pushq   %r9
116         cfi_adjust_cfa_offset(8)
117         pushq   %r12
118         cfi_adjust_cfa_offset(8)
119         pushq   %r13
120         cfi_adjust_cfa_offset(8)
121         cfi_offset(%r8, -16)
122         cfi_offset(%r9, -24)
123         cfi_offset(%r12, -32)
124         cfi_offset(%r13, -40)
126         /* Stack frame for the timespec and timeval structs.  */
127         subq    $24, %rsp
128         cfi_adjust_cfa_offset(24)
130         movq    %rdi, %r12
131         movq    %rdx, %r13
133 1:      movq    %rax, 16(%rsp)
135         /* Get current time.  */
136         movq    %rsp, %rdi
137         xorl    %esi, %esi
138         movq    $VSYSCALL_ADDR_vgettimeofday, %rax
139         /* This is a regular function call, all caller-save registers
140            might be clobbered.  */
141         callq   *%rax
143         /* Compute relative timeout.  */
144         movq    8(%rsp), %rax
145         movl    $1000, %edi
146         mul     %rdi            /* Milli seconds to nano seconds.  */
147         movq    (%r13), %rdi
148         movq    8(%r13), %rsi
149         subq    (%rsp), %rdi
150         subq    %rax, %rsi
151         jns     4f
152         addq    $1000000000, %rsi
153         decq    %rdi
154 4:      testq   %rdi, %rdi
155         js      8f              /* Time is already up.  */
157         /* Futex call.  */
158         movq    %rdi, (%rsp)    /* Store relative timeout.  */
159         movq    %rsi, 8(%rsp)
161         movq    16(%rsp), %rdx
162         movl    %edx, %eax
163         orl     $FUTEX_WAITERS, %edx
165         testl   $FUTEX_OWNER_DIED, %eax
166         jnz     6f
168         cmpl    %eax, %edx
169         je      2f
171         LOCK
172         cmpxchgl %edx, (%r12)
173         movq    $0, %rcx        /* Must use mov to avoid changing cc.  */
174         jnz     5f
176 2:      movq    %rsp, %r10
177 #if FUTEX_WAIT == 0
178         xorl    %esi, %esi
179 #else
180         movl    $FUTEX_WAIT, %esi
181 #endif
182         movq    %r12, %rdi
183         movl    $SYS_futex, %eax
184         syscall
185         movq    %rax, %rcx
187         movl    (%r12), %eax
189 5:      testl   %eax, %eax
190         jne     7f
192         movl    %fs:TID, %edx
193         orl     $FUTEX_WAITERS, %edx
194         LOCK
195         cmpxchgl %edx, (%r12)
196         jnz     7f
198 6:      addq    $24, %rsp
199         cfi_adjust_cfa_offset(-24)
200         popq    %r13
201         cfi_adjust_cfa_offset(-8)
202         cfi_restore(%r13)
203         popq    %r12
204         cfi_adjust_cfa_offset(-8)
205         cfi_restore(%r12)
206         popq    %r9
207         cfi_adjust_cfa_offset(-8)
208         cfi_restore(%r9)
209         popq    %r8
210         cfi_adjust_cfa_offset(-8)
211         cfi_restore(%r8)
212         retq
214 3:      movl    $EINVAL, %eax
215         retq
217         cfi_adjust_cfa_offset(56)
218         cfi_offset(%r8, -16)
219         cfi_offset(%r9, -24)
220         cfi_offset(%r12, -32)
221         cfi_offset(%r13, -40)
222         /* Check whether the time expired.  */
223 7:      cmpq    $-ETIMEDOUT, %rcx
224         jne     1b
226 8:      movl    $ETIMEDOUT, %eax
227         jmp     6b
228         cfi_endproc
229         .size   __lll_robust_mutex_timedlock_wait,.-__lll_robust_mutex_timedlock_wait