2.9
[glibc/nacl-glibc.git] / nptl / sysdeps / unix / sysv / linux / x86_64 / lowlevelrobustlock.S
blobfa7516ef71b0878b2df928657781f005c6b2086e
1 /* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007
2    Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
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.
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.
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.  */
21 #include <sysdep.h>
22 #include <pthread-errnos.h>
23 #include <lowlevellock.h>
24 #include <lowlevelrobustlock.h>
25 #include <kernel-features.h>
27         .text
29 #define FUTEX_WAITERS           0x80000000
30 #define FUTEX_OWNER_DIED        0x40000000
32 #ifdef __ASSUME_PRIVATE_FUTEX
33 # define LOAD_FUTEX_WAIT(reg) \
34         xorl    $(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg
35 #else
36 # if FUTEX_WAIT == 0
37 #  define LOAD_FUTEX_WAIT(reg) \
38         xorl    $FUTEX_PRIVATE_FLAG, reg ; \
39         andl    %fs:PRIVATE_FUTEX, reg
40 # else
41 #  define LOAD_FUTEX_WAIT(reg) \
42         xorl    $FUTEX_PRIVATE_FLAG, reg ; \
43         andl    %fs:PRIVATE_FUTEX, reg ; \
44         orl     $FUTEX_WAIT, reg
45 # endif
46 #endif
48 /* For the calculation see asm/vsyscall.h.  */
49 #define VSYSCALL_ADDR_vgettimeofday     0xffffffffff600000
52         .globl  __lll_robust_lock_wait
53         .type   __lll_robust_lock_wait,@function
54         .hidden __lll_robust_lock_wait
55         .align  16
56 __lll_robust_lock_wait:
57         cfi_startproc
58         pushq   %r10
59         cfi_adjust_cfa_offset(8)
60         pushq   %rdx
61         cfi_adjust_cfa_offset(8)
62         cfi_offset(%r10, -16)
63         cfi_offset(%rdx, -24)
65         xorq    %r10, %r10      /* No timeout.  */
66         LOAD_FUTEX_WAIT (%esi)
68 4:      movl    %eax, %edx
69         orl     $FUTEX_WAITERS, %edx
71         testl   $FUTEX_OWNER_DIED, %eax
72         jnz     3f
74         cmpl    %edx, %eax
75         je      1f
77         LOCK
78         cmpxchgl %edx, (%rdi)
79         jnz     2f
81 1:      movl    $SYS_futex, %eax
82         syscall
84         movl    (%rdi), %eax
86 2:      testl   %eax, %eax
87         jne     4b
89         movl    %fs:TID, %edx
90         orl     $FUTEX_WAITERS, %edx
91         LOCK
92         cmpxchgl %edx, (%rdi)
93         jnz     4b
94         /* NB:   %rax == 0 */
96 3:      popq    %rdx
97         cfi_adjust_cfa_offset(-8)
98         cfi_restore(%rdx)
99         popq    %r10
100         cfi_adjust_cfa_offset(-8)
101         cfi_restore(%r10)
102         retq
103         cfi_endproc
104         .size   __lll_robust_lock_wait,.-__lll_robust_lock_wait
107         .globl  __lll_robust_timedlock_wait
108         .type   __lll_robust_timedlock_wait,@function
109         .hidden __lll_robust_timedlock_wait
110         .align  16
111 __lll_robust_timedlock_wait:
112         cfi_startproc
113         /* Check for a valid timeout value.  */
114         cmpq    $1000000000, 8(%rdx)
115         jae     3f
117         pushq   %r8
118         cfi_adjust_cfa_offset(8)
119         pushq   %r9
120         cfi_adjust_cfa_offset(8)
121         pushq   %r12
122         cfi_adjust_cfa_offset(8)
123         pushq   %r13
124         cfi_adjust_cfa_offset(8)
125         cfi_offset(%r8, -16)
126         cfi_offset(%r9, -24)
127         cfi_offset(%r12, -32)
128         cfi_offset(%r13, -40)
129         pushq   %rsi
130         cfi_adjust_cfa_offset(8)
132         /* Stack frame for the timespec and timeval structs.  */
133         subq    $32, %rsp
134         cfi_adjust_cfa_offset(32)
136         movq    %rdi, %r12
137         movq    %rdx, %r13
139 1:      movq    %rax, 16(%rsp)
141         /* Get current time.  */
142         movq    %rsp, %rdi
143         xorl    %esi, %esi
144         movq    $VSYSCALL_ADDR_vgettimeofday, %rax
145         /* This is a regular function call, all caller-save registers
146            might be clobbered.  */
147         callq   *%rax
149         /* Compute relative timeout.  */
150         movq    8(%rsp), %rax
151         movl    $1000, %edi
152         mul     %rdi            /* Milli seconds to nano seconds.  */
153         movq    (%r13), %rdi
154         movq    8(%r13), %rsi
155         subq    (%rsp), %rdi
156         subq    %rax, %rsi
157         jns     4f
158         addq    $1000000000, %rsi
159         decq    %rdi
160 4:      testq   %rdi, %rdi
161         js      8f              /* Time is already up.  */
163         /* Futex call.  */
164         movq    %rdi, (%rsp)    /* Store relative timeout.  */
165         movq    %rsi, 8(%rsp)
167         movq    16(%rsp), %rdx
168         movl    %edx, %eax
169         orl     $FUTEX_WAITERS, %edx
171         testl   $FUTEX_OWNER_DIED, %eax
172         jnz     6f
174         cmpl    %eax, %edx
175         je      2f
177         LOCK
178         cmpxchgl %edx, (%r12)
179         movq    $0, %rcx        /* Must use mov to avoid changing cc.  */
180         jnz     5f
182 2:      movq    %rsp, %r10
183         movl    32(%rsp), %esi
184         LOAD_FUTEX_WAIT (%esi)
185         movq    %r12, %rdi
186         movl    $SYS_futex, %eax
187         syscall
188         movq    %rax, %rcx
190         movl    (%r12), %eax
192 5:      testl   %eax, %eax
193         jne     7f
195         movl    %fs:TID, %edx
196         orl     $FUTEX_WAITERS, %edx
197         LOCK
198         cmpxchgl %edx, (%r12)
199         jnz     7f
201 6:      addq    $40, %rsp
202         cfi_adjust_cfa_offset(-40)
203         popq    %r13
204         cfi_adjust_cfa_offset(-8)
205         cfi_restore(%r13)
206         popq    %r12
207         cfi_adjust_cfa_offset(-8)
208         cfi_restore(%r12)
209         popq    %r9
210         cfi_adjust_cfa_offset(-8)
211         cfi_restore(%r9)
212         popq    %r8
213         cfi_adjust_cfa_offset(-8)
214         cfi_restore(%r8)
215         retq
217 3:      movl    $EINVAL, %eax
218         retq
220         cfi_adjust_cfa_offset(72)
221         cfi_offset(%r8, -16)
222         cfi_offset(%r9, -24)
223         cfi_offset(%r12, -32)
224         cfi_offset(%r13, -40)
225         /* Check whether the time expired.  */
226 7:      cmpq    $-ETIMEDOUT, %rcx
227         jne     1b
229 8:      movl    $ETIMEDOUT, %eax
230         jmp     6b
231         cfi_endproc
232         .size   __lll_robust_timedlock_wait,.-__lll_robust_timedlock_wait