OSDN Git Service

4e8e967838f8c1da88180e89cf00554248f2ea8f
[uclinux-h8/uClibc.git] / libpthread / nptl / sysdeps / unix / sysv / linux / x86_64 / pthread_rwlock_timedrdlock.S
1 /* Copyright (C) 2002-2005, 2007, 2009 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, see
17    <http://www.gnu.org/licenses/>.  */
18
19 #include <sysdep.h>
20 #include <lowlevellock.h>
21 #include <lowlevelrwlock.h>
22 #include <pthread-errnos.h>
23 #include <bits/kernel-features.h>
24 #include <tcb-offsets.h>
25
26
27 /* For the calculation see asm/vsyscall.h.  */
28 #define VSYSCALL_ADDR_vgettimeofday     0xffffffffff600000
29
30         .text
31
32         .globl  pthread_rwlock_timedrdlock
33         .type   pthread_rwlock_timedrdlock,@function
34         .align  16
35 pthread_rwlock_timedrdlock:
36         cfi_startproc
37         pushq   %r12
38         cfi_adjust_cfa_offset(8)
39         cfi_rel_offset(%r12, 0)
40         pushq   %r13
41         cfi_adjust_cfa_offset(8)
42         cfi_rel_offset(%r13, 0)
43 #ifdef __ASSUME_FUTEX_CLOCK_REALTIME
44 # define VALREG %edx
45 #else
46         pushq   %r14
47         cfi_adjust_cfa_offset(8)
48         cfi_rel_offset(%r14, 0)
49
50         subq    $16, %rsp
51         cfi_adjust_cfa_offset(16)
52 # define VALREG %r14d
53 #endif
54
55         movq    %rdi, %r12
56         movq    %rsi, %r13
57
58         /* Get the lock.  */
59         movl    $1, %esi
60         xorl    %eax, %eax
61         LOCK
62 #if MUTEX == 0
63         cmpxchgl %esi, (%rdi)
64 #else
65         cmpxchgl %esi, MUTEX(%rdi)
66 #endif
67         jnz     1f
68
69 2:      movl    WRITER(%r12), %eax
70         testl   %eax, %eax
71         jne     14f
72         cmpl    $0, WRITERS_QUEUED(%r12)
73         je      5f
74         cmpl    $0, FLAGS(%r12)
75         je      5f
76
77         /* Check the value of the timeout parameter.  */
78 3:      cmpq    $1000000000, 8(%r13)
79         jae     19f
80
81         incl    READERS_QUEUED(%r12)
82         je      4f
83
84         movl    READERS_WAKEUP(%r12), VALREG
85
86         /* Unlock.  */
87         LOCK
88 #if MUTEX == 0
89         decl    (%r12)
90 #else
91         decl    MUTEX(%r12)
92 #endif
93         jne     10f
94
95 11:
96 #ifndef __ASSUME_FUTEX_CLOCK_REALTIME
97 #  ifdef __PIC__
98         cmpl    $0, __have_futex_clock_realtime@GOTOFF(%rip)
99 #  else
100         cmpl    $0, __have_futex_clock_realtime
101 #  endif
102         je      .Lreltmo
103 #endif
104
105         movl    $FUTEX_PRIVATE_FLAG|FUTEX_WAIT_BITSET|FUTEX_CLOCK_REALTIME, %esi
106         xorl    PSHARED(%r12), %esi
107         movq    %r13, %r10
108         movl    $0xffffffff, %r9d
109 #ifndef __ASSUME_FUTEX_CLOCK_REALTIME
110         movl    %r14d, %edx
111 #endif
112 21:     leaq    READERS_WAKEUP(%r12), %rdi
113         movl    $SYS_futex, %eax
114         syscall
115         movq    %rax, %rdx
116
117 #ifndef __ASSUME_FUTEX_CLOCK_REALTIME
118         .subsection 2
119 .Lreltmo:
120         /* Get current time.  */
121         movq    %rsp, %rdi
122         xorl    %esi, %esi
123         movq    $VSYSCALL_ADDR_vgettimeofday, %rax
124         callq   *%rax
125
126         /* Compute relative timeout.  */
127         movq    8(%rsp), %rax
128         movl    $1000, %edi
129         mul     %rdi            /* Milli seconds to nano seconds.  */
130         movq    (%r13), %rcx
131         movq    8(%r13), %rdi
132         subq    (%rsp), %rcx
133         subq    %rax, %rdi
134         jns     15f
135         addq    $1000000000, %rdi
136         decq    %rcx
137 15:     testq   %rcx, %rcx
138         js      16f             /* Time is already up.  */
139
140         /* Futex call.  */
141         movq    %rcx, (%rsp)    /* Store relative timeout.  */
142         movq    %rdi, 8(%rsp)
143
144 # ifdef __ASSUME_PRIVATE_FUTEX
145         movl    $FUTEX_PRIVATE_FLAG|FUTEX_WAIT, %esi
146         xorl    PSHARED(%r12), %esi
147 # else
148 #  if FUTEX_WAIT == 0
149         movl    PSHARED(%r12), %esi
150 #  else
151         movl    $FUTEX_WAIT, %esi
152         orl     PSHARED(%r12), %esi
153 #  endif
154         xorl    %fs:PRIVATE_FUTEX, %esi
155 # endif
156         movq    %rsp, %r10
157         movl    %r14d, %edx
158
159         jmp     21b
160         .previous
161 #endif
162
163 17:     /* Reget the lock.  */
164         movl    $1, %esi
165         xorl    %eax, %eax
166         LOCK
167 #if MUTEX == 0
168         cmpxchgl %esi, (%r12)
169 #else
170         cmpxchgl %esi, MUTEX(%r12)
171 #endif
172         jnz     12f
173
174 13:     decl    READERS_QUEUED(%r12)
175         cmpq    $-ETIMEDOUT, %rdx
176         jne     2b
177
178 18:     movl    $ETIMEDOUT, %edx
179         jmp     9f
180
181
182 5:      xorl    %edx, %edx
183         incl    NR_READERS(%r12)
184         je      8f
185 9:      LOCK
186 #if MUTEX == 0
187         decl    (%r12)
188 #else
189         decl    MUTEX(%r12)
190 #endif
191         jne     6f
192
193 7:      movq    %rdx, %rax
194
195 #ifndef __ASSUME_FUTEX_CLOCK_REALTIME
196         addq    $16, %rsp
197         cfi_adjust_cfa_offset(-16)
198         popq    %r14
199         cfi_adjust_cfa_offset(-8)
200         cfi_restore(%r14)
201 #endif
202         popq    %r13
203         cfi_adjust_cfa_offset(-8)
204         cfi_restore(%r13)
205         popq    %r12
206         cfi_adjust_cfa_offset(-8)
207         cfi_restore(%r12)
208         retq
209
210 #ifdef __ASSUME_PRIVATE_FUTEX
211         cfi_adjust_cfa_offset(16)
212         cfi_rel_offset(%r12, 8)
213         cfi_rel_offset(%r13, 0)
214 #else
215         cfi_adjust_cfa_offset(40)
216         cfi_offset(%r12, -16)
217         cfi_offset(%r13, -24)
218         cfi_offset(%r14, -32)
219 #endif
220 1:      movl    PSHARED(%rdi), %esi
221 #if MUTEX != 0
222         addq    $MUTEX, %rdi
223 #endif
224         callq   __lll_lock_wait
225         jmp     2b
226
227 14:     cmpl    %fs:TID, %eax
228         jne     3b
229         movl    $EDEADLK, %edx
230         jmp     9b
231
232 6:      movl    PSHARED(%r12), %esi
233 #if MUTEX == 0
234         movq    %r12, %rdi
235 #else
236         leal    MUTEX(%r12), %rdi
237 #endif
238         callq   __lll_unlock_wake
239         jmp     7b
240
241         /* Overflow.  */
242 8:      decl    NR_READERS(%r12)
243         movl    $EAGAIN, %edx
244         jmp     9b
245
246         /* Overflow.  */
247 4:      decl    READERS_QUEUED(%r12)
248         movl    $EAGAIN, %edx
249         jmp     9b
250
251 10:     movl    PSHARED(%r12), %esi
252 #if MUTEX == 0
253         movq    %r12, %rdi
254 #else
255         leaq    MUTEX(%r12), %rdi
256 #endif
257         callq   __lll_unlock_wake
258         jmp     11b
259
260 12:     movl    PSHARED(%r12), %esi
261 #if MUTEX == 0
262         movq    %r12, %rdi
263 #else
264         leaq    MUTEX(%r12), %rdi
265 #endif
266         callq   __lll_lock_wait
267         jmp     13b
268
269 16:     movq    $-ETIMEDOUT, %rdx
270         jmp     17b
271
272 19:     movl    $EINVAL, %edx
273         jmp     9b
274         cfi_endproc
275         .size   pthread_rwlock_timedrdlock,.-pthread_rwlock_timedrdlock