2.5-18.1
[glibc.git] / nptl / sysdeps / unix / sysv / linux / x86_64 / pthread_rwlock_timedrdlock.S
blobb44660418a450e290bd17d3e1af270e0fda37da0
1 /* Copyright (C) 2002, 2003, 2004, 2005 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 <lowlevelrwlock.h>
22 #include <pthread-errnos.h>
25 #define SYS_futex               202
26 #define FUTEX_WAIT              0
27 #define FUTEX_WAKE              1
29 /* For the calculation see asm/vsyscall.h.  */
30 #define VSYSCALL_ADDR_vgettimeofday     0xffffffffff600000
33 #ifndef UP
34 # define LOCK lock
35 #else
36 # define LOCK
37 #endif
40         .text
42         .globl  pthread_rwlock_timedrdlock
43         .type   pthread_rwlock_timedrdlock,@function
44         .align  16
45 pthread_rwlock_timedrdlock:
46         pushq   %r12
47         pushq   %r13
48         pushq   %r14
49         subq    $16, %rsp
51         movq    %rdi, %r12
52         movq    %rsi, %r13
54         /* Get the lock.  */
55         movl    $1, %esi
56         xorl    %eax, %eax
57         LOCK
58 #if MUTEX == 0
59         cmpxchgl %esi, (%rdi)
60 #else
61         cmpxchgl %esi, MUTEX(%rdi)
62 #endif
63         jnz     1f
65 2:      movl    WRITER(%r12), %eax
66         testl   %eax, %eax
67         jne     14f
68         cmpl    $0, WRITERS_QUEUED(%r12)
69         je      5f
70         cmpl    $0, FLAGS(%r12)
71         je      5f
73         /* Check the value of the timeout parameter.  */
74 3:      cmpq    $1000000000, 8(%r13)
75         jae     19f
77         incl    READERS_QUEUED(%r12)
78         je      4f
80         movl    READERS_WAKEUP(%r12), %r14d
82         /* Unlock.  */
83         LOCK
84 #if MUTEX == 0
85         decl    (%r12)
86 #else
87         decl    MUTEX(%r12)
88 #endif
89         jne     10f
91         /* Get current time.  */
92 11:     movq    %rsp, %rdi
93         xorl    %esi, %esi
94         movq    $VSYSCALL_ADDR_vgettimeofday, %rax
95         callq   *%rax
97         /* Compute relative timeout.  */
98         movq    8(%rsp), %rax
99         movl    $1000, %edi
100         mul     %rdi            /* Milli seconds to nano seconds.  */
101         movq    (%r13), %rcx
102         movq    8(%r13), %rdi
103         subq    (%rsp), %rcx
104         subq    %rax, %rdi
105         jns     15f
106         addq    $1000000000, %rdi
107         decq    %rcx
108 15:     testq   %rcx, %rcx
109         js      16f             /* Time is already up.  */
111         /* Futex call.  */
112         movq    %rcx, (%rsp)    /* Store relative timeout.  */
113         movq    %rdi, 8(%rsp)
115 #if FUTEX_WAIT == 0
116         xorl    %esi, %esi
117 #else
118         movl    $FUTEX_WAIT, %esi
119 #endif
120         movq    %rsp, %r10
121         movl    %r14d, %edx
122         leaq    READERS_WAKEUP(%r12), %rdi
123         movl    $SYS_futex, %eax
124         syscall
125         movq    %rax, %rdx
128         /* Reget the lock.  */
129         movl    $1, %esi
130         xorl    %eax, %eax
131         LOCK
132 #if MUTEX == 0
133         cmpxchgl %esi, (%r12)
134 #else
135         cmpxchgl %esi, MUTEX(%r12)
136 #endif
137         jnz     12f
139 13:     decl    READERS_QUEUED(%r12)
140         cmpq    $-ETIMEDOUT, %rdx
141         jne     2b
143 18:     movl    $ETIMEDOUT, %edx
144         jmp     9f
147 5:      xorl    %edx, %edx
148         incl    NR_READERS(%r12)
149         je      8f
150 9:      LOCK
151 #if MUTEX == 0
152         decl    (%r12)
153 #else
154         decl    MUTEX(%r12)
155 #endif
156         jne     6f
158 7:      movq    %rdx, %rax
160         addq    $16, %rsp
161         popq    %r14
162         popq    %r13
163         popq    %r12
164         retq
167 #if MUTEX != 0
168         addq    $MUTEX, %rdi
169 #endif
170         callq   __lll_mutex_lock_wait
171         jmp     2b
173 14:     cmpl    %fs:TID, %eax
174         jne     3b
175         movl    $EDEADLK, %edx
176         jmp     9b
179 #if MUTEX == 0
180         movq    %r12, %rdi
181 #else
182         leal    MUTEX(%r12), %rdi
183 #endif
184         callq   __lll_mutex_unlock_wake
185         jmp     7b
187         /* Overflow.  */
188 8:      decl    NR_READERS(%r12)
189         movl    $EAGAIN, %edx
190         jmp     9b
192         /* Overflow.  */
193 4:      decl    READERS_QUEUED(%r12)
194         movl    $EAGAIN, %edx
195         jmp     9b
198 #if MUTEX == 0
199         movq    %r12, %rdi
200 #else
201         leaq    MUTEX(%r12), %rdi
202 #endif
203         callq   __lll_mutex_unlock_wake
204         jmp     11b
207 #if MUTEX == 0
208         movq    %r12, %rdi
209 #else
210         leaq    MUTEX(%r12), %rdi
211 #endif
212         callq   __lll_mutex_lock_wait
213         jmp     13b
215 16:     movq    $-ETIMEDOUT, %rdx
216         jmp     17b
218 19:     movl    $EINVAL, %edx
219         jmp     9b
220         .size   pthread_rwlock_timedrdlock,.-pthread_rwlock_timedrdlock