Update copyright notices with scripts/update-copyrights
[glibc.git] / nptl / sysdeps / unix / sysv / linux / x86_64 / pthread_rwlock_timedwrlock.S
blobf57ef5238c98f9c18a3bb55ce57013f623603c33
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_timedwrlock
28         .type   pthread_rwlock_timedwrlock,@function
29         .align  16
30 pthread_rwlock_timedwrlock:
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, NR_READERS(%r12)
68         je      5f
70         /* Check the value of the timeout parameter.  */
71 3:      cmpq    $1000000000, 8(%r13)
72         jae     19f
74         incl    WRITERS_QUEUED(%r12)
75         je      4f
77         movl    WRITERS_WAKEUP(%r12), VALREG
79         LOCK
80 #if MUTEX == 0
81         decl    (%r12)
82 #else
83         decl    MUTEX(%r12)
84 #endif
85         jne     10f
87 11:
88 #ifndef __ASSUME_FUTEX_CLOCK_REALTIME
89 #  ifdef PIC
90         cmpl    $0, __have_futex_clock_realtime(%rip)
91 #  else
92         cmpl    $0, __have_futex_clock_realtime
93 #  endif
94         je      .Lreltmo
95 #endif
97         cmpq    $0, (%r13)
98         js      16f             /* Time is already up. */
100         movl    $FUTEX_PRIVATE_FLAG|FUTEX_WAIT_BITSET|FUTEX_CLOCK_REALTIME, %esi
101         xorl    PSHARED(%r12), %esi
102         movq    %r13, %r10
103         movl    $0xffffffff, %r9d
104 #ifndef __ASSUME_FUTEX_CLOCK_REALTIME
105         movl    %r14d, %edx
106 #endif
107 21:     leaq    WRITERS_WAKEUP(%r12), %rdi
108         movl    $SYS_futex, %eax
109         syscall
110         movq    %rax, %rdx
112 #ifndef __ASSUME_FUTEX_CLOCK_REALTIME
113         .subsection 2
114 .Lreltmo:
115         /* Get current time.  */
116         movq    %rsp, %rdi
117         xorl    %esi, %esi
118         /* This call works because we directly jump to a system call entry
119            which preserves all the registers.  */
120         call    JUMPTARGET(__gettimeofday)
122         /* Compute relative timeout.  */
123         movq    8(%rsp), %rax
124         movl    $1000, %edi
125         mul     %rdi            /* Milli seconds to nano seconds.  */
126         movq    (%r13), %rcx
127         movq    8(%r13), %rdi
128         subq    (%rsp), %rcx
129         subq    %rax, %rdi
130         jns     15f
131         addq    $1000000000, %rdi
132         decq    %rcx
133 15:     testq   %rcx, %rcx
134         js      16f             /* Time is already up.  */
136         /* Futex call.  */
137         movq    %rcx, (%rsp)    /* Store relative timeout.  */
138         movq    %rdi, 8(%rsp)
140 # ifdef __ASSUME_PRIVATE_FUTEX
141         movl    $FUTEX_PRIVATE_FLAG|FUTEX_WAIT, %esi
142         xorl    PSHARED(%r12), %esi
143 # else
144 #  if FUTEX_WAIT == 0
145         movl    PSHARED(%r12), %esi
146 #  else
147         movl    $FUTEX_WAIT, %esi
148         orl     PSHARED(%r12), %esi
149 #  endif
150         xorl    %fs:PRIVATE_FUTEX, %esi
151 # endif
152         movq    %rsp, %r10
153         movl    %r14d, %edx
155         jmp     21b
156         .previous
157 #endif
159 17:     /* Reget the lock.  */
160         movl    $1, %esi
161         xorl    %eax, %eax
162         LOCK
163 #if MUTEX == 0
164         cmpxchgl %esi, (%r12)
165 #else
166         cmpxchgl %esi, MUTEX(%r12)
167 #endif
168         jnz     12f
170 13:     decl    WRITERS_QUEUED(%r12)
171         cmpq    $-ETIMEDOUT, %rdx
172         jne     2b
174 18:     movl    $ETIMEDOUT, %edx
175         jmp     9f
178 5:      xorl    %edx, %edx
179         movl    %fs:TID, %eax
180         movl    %eax, WRITER(%r12)
181 9:      LOCK
182 #if MUTEX == 0
183         decl    (%r12)
184 #else
185         decl    MUTEX(%r12)
186 #endif
187         jne     6f
189 7:      movq    %rdx, %rax
191 #ifndef __ASSUME_FUTEX_CLOCK_REALTIME
192         addq    $16, %rsp
193         cfi_adjust_cfa_offset(-16)
194         popq    %r14
195         cfi_adjust_cfa_offset(-8)
196         cfi_restore(%r14)
197 #endif
198         popq    %r13
199         cfi_adjust_cfa_offset(-8)
200         cfi_restore(%r13)
201         popq    %r12
202         cfi_adjust_cfa_offset(-8)
203         cfi_restore(%r12)
204         retq
206 #ifdef __ASSUME_PRIVATE_FUTEX
207         cfi_adjust_cfa_offset(16)
208         cfi_rel_offset(%r12, 8)
209         cfi_rel_offset(%r13, 0)
210 #else
211         cfi_adjust_cfa_offset(40)
212         cfi_offset(%r12, -16)
213         cfi_offset(%r13, -24)
214         cfi_offset(%r14, -32)
215 #endif
216 1:      movl    PSHARED(%rdi), %esi
217 #if MUTEX != 0
218         addq    $MUTEX, %rdi
219 #endif
220         callq   __lll_lock_wait
221         jmp     2b
223 14:     cmpl    %fs:TID, %eax
224         jne     3b
225 20:     movl    $EDEADLK, %edx
226         jmp     9b
228 6:      movl    PSHARED(%r12), %esi
229 #if MUTEX == 0
230         movq    %r12, %rdi
231 #else
232         leal    MUTEX(%r12), %rdi
233 #endif
234         callq   __lll_unlock_wake
235         jmp     7b
237         /* Overflow.  */
238 4:      decl    WRITERS_QUEUED(%r12)
239         movl    $EAGAIN, %edx
240         jmp     9b
242 10:     movl    PSHARED(%r12), %esi
243 #if MUTEX == 0
244         movq    %r12, %rdi
245 #else
246         leaq    MUTEX(%r12), %rdi
247 #endif
248         callq   __lll_unlock_wake
249         jmp     11b
251 12:     movl    PSHARED(%r12), %esi
252 #if MUTEX == 0
253         movq    %r12, %rdi
254 #else
255         leaq    MUTEX(%r12), %rdi
256 #endif
257         callq   __lll_lock_wait
258         jmp     13b
260 16:     movq    $-ETIMEDOUT, %rdx
261         jmp     17b
263 19:     movl    $EINVAL, %edx
264         jmp     9b
265         cfi_endproc
266         .size   pthread_rwlock_timedwrlock,.-pthread_rwlock_timedwrlock