]>
Commit | Line | Data |
---|---|---|
0ecb606c | 1 | /* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. |
d0369fb8 UD |
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 | ||
d0369fb8 UD |
25 | #define SYS_futex 202 |
26 | #define FUTEX_WAIT 0 | |
27 | #define FUTEX_WAKE 1 | |
28 | ||
92ed3daf UD |
29 | /* For the calculation see asm/vsyscall.h. */ |
30 | #define VSYSCALL_ADDR_vgettimeofday 0xffffffffff600000 | |
31 | ||
32 | ||
d0369fb8 UD |
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: | |
92ed3daf UD |
46 | pushq %r12 |
47 | pushq %r13 | |
51d0678c | 48 | pushq %r14 |
d0369fb8 UD |
49 | subq $16, %rsp |
50 | ||
92ed3daf UD |
51 | movq %rdi, %r12 |
52 | movq %rsi, %r13 | |
d0369fb8 UD |
53 | |
54 | /* Get the lock. */ | |
55 | movl $1, %esi | |
3a226d33 | 56 | xorl %eax, %eax |
d0369fb8 UD |
57 | LOCK |
58 | #if MUTEX == 0 | |
3a226d33 | 59 | cmpxchgl %esi, (%rdi) |
d0369fb8 | 60 | #else |
3a226d33 | 61 | cmpxchgl %esi, MUTEX(%rdi) |
d0369fb8 | 62 | #endif |
3a226d33 | 63 | jnz 1f |
d0369fb8 | 64 | |
4ad0bbf4 UD |
65 | 2: movl WRITER(%r12), %eax |
66 | testl %eax, %eax | |
d0369fb8 | 67 | jne 14f |
92ed3daf | 68 | cmpl $0, WRITERS_QUEUED(%r12) |
d0369fb8 | 69 | je 5f |
92ed3daf | 70 | cmpl $0, FLAGS(%r12) |
d0369fb8 UD |
71 | je 5f |
72 | ||
73 | /* Check the value of the timeout parameter. */ | |
38205402 | 74 | 3: cmpq $1000000000, 8(%r13) |
d0369fb8 UD |
75 | jae 19f |
76 | ||
92ed3daf | 77 | incl READERS_QUEUED(%r12) |
d0369fb8 UD |
78 | je 4f |
79 | ||
51d0678c | 80 | movl READERS_WAKEUP(%r12), %r14d |
d0369fb8 UD |
81 | |
82 | /* Unlock. */ | |
83 | LOCK | |
84 | #if MUTEX == 0 | |
51d0678c | 85 | decl (%r12) |
d0369fb8 | 86 | #else |
51d0678c | 87 | decl MUTEX(%r12) |
d0369fb8 UD |
88 | #endif |
89 | jne 10f | |
90 | ||
91 | /* Get current time. */ | |
92 | 11: movq %rsp, %rdi | |
0ecb606c | 93 | xorl %esi, %esi |
92ed3daf UD |
94 | movq $VSYSCALL_ADDR_vgettimeofday, %rax |
95 | callq *%rax | |
d0369fb8 UD |
96 | |
97 | /* Compute relative timeout. */ | |
98 | movq 8(%rsp), %rax | |
0ecb606c | 99 | movl $1000, %edi |
d0369fb8 | 100 | mul %rdi /* Milli seconds to nano seconds. */ |
92ed3daf UD |
101 | movq (%r13), %rcx |
102 | movq 8(%r13), %rdi | |
d0369fb8 UD |
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 | ||
0ecb606c JJ |
115 | #if FUTEX_WAIT == 0 |
116 | xorl %esi, %esi | |
117 | #else | |
118 | movl $FUTEX_WAIT, %esi | |
119 | #endif | |
51d0678c UD |
120 | movq %rsp, %r10 |
121 | movl %r14d, %edx | |
92ed3daf | 122 | leaq READERS_WAKEUP(%r12), %rdi |
0ecb606c | 123 | movl $SYS_futex, %eax |
d0369fb8 UD |
124 | syscall |
125 | movq %rax, %rdx | |
126 | 17: | |
127 | ||
128 | /* Reget the lock. */ | |
129 | movl $1, %esi | |
3a226d33 | 130 | xorl %eax, %eax |
d0369fb8 UD |
131 | LOCK |
132 | #if MUTEX == 0 | |
3a226d33 | 133 | cmpxchgl %esi, (%r12) |
d0369fb8 | 134 | #else |
3a226d33 | 135 | cmpxchgl %esi, MUTEX(%r12) |
d0369fb8 | 136 | #endif |
3a226d33 | 137 | jnz 12f |
d0369fb8 | 138 | |
92ed3daf | 139 | 13: decl READERS_QUEUED(%r12) |
d0369fb8 UD |
140 | cmpq $-ETIMEDOUT, %rdx |
141 | jne 2b | |
142 | ||
0ecb606c | 143 | 18: movl $ETIMEDOUT, %edx |
d0369fb8 UD |
144 | jmp 9f |
145 | ||
146 | ||
0ecb606c | 147 | 5: xorl %edx, %edx |
92ed3daf | 148 | incl NR_READERS(%r12) |
d0369fb8 UD |
149 | je 8f |
150 | 9: LOCK | |
151 | #if MUTEX == 0 | |
92ed3daf | 152 | decl (%r12) |
d0369fb8 | 153 | #else |
92ed3daf | 154 | decl MUTEX(%r12) |
d0369fb8 UD |
155 | #endif |
156 | jne 6f | |
157 | ||
92ed3daf | 158 | 7: movq %rdx, %rax |
d0369fb8 UD |
159 | |
160 | addq $16, %rsp | |
51d0678c | 161 | popq %r14 |
92ed3daf UD |
162 | popq %r13 |
163 | popq %r12 | |
d0369fb8 UD |
164 | retq |
165 | ||
166 | 1: | |
167 | #if MUTEX != 0 | |
168 | addq $MUTEX, %rdi | |
169 | #endif | |
170 | callq __lll_mutex_lock_wait | |
171 | jmp 2b | |
172 | ||
4ad0bbf4 | 173 | 14: cmpl %fs:TID, %eax |
d0369fb8 | 174 | jne 3b |
0ecb606c | 175 | movl $EDEADLK, %edx |
d0369fb8 UD |
176 | jmp 9b |
177 | ||
178 | 6: | |
179 | #if MUTEX == 0 | |
92ed3daf | 180 | movq %r12, %rdi |
d0369fb8 | 181 | #else |
92ed3daf | 182 | leal MUTEX(%r12), %rdi |
d0369fb8 UD |
183 | #endif |
184 | callq __lll_mutex_unlock_wake | |
185 | jmp 7b | |
186 | ||
187 | /* Overflow. */ | |
92ed3daf | 188 | 8: decl NR_READERS(%r12) |
0ecb606c | 189 | movl $EAGAIN, %edx |
d0369fb8 UD |
190 | jmp 9b |
191 | ||
192 | /* Overflow. */ | |
92ed3daf | 193 | 4: decl READERS_QUEUED(%r12) |
0ecb606c | 194 | movl $EAGAIN, %edx |
d0369fb8 UD |
195 | jmp 9b |
196 | ||
197 | 10: | |
198 | #if MUTEX == 0 | |
92ed3daf | 199 | movq %r12, %rdi |
d0369fb8 | 200 | #else |
92ed3daf | 201 | leaq MUTEX(%r12), %rdi |
d0369fb8 UD |
202 | #endif |
203 | callq __lll_mutex_unlock_wake | |
204 | jmp 11b | |
205 | ||
206 | 12: | |
207 | #if MUTEX == 0 | |
92ed3daf | 208 | movq %r12, %rdi |
d0369fb8 | 209 | #else |
92ed3daf | 210 | leaq MUTEX(%r12), %rdi |
d0369fb8 | 211 | #endif |
92ed3daf | 212 | callq __lll_mutex_lock_wait |
d0369fb8 UD |
213 | jmp 13b |
214 | ||
215 | 16: movq $-ETIMEDOUT, %rdx | |
216 | jmp 17b | |
217 | ||
0ecb606c | 218 | 19: movl $EINVAL, %edx |
d0369fb8 UD |
219 | jmp 9b |
220 | .size pthread_rwlock_timedrdlock,.-pthread_rwlock_timedrdlock |