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