2.9
[glibc/nacl-glibc.git] / nptl / sysdeps / unix / sysv / linux / x86_64 / pthread_rwlock_timedrdlock.S
blob366c96fc36dec65844aba3a926433714e5107d3c
1 /* Copyright (C) 2002, 2003, 2004, 2005, 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
18    02111-1307 USA.  */
20 #include <sysdep.h>
21 #include <lowlevellock.h>
22 #include <lowlevelrwlock.h>
23 #include <pthread-errnos.h>
24 #include <kernel-features.h>
27 /* For the calculation see asm/vsyscall.h.  */
28 #define VSYSCALL_ADDR_vgettimeofday     0xffffffffff600000
30         .text
32         .globl  pthread_rwlock_timedrdlock
33         .type   pthread_rwlock_timedrdlock,@function
34         .align  16
35 pthread_rwlock_timedrdlock:
36         cfi_startproc
37         pushq   %r12
38         cfi_adjust_cfa_offset(8)
39         pushq   %r13
40         cfi_adjust_cfa_offset(8)
41         pushq   %r14
42         cfi_adjust_cfa_offset(8)
43         cfi_offset(%r12, -16)
44         cfi_offset(%r13, -24)
45         cfi_offset(%r14, -32)
47         subq    $16, %rsp
48         cfi_adjust_cfa_offset(16)
50         movq    %rdi, %r12
51         movq    %rsi, %r13
53         /* Get the lock.  */
54         movl    $1, %esi
55         xorl    %eax, %eax
56         LOCK
57 #if MUTEX == 0
58         cmpxchgl %esi, (%rdi)
59 #else
60         cmpxchgl %esi, MUTEX(%rdi)
61 #endif
62         jnz     1f
64 2:      movl    WRITER(%r12), %eax
65         testl   %eax, %eax
66         jne     14f
67         cmpl    $0, WRITERS_QUEUED(%r12)
68         je      5f
69         cmpl    $0, FLAGS(%r12)
70         je      5f
72         /* Check the value of the timeout parameter.  */
73 3:      cmpq    $1000000000, 8(%r13)
74         jae     19f
76         incl    READERS_QUEUED(%r12)
77         je      4f
79         movl    READERS_WAKEUP(%r12), %r14d
81         /* Unlock.  */
82         LOCK
83 #if MUTEX == 0
84         decl    (%r12)
85 #else
86         decl    MUTEX(%r12)
87 #endif
88         jne     10f
90         /* Get current time.  */
91 11:     movq    %rsp, %rdi
92         xorl    %esi, %esi
93         movq    $VSYSCALL_ADDR_vgettimeofday, %rax
94         callq   *%rax
96         /* Compute relative timeout.  */
97         movq    8(%rsp), %rax
98         movl    $1000, %edi
99         mul     %rdi            /* Milli seconds to nano seconds.  */
100         movq    (%r13), %rcx
101         movq    8(%r13), %rdi
102         subq    (%rsp), %rcx
103         subq    %rax, %rdi
104         jns     15f
105         addq    $1000000000, %rdi
106         decq    %rcx
107 15:     testq   %rcx, %rcx
108         js      16f             /* Time is already up.  */
110         /* Futex call.  */
111         movq    %rcx, (%rsp)    /* Store relative timeout.  */
112         movq    %rdi, 8(%rsp)
114 #ifdef __ASSUME_PRIVATE_FUTEX
115         movl    $FUTEX_PRIVATE_FLAG|FUTEX_WAIT, %esi
116         xorl    PSHARED(%r12), %esi
117 #else
118 # if FUTEX_WAIT == 0
119         movl    PSHARED(%r12), %esi
120 # else
121         movl    $FUTEX_WAIT, %esi
122         orl     PSHARED(%r12), %esi
123 # endif
124         xorl    %fs:PRIVATE_FUTEX, %esi
125 #endif
126         movq    %rsp, %r10
127         movl    %r14d, %edx
128         leaq    READERS_WAKEUP(%r12), %rdi
129         movl    $SYS_futex, %eax
130         syscall
131         movq    %rax, %rdx
134         /* Reget the lock.  */
135         movl    $1, %esi
136         xorl    %eax, %eax
137         LOCK
138 #if MUTEX == 0
139         cmpxchgl %esi, (%r12)
140 #else
141         cmpxchgl %esi, MUTEX(%r12)
142 #endif
143         jnz     12f
145 13:     decl    READERS_QUEUED(%r12)
146         cmpq    $-ETIMEDOUT, %rdx
147         jne     2b
149 18:     movl    $ETIMEDOUT, %edx
150         jmp     9f
153 5:      xorl    %edx, %edx
154         incl    NR_READERS(%r12)
155         je      8f
156 9:      LOCK
157 #if MUTEX == 0
158         decl    (%r12)
159 #else
160         decl    MUTEX(%r12)
161 #endif
162         jne     6f
164 7:      movq    %rdx, %rax
166         addq    $16, %rsp
167         cfi_adjust_cfa_offset(-16)
168         popq    %r14
169         cfi_adjust_cfa_offset(-8)
170         cfi_restore(%r14)
171         popq    %r13
172         cfi_adjust_cfa_offset(-8)
173         cfi_restore(%r13)
174         popq    %r12
175         cfi_adjust_cfa_offset(-8)
176         cfi_restore(%r12)
177         retq
179         cfi_adjust_cfa_offset(40)
180         cfi_offset(%r12, -16)
181         cfi_offset(%r13, -24)
182         cfi_offset(%r14, -32)
183 1:      movl    PSHARED(%rdi), %esi
184 #if MUTEX != 0
185         addq    $MUTEX, %rdi
186 #endif
187         callq   __lll_lock_wait
188         jmp     2b
190 14:     cmpl    %fs:TID, %eax
191         jne     3b
192         movl    $EDEADLK, %edx
193         jmp     9b
195 6:      movl    PSHARED(%r12), %esi
196 #if MUTEX == 0
197         movq    %r12, %rdi
198 #else
199         leal    MUTEX(%r12), %rdi
200 #endif
201         callq   __lll_unlock_wake
202         jmp     7b
204         /* Overflow.  */
205 8:      decl    NR_READERS(%r12)
206         movl    $EAGAIN, %edx
207         jmp     9b
209         /* Overflow.  */
210 4:      decl    READERS_QUEUED(%r12)
211         movl    $EAGAIN, %edx
212         jmp     9b
214 10:     movl    PSHARED(%r12), %esi
215 #if MUTEX == 0
216         movq    %r12, %rdi
217 #else
218         leaq    MUTEX(%r12), %rdi
219 #endif
220         callq   __lll_unlock_wake
221         jmp     11b
223 12:     movl    PSHARED(%r12), %esi
224 #if MUTEX == 0
225         movq    %r12, %rdi
226 #else
227         leaq    MUTEX(%r12), %rdi
228 #endif
229         callq   __lll_lock_wait
230         jmp     13b
232 16:     movq    $-ETIMEDOUT, %rdx
233         jmp     17b
235 19:     movl    $EINVAL, %edx
236         jmp     9b
237         cfi_endproc
238         .size   pthread_rwlock_timedrdlock,.-pthread_rwlock_timedrdlock