Updated to fedora-glibc-20041006T0900
[kopensolaris-gnu/glibc.git] / nptl / sysdeps / unix / sysv / linux / x86_64 / pthread_rwlock_timedrdlock.S
1 /* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
4
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.
9
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.
14
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.  */
19
20 #include <sysdep.h>
21 #include <lowlevelrwlock.h>
22 #include <pthread-errnos.h>
23
24
25 #define SYS_futex               202
26 #define FUTEX_WAIT              0
27 #define FUTEX_WAKE              1
28
29 /* For the calculation see asm/vsyscall.h.  */
30 #define VSYSCALL_ADDR_vgettimeofday     0xffffffffff600000
31
32
33 #ifndef UP
34 # define LOCK lock
35 #else
36 # define LOCK
37 #endif
38
39
40         .text
41
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
50
51         movq    %rdi, %r12
52         movq    %rsi, %r13
53
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
64
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
72
73         /* Check the value of the timeout parameter.  */
74 3:      cmpq    $1000000000, 8(%r13)
75         jae     19f
76
77         incl    READERS_QUEUED(%r12)
78         je      4f
79
80         movl    READERS_WAKEUP(%r12), %r14d
81
82         /* Unlock.  */
83         LOCK
84 #if MUTEX == 0
85         decl    (%r12)
86 #else
87         decl    MUTEX(%r12)
88 #endif
89         jne     10f
90
91         /* Get current time.  */
92 11:     movq    %rsp, %rdi
93         xorq    %rsi, %rsi
94         movq    $VSYSCALL_ADDR_vgettimeofday, %rax
95         callq   *%rax
96
97         /* Compute relative timeout.  */
98         movq    8(%rsp), %rax
99         movq    $1000, %rdi
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.  */
110
111         /* Futex call.  */
112         movq    %rcx, (%rsp)    /* Store relative timeout.  */
113         movq    %rdi, 8(%rsp)
114
115         xorq    %rsi, %rsi      /* movq $FUTEX_WAIT, %rsi */
116         movq    %rsp, %r10
117         movl    %r14d, %edx
118         leaq    READERS_WAKEUP(%r12), %rdi
119         movq    $SYS_futex, %rax
120         syscall
121         movq    %rax, %rdx
122 17:
123
124         /* Reget the lock.  */
125         movl    $1, %esi
126         xorl    %eax, %eax
127         LOCK
128 #if MUTEX == 0
129         cmpxchgl %esi, (%r12)
130 #else
131         cmpxchgl %esi, MUTEX(%r12)
132 #endif
133         jnz     12f
134
135 13:     decl    READERS_QUEUED(%r12)
136         cmpq    $-ETIMEDOUT, %rdx
137         jne     2b
138
139 18:     movq    $ETIMEDOUT, %rdx
140         jmp     9f
141
142
143 5:      xorq    %rdx, %rdx
144         incl    NR_READERS(%r12)
145         je      8f
146 9:      LOCK
147 #if MUTEX == 0
148         decl    (%r12)
149 #else
150         decl    MUTEX(%r12)
151 #endif
152         jne     6f
153
154 7:      movq    %rdx, %rax
155
156         addq    $16, %rsp
157         popq    %r14
158         popq    %r13
159         popq    %r12
160         retq
161
162 1:
163 #if MUTEX != 0
164         addq    $MUTEX, %rdi
165 #endif
166         callq   __lll_mutex_lock_wait
167         jmp     2b
168
169 14:     cmpl    %fs:TID, %eax
170         jne     3b
171         movq    $EDEADLK, %rdx
172         jmp     9b
173
174 6:
175 #if MUTEX == 0
176         movq    %r12, %rdi
177 #else
178         leal    MUTEX(%r12), %rdi
179 #endif
180         callq   __lll_mutex_unlock_wake
181         jmp     7b
182
183         /* Overflow.  */
184 8:      decl    NR_READERS(%r12)
185         movq    $EAGAIN, %rdx
186         jmp     9b
187
188         /* Overflow.  */
189 4:      decl    READERS_QUEUED(%r12)
190         movq    $EAGAIN, %rdx
191         jmp     9b
192
193 10:
194 #if MUTEX == 0
195         movq    %r12, %rdi
196 #else
197         leaq    MUTEX(%r12), %rdi
198 #endif
199         callq   __lll_mutex_unlock_wake
200         jmp     11b
201
202 12:
203 #if MUTEX == 0
204         movq    %r12, %rdi
205 #else
206         leaq    MUTEX(%r12), %rdi
207 #endif
208         callq   __lll_mutex_lock_wait
209         jmp     13b
210
211 16:     movq    $-ETIMEDOUT, %rdx
212         jmp     17b
213
214 19:     movq    $EINVAL, %rdx
215         jmp     9b
216         .size   pthread_rwlock_timedrdlock,.-pthread_rwlock_timedrdlock