Updated to fedora-glibc-20041006T0900
[kopensolaris-gnu/glibc.git] / nptl / sysdeps / unix / sysv / linux / x86_64 / pthread_rwlock_timedwrlock.S
1 /* Copyright (C) 2002, 2003 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 #ifndef UP
33 # define LOCK lock
34 #else
35 # define LOCK
36 #endif
37
38
39         .text
40
41         .globl  pthread_rwlock_timedwrlock
42         .type   pthread_rwlock_timedwrlock,@function
43         .align  16
44 pthread_rwlock_timedwrlock:
45         pushq   %r12
46         pushq   %r13
47         pushq   %r14
48         subq    $16, %rsp
49
50         movq    %rdi, %r12
51         movq    %rsi, %r13
52
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
63
64 2:      movl    WRITER(%r12), %eax
65         testl   %eax, %eax
66         jne     14f
67         cmpl    $0, NR_READERS(%r12)
68         je      5f
69
70         /* Check the value of the timeout parameter.  */
71 3:      cmpq    $1000000000, 8(%r13)
72         jae     19f
73
74         incl    WRITERS_QUEUED(%r12)
75         je      4f
76
77         movl    WRITERS_WAKEUP(%r12), %r14d
78
79         LOCK
80 #if MUTEX == 0
81         decl    (%r12)
82 #else
83         decl    MUTEX(%r12)
84 #endif
85         jne     10f
86
87         /* Get current time.  */
88 11:     movq    %rsp, %rdi
89         xorq    %rsi, %rsi
90         movq    $VSYSCALL_ADDR_vgettimeofday, %rax
91         callq   *%rax
92
93         /* Compute relative timeout.  */
94         movq    8(%rsp), %rax
95         movq    $1000, %rdi
96         mul     %rdi            /* Milli seconds to nano seconds.  */
97         movq    (%r13), %rcx
98         movq    8(%r13), %rdi
99         subq    (%rsp), %rcx
100         subq    %rax, %rdi
101         jns     15f
102         addq    $1000000000, %rdi
103         decq    %rcx
104 15:     testq   %rcx, %rcx
105         js      16f             /* Time is already up.  */
106
107         /* Futex call.  */
108         movq    %rcx, (%rsp)    /* Store relative timeout.  */
109         movq    %rdi, 8(%rsp)
110
111         xorq    %rsi, %rsi      /* movq $FUTEX_WAIT, %rsi */
112         movq    %rsp, %r10
113         movl    %r14d, %edx
114         leaq    WRITERS_WAKEUP(%r12), %rdi
115         movq    $SYS_futex, %rax
116         syscall
117         movq    %rax, %rdx
118 17:
119
120         /* Reget the lock.  */
121         movl    $1, %esi
122         xorl    %eax, %eax
123         LOCK
124 #if MUTEX == 0
125         cmpxchgl %esi, (%r12)
126 #else
127         cmpxchgl %esi, MUTEX(%r12)
128 #endif
129         jnz     12f
130
131 13:     decl    WRITERS_QUEUED(%r12)
132         cmpq    $-ETIMEDOUT, %rdx
133         jne     2b
134
135 18:     movq    $ETIMEDOUT, %rdx
136         jmp     9f
137
138
139 5:      xorq    %rdx, %rdx
140         movl    %fs:TID, %eax
141         movl    %eax, WRITER(%r12)
142 9:      LOCK
143 #if MUTEX == 0
144         decl    (%r12)
145 #else
146         decl    MUTEX(%r12)
147 #endif
148         jne     6f
149
150 7:      movq    %rdx, %rax
151
152         addq    $16, %rsp
153         popq    %r14
154         popq    %r13
155         popq    %r12
156         retq
157
158 1:
159 #if MUTEX != 0
160         addq    $MUTEX, %rdi
161 #endif
162         callq   __lll_mutex_lock_wait
163         jmp     2b
164
165 14:     cmpl    %fs:TID, %eax
166         jne     3b
167 20:     movq    $EDEADLK, %rdx
168         jmp     9b
169
170 6:
171 #if MUTEX == 0
172         movq    %r12, %rdi
173 #else
174         leal    MUTEX(%r12), %rdi
175 #endif
176         callq   __lll_mutex_unlock_wake
177         jmp     7b
178
179         /* Overflow.  */
180 4:      decl    WRITERS_QUEUED(%r12)
181         movq    $EAGAIN, %rdx
182         jmp     9b
183
184 10:
185 #if MUTEX == 0
186         movq    %r12, %rdi
187 #else
188         leaq    MUTEX(%r12), %rdi
189 #endif
190         callq   __lll_mutex_unlock_wake
191         jmp     11b
192
193 12:
194 #if MUTEX == 0
195         movq    %r12, %rdi
196 #else
197         leaq    MUTEX(%r12), %rdi
198 #endif
199         callq   __lll_mutex_lock_wait
200         jmp     13b
201
202 16:     movq    $-ETIMEDOUT, %rdx
203         jmp     17b
204
205 19:     movq    $EINVAL, %rdx
206         jmp     9b
207         .size   pthread_rwlock_timedwrlock,.-pthread_rwlock_timedwrlock