]> git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/unix/sysv/linux/i386/lowlevellock.S
83191a38992c4a609dceae5a96e73812a1e80af6
[thirdparty/glibc.git] / sysdeps / unix / sysv / linux / i386 / lowlevellock.S
1 /* Copyright (C) 2002-2019 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 <kernel-features.h>
22 #include <lowlevellock.h>
23
24 #include <stap-probe.h>
25
26 .text
27
28 #define LOAD_PRIVATE_FUTEX_WAIT(reg) \
29 movl $(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg
30 #define LOAD_PRIVATE_FUTEX_WAKE(reg) \
31 movl $(FUTEX_WAKE | FUTEX_PRIVATE_FLAG), reg
32 #define LOAD_FUTEX_WAIT(reg) \
33 xorl $(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg
34 #define LOAD_FUTEX_WAIT_ABS(reg) \
35 xorl $(FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME), reg
36 #define LOAD_FUTEX_WAKE(reg) \
37 xorl $(FUTEX_WAKE | FUTEX_PRIVATE_FLAG), reg
38
39 .globl __lll_lock_wait_private
40 .type __lll_lock_wait_private,@function
41 .hidden __lll_lock_wait_private
42 .align 16
43 __lll_lock_wait_private:
44 cfi_startproc
45 pushl %edx
46 cfi_adjust_cfa_offset(4)
47 pushl %ebx
48 cfi_adjust_cfa_offset(4)
49 pushl %esi
50 cfi_adjust_cfa_offset(4)
51 cfi_offset(%edx, -8)
52 cfi_offset(%ebx, -12)
53 cfi_offset(%esi, -16)
54
55 movl $2, %edx
56 movl %ecx, %ebx
57 xorl %esi, %esi /* No timeout. */
58 LOAD_PRIVATE_FUTEX_WAIT (%ecx)
59
60 cmpl %edx, %eax /* NB: %edx == 2 */
61 jne 2f
62
63 1: LIBC_PROBE (lll_lock_wait_private, 1, %ebx)
64 movl $SYS_futex, %eax
65 ENTER_KERNEL
66
67 2: movl %edx, %eax
68 xchgl %eax, (%ebx) /* NB: lock is implied */
69
70 testl %eax, %eax
71 jnz 1b
72
73 popl %esi
74 cfi_adjust_cfa_offset(-4)
75 cfi_restore(%esi)
76 popl %ebx
77 cfi_adjust_cfa_offset(-4)
78 cfi_restore(%ebx)
79 popl %edx
80 cfi_adjust_cfa_offset(-4)
81 cfi_restore(%edx)
82 ret
83 cfi_endproc
84 .size __lll_lock_wait_private,.-__lll_lock_wait_private
85
86 #if !IS_IN (libc)
87 .globl __lll_lock_wait
88 .type __lll_lock_wait,@function
89 .hidden __lll_lock_wait
90 .align 16
91 __lll_lock_wait:
92 cfi_startproc
93 pushl %edx
94 cfi_adjust_cfa_offset(4)
95 pushl %ebx
96 cfi_adjust_cfa_offset(4)
97 pushl %esi
98 cfi_adjust_cfa_offset(4)
99 cfi_offset(%edx, -8)
100 cfi_offset(%ebx, -12)
101 cfi_offset(%esi, -16)
102
103 movl %edx, %ebx
104 movl $2, %edx
105 xorl %esi, %esi /* No timeout. */
106 LOAD_FUTEX_WAIT (%ecx)
107
108 cmpl %edx, %eax /* NB: %edx == 2 */
109 jne 2f
110
111 1: movl $SYS_futex, %eax
112 ENTER_KERNEL
113
114 2: movl %edx, %eax
115 xchgl %eax, (%ebx) /* NB: lock is implied */
116
117 testl %eax, %eax
118 jnz 1b
119
120 popl %esi
121 cfi_adjust_cfa_offset(-4)
122 cfi_restore(%esi)
123 popl %ebx
124 cfi_adjust_cfa_offset(-4)
125 cfi_restore(%ebx)
126 popl %edx
127 cfi_adjust_cfa_offset(-4)
128 cfi_restore(%edx)
129 ret
130 cfi_endproc
131 .size __lll_lock_wait,.-__lll_lock_wait
132
133 /* %ecx: futex
134 %esi: flags
135 %edx: timeout
136 %eax: futex value
137 */
138 .globl __lll_timedlock_wait
139 .type __lll_timedlock_wait,@function
140 .hidden __lll_timedlock_wait
141 .align 16
142 __lll_timedlock_wait:
143 cfi_startproc
144 pushl %ebp
145 cfi_adjust_cfa_offset(4)
146 cfi_rel_offset(%ebp, 0)
147 pushl %ebx
148 cfi_adjust_cfa_offset(4)
149 cfi_rel_offset(%ebx, 0)
150
151 # ifndef __ASSUME_FUTEX_CLOCK_REALTIME
152 # ifdef PIC
153 LOAD_PIC_REG (bx)
154 cmpl $0, __have_futex_clock_realtime@GOTOFF(%ebx)
155 # else
156 cmpl $0, __have_futex_clock_realtime
157 # endif
158 je .Lreltmo
159 # endif
160
161 cmpl $0, (%edx)
162 js 8f
163
164 movl %ecx, %ebx
165 movl %esi, %ecx
166 movl %edx, %esi
167 movl $0xffffffff, %ebp
168 LOAD_FUTEX_WAIT_ABS (%ecx)
169
170 movl $2, %edx
171 cmpl %edx, %eax
172 jne 2f
173
174 1: movl $SYS_futex, %eax
175 movl $2, %edx
176 ENTER_KERNEL
177
178 2: xchgl %edx, (%ebx) /* NB: lock is implied */
179
180 testl %edx, %edx
181 jz 3f
182
183 cmpl $-ETIMEDOUT, %eax
184 je 4f
185 cmpl $-EINVAL, %eax
186 jne 1b
187 4: movl %eax, %edx
188 negl %edx
189
190 3: movl %edx, %eax
191 7: popl %ebx
192 cfi_adjust_cfa_offset(-4)
193 cfi_restore(%ebx)
194 popl %ebp
195 cfi_adjust_cfa_offset(-4)
196 cfi_restore(%ebp)
197 ret
198
199 8: movl $ETIMEDOUT, %eax
200 jmp 7b
201
202 # ifndef __ASSUME_FUTEX_CLOCK_REALTIME
203 .Lreltmo:
204 /* Check for a valid timeout value. */
205 cmpl $1000000000, 4(%edx)
206 jae 3f
207
208 pushl %esi
209 cfi_adjust_cfa_offset(4)
210 cfi_rel_offset(%esi, 0)
211 pushl %edi
212 cfi_adjust_cfa_offset(4)
213 cfi_rel_offset(%edi, 0)
214
215 /* Stack frame for the timespec and timeval structs. */
216 subl $8, %esp
217 cfi_adjust_cfa_offset(8)
218
219 movl %ecx, %ebp
220 movl %edx, %edi
221
222 movl $2, %edx
223 xchgl %edx, (%ebp)
224
225 test %edx, %edx
226 je 6f
227
228 1:
229 /* Get current time. */
230 movl %esp, %ebx
231 xorl %ecx, %ecx
232 movl $__NR_gettimeofday, %eax
233 ENTER_KERNEL
234
235 /* Compute relative timeout. */
236 movl 4(%esp), %eax
237 movl $1000, %edx
238 mul %edx /* Milli seconds to nano seconds. */
239 movl (%edi), %ecx
240 movl 4(%edi), %edx
241 subl (%esp), %ecx
242 subl %eax, %edx
243 jns 4f
244 addl $1000000000, %edx
245 subl $1, %ecx
246 4: testl %ecx, %ecx
247 js 2f /* Time is already up. */
248
249 /* Store relative timeout. */
250 movl %ecx, (%esp)
251 movl %edx, 4(%esp)
252
253 /* Futex call. */
254 movl %ebp, %ebx
255 movl $2, %edx
256 movl %esp, %esi
257 movl 16(%esp), %ecx
258 LOAD_FUTEX_WAIT (%ecx)
259 movl $SYS_futex, %eax
260 ENTER_KERNEL
261
262 /* NB: %edx == 2 */
263 xchgl %edx, (%ebp)
264
265 testl %edx, %edx
266 je 6f
267
268 cmpl $-ETIMEDOUT, %eax
269 jne 1b
270 2: movl $ETIMEDOUT, %edx
271
272 6: addl $8, %esp
273 cfi_adjust_cfa_offset(-8)
274 popl %edi
275 cfi_adjust_cfa_offset(-4)
276 cfi_restore(%edi)
277 popl %esi
278 cfi_adjust_cfa_offset(-4)
279 cfi_restore(%esi)
280 7: popl %ebx
281 cfi_adjust_cfa_offset(-4)
282 cfi_restore(%ebx)
283 popl %ebp
284 cfi_adjust_cfa_offset(-4)
285 cfi_restore(%ebp)
286 movl %edx, %eax
287 ret
288
289 3: movl $EINVAL, %edx
290 jmp 7b
291 # endif
292 cfi_endproc
293 .size __lll_timedlock_wait,.-__lll_timedlock_wait
294 #endif
295
296 .globl __lll_unlock_wake_private
297 .type __lll_unlock_wake_private,@function
298 .hidden __lll_unlock_wake_private
299 .align 16
300 __lll_unlock_wake_private:
301 cfi_startproc
302 pushl %ebx
303 cfi_adjust_cfa_offset(4)
304 pushl %ecx
305 cfi_adjust_cfa_offset(4)
306 pushl %edx
307 cfi_adjust_cfa_offset(4)
308 cfi_offset(%ebx, -8)
309 cfi_offset(%ecx, -12)
310 cfi_offset(%edx, -16)
311
312 movl %eax, %ebx
313 movl $0, (%eax)
314 LOAD_PRIVATE_FUTEX_WAKE (%ecx)
315 movl $1, %edx /* Wake one thread. */
316 movl $SYS_futex, %eax
317 ENTER_KERNEL
318
319 popl %edx
320 cfi_adjust_cfa_offset(-4)
321 cfi_restore(%edx)
322 popl %ecx
323 cfi_adjust_cfa_offset(-4)
324 cfi_restore(%ecx)
325 popl %ebx
326 cfi_adjust_cfa_offset(-4)
327 cfi_restore(%ebx)
328 ret
329 cfi_endproc
330 .size __lll_unlock_wake_private,.-__lll_unlock_wake_private
331
332 #if !IS_IN (libc)
333 .globl __lll_unlock_wake
334 .type __lll_unlock_wake,@function
335 .hidden __lll_unlock_wake
336 .align 16
337 __lll_unlock_wake:
338 cfi_startproc
339 pushl %ebx
340 cfi_adjust_cfa_offset(4)
341 pushl %ecx
342 cfi_adjust_cfa_offset(4)
343 pushl %edx
344 cfi_adjust_cfa_offset(4)
345 cfi_offset(%ebx, -8)
346 cfi_offset(%ecx, -12)
347 cfi_offset(%edx, -16)
348
349 movl %eax, %ebx
350 movl $0, (%eax)
351 LOAD_FUTEX_WAKE (%ecx)
352 movl $1, %edx /* Wake one thread. */
353 movl $SYS_futex, %eax
354 ENTER_KERNEL
355
356 popl %edx
357 cfi_adjust_cfa_offset(-4)
358 cfi_restore(%edx)
359 popl %ecx
360 cfi_adjust_cfa_offset(-4)
361 cfi_restore(%ecx)
362 popl %ebx
363 cfi_adjust_cfa_offset(-4)
364 cfi_restore(%ebx)
365 ret
366 cfi_endproc
367 .size __lll_unlock_wake,.-__lll_unlock_wake
368 #endif