]> git.ipfire.org Git - thirdparty/glibc.git/blob - nptl/sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S
Update copyright notices with scripts/update-copyrights
[thirdparty/glibc.git] / nptl / sysdeps / unix / sysv / linux / x86_64 / lowlevelrobustlock.S
1 /* Copyright (C) 2002-2014 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 <pthread-errnos.h>
21 #include <lowlevellock.h>
22 #include <lowlevelrobustlock.h>
23 #include <kernel-features.h>
24
25 .text
26
27 #define FUTEX_WAITERS 0x80000000
28 #define FUTEX_OWNER_DIED 0x40000000
29
30 #ifdef __ASSUME_PRIVATE_FUTEX
31 # define LOAD_FUTEX_WAIT(reg) \
32 xorl $(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg
33 # define LOAD_FUTEX_WAIT_ABS(reg) \
34 xorl $(FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME), reg
35 #else
36 # if FUTEX_WAIT == 0
37 # define LOAD_FUTEX_WAIT(reg) \
38 xorl $FUTEX_PRIVATE_FLAG, reg ; \
39 andl %fs:PRIVATE_FUTEX, reg
40 # else
41 # define LOAD_FUTEX_WAIT(reg) \
42 xorl $FUTEX_PRIVATE_FLAG, reg ; \
43 andl %fs:PRIVATE_FUTEX, reg ; \
44 orl $FUTEX_WAIT, reg
45 # endif
46 # define LOAD_FUTEX_WAIT_ABS(reg) \
47 xorl $FUTEX_PRIVATE_FLAG, reg ; \
48 andl %fs:PRIVATE_FUTEX, reg ; \
49 orl $FUTEX_WAIT_BITSET | FUTEX_CLOCK_REALTIME, reg
50 #endif
51
52
53 .globl __lll_robust_lock_wait
54 .type __lll_robust_lock_wait,@function
55 .hidden __lll_robust_lock_wait
56 .align 16
57 __lll_robust_lock_wait:
58 cfi_startproc
59 pushq %r10
60 cfi_adjust_cfa_offset(8)
61 pushq %rdx
62 cfi_adjust_cfa_offset(8)
63 cfi_offset(%r10, -16)
64 cfi_offset(%rdx, -24)
65
66 xorq %r10, %r10 /* No timeout. */
67 LOAD_FUTEX_WAIT (%esi)
68
69 4: movl %eax, %edx
70 orl $FUTEX_WAITERS, %edx
71
72 testl $FUTEX_OWNER_DIED, %eax
73 jnz 3f
74
75 cmpl %edx, %eax
76 je 1f
77
78 LOCK
79 cmpxchgl %edx, (%rdi)
80 jnz 2f
81
82 1: movl $SYS_futex, %eax
83 syscall
84
85 movl (%rdi), %eax
86
87 2: testl %eax, %eax
88 jne 4b
89
90 movl %fs:TID, %edx
91 orl $FUTEX_WAITERS, %edx
92 LOCK
93 cmpxchgl %edx, (%rdi)
94 jnz 4b
95 /* NB: %rax == 0 */
96
97 3: popq %rdx
98 cfi_adjust_cfa_offset(-8)
99 cfi_restore(%rdx)
100 popq %r10
101 cfi_adjust_cfa_offset(-8)
102 cfi_restore(%r10)
103 retq
104 cfi_endproc
105 .size __lll_robust_lock_wait,.-__lll_robust_lock_wait
106
107
108 .globl __lll_robust_timedlock_wait
109 .type __lll_robust_timedlock_wait,@function
110 .hidden __lll_robust_timedlock_wait
111 .align 16
112 __lll_robust_timedlock_wait:
113 cfi_startproc
114 # ifndef __ASSUME_FUTEX_CLOCK_REALTIME
115 # ifdef PIC
116 cmpl $0, __have_futex_clock_realtime(%rip)
117 # else
118 cmpl $0, __have_futex_clock_realtime
119 # endif
120 je .Lreltmo
121 # endif
122
123 cmpq $0, (%rdx)
124 js 7f
125
126 pushq %r9
127 cfi_adjust_cfa_offset(8)
128 cfi_rel_offset(%r9, 0)
129 movq %rdx, %r10
130 movl $0xffffffff, %r9d
131 LOAD_FUTEX_WAIT_ABS (%esi)
132
133 1: testl $FUTEX_OWNER_DIED, %eax
134 jnz 3f
135
136 movl %eax, %edx
137 orl $FUTEX_WAITERS, %edx
138
139 cmpl %eax, %edx
140 je 5f
141
142 LOCK
143 cmpxchgl %edx, (%rdi)
144 movq $0, %rcx /* Must use mov to avoid changing cc. */
145 jnz 6f
146
147 5: movl $SYS_futex, %eax
148 syscall
149 movl %eax, %ecx
150
151 movl (%rdi), %eax
152
153 6: testl %eax, %eax
154 jne 2f
155
156 movl %fs:TID, %edx
157 orl $FUTEX_WAITERS, %edx
158 LOCK
159 cmpxchgl %edx, (%rdi)
160 jnz 2f
161
162 3: popq %r9
163 cfi_adjust_cfa_offset(-8)
164 cfi_restore(%r9)
165 retq
166
167 cfi_adjust_cfa_offset(8)
168 cfi_rel_offset(%r9, 0)
169 /* Check whether the time expired. */
170 2: cmpl $-ETIMEDOUT, %ecx
171 je 4f
172 cmpl $-EINVAL, %ecx
173 jne 1b
174
175 4: movl %ecx, %eax
176 negl %eax
177 jmp 3b
178 cfi_adjust_cfa_offset(-8)
179 cfi_restore(%r9)
180
181 7: movl $ETIMEDOUT, %eax
182 retq
183
184
185 # ifndef __ASSUME_FUTEX_CLOCK_REALTIME
186 .Lreltmo:
187 /* Check for a valid timeout value. */
188 cmpq $1000000000, 8(%rdx)
189 jae 3f
190
191 pushq %r8
192 cfi_adjust_cfa_offset(8)
193 pushq %r9
194 cfi_adjust_cfa_offset(8)
195 pushq %r12
196 cfi_adjust_cfa_offset(8)
197 pushq %r13
198 cfi_adjust_cfa_offset(8)
199 cfi_offset(%r8, -16)
200 cfi_offset(%r9, -24)
201 cfi_offset(%r12, -32)
202 cfi_offset(%r13, -40)
203 pushq %rsi
204 cfi_adjust_cfa_offset(8)
205
206 /* Stack frame for the timespec and timeval structs. */
207 subq $32, %rsp
208 cfi_adjust_cfa_offset(32)
209
210 movq %rdi, %r12
211 movq %rdx, %r13
212
213 1: movq %rax, 16(%rsp)
214
215 /* Get current time. */
216 movq %rsp, %rdi
217 xorl %esi, %esi
218 /* This call works because we directly jump to a system call entry
219 which preserves all the registers. */
220 call JUMPTARGET(__gettimeofday)
221
222 /* Compute relative timeout. */
223 movq 8(%rsp), %rax
224 movl $1000, %edi
225 mul %rdi /* Milli seconds to nano seconds. */
226 movq (%r13), %rdi
227 movq 8(%r13), %rsi
228 subq (%rsp), %rdi
229 subq %rax, %rsi
230 jns 4f
231 addq $1000000000, %rsi
232 decq %rdi
233 4: testq %rdi, %rdi
234 js 8f /* Time is already up. */
235
236 /* Futex call. */
237 movq %rdi, (%rsp) /* Store relative timeout. */
238 movq %rsi, 8(%rsp)
239
240 movq 16(%rsp), %rdx
241 movl %edx, %eax
242 orl $FUTEX_WAITERS, %edx
243
244 testl $FUTEX_OWNER_DIED, %eax
245 jnz 6f
246
247 cmpl %eax, %edx
248 je 2f
249
250 LOCK
251 cmpxchgl %edx, (%r12)
252 movq $0, %rcx /* Must use mov to avoid changing cc. */
253 jnz 5f
254
255 2: movq %rsp, %r10
256 movl 32(%rsp), %esi
257 LOAD_FUTEX_WAIT (%esi)
258 movq %r12, %rdi
259 movl $SYS_futex, %eax
260 syscall
261 movq %rax, %rcx
262
263 movl (%r12), %eax
264
265 5: testl %eax, %eax
266 jne 7f
267
268 movl %fs:TID, %edx
269 orl $FUTEX_WAITERS, %edx
270 LOCK
271 cmpxchgl %edx, (%r12)
272 jnz 7f
273
274 6: addq $40, %rsp
275 cfi_adjust_cfa_offset(-40)
276 popq %r13
277 cfi_adjust_cfa_offset(-8)
278 cfi_restore(%r13)
279 popq %r12
280 cfi_adjust_cfa_offset(-8)
281 cfi_restore(%r12)
282 popq %r9
283 cfi_adjust_cfa_offset(-8)
284 cfi_restore(%r9)
285 popq %r8
286 cfi_adjust_cfa_offset(-8)
287 cfi_restore(%r8)
288 retq
289
290 3: movl $EINVAL, %eax
291 retq
292
293 cfi_adjust_cfa_offset(72)
294 cfi_offset(%r8, -16)
295 cfi_offset(%r9, -24)
296 cfi_offset(%r12, -32)
297 cfi_offset(%r13, -40)
298 /* Check whether the time expired. */
299 7: cmpl $-ETIMEDOUT, %ecx
300 jne 1b
301
302 8: movl $ETIMEDOUT, %eax
303 jmp 6b
304 #endif
305 cfi_endproc
306 .size __lll_robust_timedlock_wait,.-__lll_robust_timedlock_wait