Update copyright notices with scripts/update-copyrights
[glibc.git] / nptl / sysdeps / unix / sysv / linux / x86_64 / pthread_rwlock_timedrdlock.S
blob40bcc04a9d8870f06448f96547a28100fbbb52fc
1 /* Copyright (C) 2002-2014 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, see
17    <http://www.gnu.org/licenses/>.  */
19 #include <sysdep.h>
20 #include <lowlevellock.h>
21 #include <lowlevelrwlock.h>
22 #include <pthread-errnos.h>
23 #include <kernel-features.h>
25         .text
27         .globl  pthread_rwlock_timedrdlock
28         .type   pthread_rwlock_timedrdlock,@function
29         .align  16
30 pthread_rwlock_timedrdlock:
31         cfi_startproc
32         pushq   %r12
33         cfi_adjust_cfa_offset(8)
34         cfi_rel_offset(%r12, 0)
35         pushq   %r13
36         cfi_adjust_cfa_offset(8)
37         cfi_rel_offset(%r13, 0)
38 #ifdef __ASSUME_FUTEX_CLOCK_REALTIME
39 # define VALREG %edx
40 #else
41         pushq   %r14
42         cfi_adjust_cfa_offset(8)
43         cfi_rel_offset(%r14, 0)
45         subq    $16, %rsp
46         cfi_adjust_cfa_offset(16)
47 # define VALREG %r14d
48 #endif
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), VALREG
81         /* Unlock.  */
82         LOCK
83 #if MUTEX == 0
84         decl    (%r12)
85 #else
86         decl    MUTEX(%r12)
87 #endif
88         jne     10f
90 11:
91 #ifndef __ASSUME_FUTEX_CLOCK_REALTIME
92 #  ifdef PIC
93         cmpl    $0, __have_futex_clock_realtime(%rip)
94 #  else
95         cmpl    $0, __have_futex_clock_realtime
96 #  endif
97         je      .Lreltmo
98 #endif
100         cmpq    $0, (%r13)
101         js      16f             /* Time is already up.  */
103         movl    $FUTEX_PRIVATE_FLAG|FUTEX_WAIT_BITSET|FUTEX_CLOCK_REALTIME, %esi
104         xorl    PSHARED(%r12), %esi
105         movq    %r13, %r10
106         movl    $0xffffffff, %r9d
107 #ifndef __ASSUME_FUTEX_CLOCK_REALTIME
108         movl    %r14d, %edx
109 #endif
110 21:     leaq    READERS_WAKEUP(%r12), %rdi
111         movl    $SYS_futex, %eax
112         syscall
113         movq    %rax, %rdx
115 #ifndef __ASSUME_FUTEX_CLOCK_REALTIME
116         .subsection 2
117 .Lreltmo:
118         /* Get current time.  */
119         movq    %rsp, %rdi
120         xorl    %esi, %esi
121         /* This call works because we directly jump to a system call entry
122            which preserves all the registers.  */
123         call    JUMPTARGET(__gettimeofday)
125         /* Compute relative timeout.  */
126         movq    8(%rsp), %rax
127         movl    $1000, %edi
128         mul     %rdi            /* Milli seconds to nano seconds.  */
129         movq    (%r13), %rcx
130         movq    8(%r13), %rdi
131         subq    (%rsp), %rcx
132         subq    %rax, %rdi
133         jns     15f
134         addq    $1000000000, %rdi
135         decq    %rcx
136 15:     testq   %rcx, %rcx
137         js      16f             /* Time is already up.  */
139         /* Futex call.  */
140         movq    %rcx, (%rsp)    /* Store relative timeout.  */
141         movq    %rdi, 8(%rsp)
143 # ifdef __ASSUME_PRIVATE_FUTEX
144         movl    $FUTEX_PRIVATE_FLAG|FUTEX_WAIT, %esi
145         xorl    PSHARED(%r12), %esi
146 # else
147 #  if FUTEX_WAIT == 0
148         movl    PSHARED(%r12), %esi
149 #  else
150         movl    $FUTEX_WAIT, %esi
151         orl     PSHARED(%r12), %esi
152 #  endif
153         xorl    %fs:PRIVATE_FUTEX, %esi
154 # endif
155         movq    %rsp, %r10
156         movl    %r14d, %edx
158         jmp     21b
159         .previous
160 #endif
162 17:     /* Reget the lock.  */
163         movl    $1, %esi
164         xorl    %eax, %eax
165         LOCK
166 #if MUTEX == 0
167         cmpxchgl %esi, (%r12)
168 #else
169         cmpxchgl %esi, MUTEX(%r12)
170 #endif
171         jnz     12f
173 13:     decl    READERS_QUEUED(%r12)
174         cmpq    $-ETIMEDOUT, %rdx
175         jne     2b
177 18:     movl    $ETIMEDOUT, %edx
178         jmp     9f
181 5:      xorl    %edx, %edx
182         incl    NR_READERS(%r12)
183         je      8f
184 9:      LOCK
185 #if MUTEX == 0
186         decl    (%r12)
187 #else
188         decl    MUTEX(%r12)
189 #endif
190         jne     6f
192 7:      movq    %rdx, %rax
194 #ifndef __ASSUME_FUTEX_CLOCK_REALTIME
195         addq    $16, %rsp
196         cfi_adjust_cfa_offset(-16)
197         popq    %r14
198         cfi_adjust_cfa_offset(-8)
199         cfi_restore(%r14)
200 #endif
201         popq    %r13
202         cfi_adjust_cfa_offset(-8)
203         cfi_restore(%r13)
204         popq    %r12
205         cfi_adjust_cfa_offset(-8)
206         cfi_restore(%r12)
207         retq
209 #ifdef __ASSUME_PRIVATE_FUTEX
210         cfi_adjust_cfa_offset(16)
211         cfi_rel_offset(%r12, 8)
212         cfi_rel_offset(%r13, 0)
213 #else
214         cfi_adjust_cfa_offset(40)
215         cfi_offset(%r12, -16)
216         cfi_offset(%r13, -24)
217         cfi_offset(%r14, -32)
218 #endif
219 1:      movl    PSHARED(%rdi), %esi
220 #if MUTEX != 0
221         addq    $MUTEX, %rdi
222 #endif
223         callq   __lll_lock_wait
224         jmp     2b
226 14:     cmpl    %fs:TID, %eax
227         jne     3b
228         movl    $EDEADLK, %edx
229         jmp     9b
231 6:      movl    PSHARED(%r12), %esi
232 #if MUTEX == 0
233         movq    %r12, %rdi
234 #else
235         leal    MUTEX(%r12), %rdi
236 #endif
237         callq   __lll_unlock_wake
238         jmp     7b
240         /* Overflow.  */
241 8:      decl    NR_READERS(%r12)
242         movl    $EAGAIN, %edx
243         jmp     9b
245         /* Overflow.  */
246 4:      decl    READERS_QUEUED(%r12)
247         movl    $EAGAIN, %edx
248         jmp     9b
250 10:     movl    PSHARED(%r12), %esi
251 #if MUTEX == 0
252         movq    %r12, %rdi
253 #else
254         leaq    MUTEX(%r12), %rdi
255 #endif
256         callq   __lll_unlock_wake
257         jmp     11b
259 12:     movl    PSHARED(%r12), %esi
260 #if MUTEX == 0
261         movq    %r12, %rdi
262 #else
263         leaq    MUTEX(%r12), %rdi
264 #endif
265         callq   __lll_lock_wait
266         jmp     13b
268 16:     movq    $-ETIMEDOUT, %rdx
269         jmp     17b
271 19:     movl    $EINVAL, %edx
272         jmp     9b
273         cfi_endproc
274         .size   pthread_rwlock_timedrdlock,.-pthread_rwlock_timedrdlock