]>
Commit | Line | Data |
---|---|---|
688903eb | 1 | /* Copyright (C) 2002-2018 Free Software Foundation, Inc. |
76a50749 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/>. */ | |
76a50749 UD |
18 | |
19 | #include <sysdep.h> | |
326132db | 20 | #include <pthread-errnos.h> |
e51deae7 UD |
21 | #include <kernel-features.h> |
22 | #include <lowlevellock.h> | |
76a50749 | 23 | |
17557282 RH |
24 | #include <stap-probe.h> |
25 | ||
76a50749 UD |
26 | .text |
27 | ||
0068c085 | 28 | #define LOAD_PRIVATE_FUTEX_WAIT(reg) \ |
e51deae7 | 29 | movl $(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg |
0068c085 | 30 | #define LOAD_PRIVATE_FUTEX_WAKE(reg) \ |
e51deae7 | 31 | movl $(FUTEX_WAKE | FUTEX_PRIVATE_FLAG), reg |
0068c085 | 32 | #define LOAD_FUTEX_WAIT(reg) \ |
e51deae7 | 33 | xorl $(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg |
0068c085 | 34 | #define LOAD_FUTEX_WAIT_ABS(reg) \ |
45f77606 | 35 | xorl $(FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME), reg |
0068c085 | 36 | #define LOAD_FUTEX_WAKE(reg) \ |
e51deae7 | 37 | xorl $(FUTEX_WAKE | FUTEX_PRIVATE_FLAG), reg |
76a50749 | 38 | |
e51deae7 UD |
39 | .globl __lll_lock_wait_private |
40 | .type __lll_lock_wait_private,@function | |
41 | .hidden __lll_lock_wait_private | |
76a50749 | 42 | .align 16 |
e51deae7 | 43 | __lll_lock_wait_private: |
cd248c3f | 44 | cfi_startproc |
76a50749 | 45 | pushl %edx |
cd248c3f | 46 | cfi_adjust_cfa_offset(4) |
c0df57e1 | 47 | pushl %ebx |
cd248c3f | 48 | cfi_adjust_cfa_offset(4) |
c0df57e1 | 49 | pushl %esi |
cd248c3f UD |
50 | cfi_adjust_cfa_offset(4) |
51 | cfi_offset(%edx, -8) | |
52 | cfi_offset(%ebx, -12) | |
53 | cfi_offset(%esi, -16) | |
76a50749 | 54 | |
c0df57e1 | 55 | movl $2, %edx |
76a50749 UD |
56 | movl %ecx, %ebx |
57 | xorl %esi, %esi /* No timeout. */ | |
e51deae7 | 58 | LOAD_PRIVATE_FUTEX_WAIT (%ecx) |
71451de2 | 59 | |
a8fd5a02 | 60 | cmpl %edx, %eax /* NB: %edx == 2 */ |
ebddb424 | 61 | jne 2f |
71451de2 | 62 | |
17557282 RH |
63 | 1: LIBC_PROBE (lll_lock_wait_private, 1, %ebx) |
64 | movl $SYS_futex, %eax | |
097eca29 | 65 | ENTER_KERNEL |
76a50749 | 66 | |
ebddb424 | 67 | 2: movl %edx, %eax |
a8fd5a02 | 68 | xchgl %eax, (%ebx) /* NB: lock is implied */ |
76a50749 | 69 | |
a8fd5a02 | 70 | testl %eax, %eax |
ab9a9ff8 | 71 | jnz 1b |
76a50749 | 72 | |
ebddb424 | 73 | popl %esi |
cd248c3f UD |
74 | cfi_adjust_cfa_offset(-4) |
75 | cfi_restore(%esi) | |
c0df57e1 | 76 | popl %ebx |
cd248c3f UD |
77 | cfi_adjust_cfa_offset(-4) |
78 | cfi_restore(%ebx) | |
c0df57e1 | 79 | popl %edx |
cd248c3f UD |
80 | cfi_adjust_cfa_offset(-4) |
81 | cfi_restore(%edx) | |
76a50749 | 82 | ret |
cd248c3f | 83 | cfi_endproc |
e51deae7 | 84 | .size __lll_lock_wait_private,.-__lll_lock_wait_private |
71451de2 | 85 | |
4f41c682 | 86 | #if !IS_IN (libc) |
e51deae7 UD |
87 | .globl __lll_lock_wait |
88 | .type __lll_lock_wait,@function | |
89 | .hidden __lll_lock_wait | |
71451de2 | 90 | .align 16 |
e51deae7 UD |
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 | ||
45f77606 UD |
133 | /* %ecx: futex |
134 | %esi: flags | |
135 | %edx: timeout | |
136 | %eax: futex value | |
137 | */ | |
e51deae7 UD |
138 | .globl __lll_timedlock_wait |
139 | .type __lll_timedlock_wait,@function | |
140 | .hidden __lll_timedlock_wait | |
141 | .align 16 | |
142 | __lll_timedlock_wait: | |
cd248c3f | 143 | cfi_startproc |
45f77606 UD |
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 | ||
2983d85e AS |
161 | cmpl $0, (%edx) |
162 | js 8f | |
163 | ||
45f77606 UD |
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 | ||
2983d85e AS |
199 | 8: movl $ETIMEDOUT, %eax |
200 | jmp 7b | |
201 | ||
45f77606 UD |
202 | # ifndef __ASSUME_FUTEX_CLOCK_REALTIME |
203 | .Lreltmo: | |
71451de2 UD |
204 | /* Check for a valid timeout value. */ |
205 | cmpl $1000000000, 4(%edx) | |
206 | jae 3f | |
207 | ||
71451de2 | 208 | pushl %esi |
cd248c3f | 209 | cfi_adjust_cfa_offset(4) |
45f77606 UD |
210 | cfi_rel_offset(%esi, 0) |
211 | pushl %edi | |
cd248c3f | 212 | cfi_adjust_cfa_offset(4) |
45f77606 | 213 | cfi_rel_offset(%edi, 0) |
71451de2 UD |
214 | |
215 | /* Stack frame for the timespec and timeval structs. */ | |
216 | subl $8, %esp | |
cd248c3f | 217 | cfi_adjust_cfa_offset(8) |
71451de2 UD |
218 | |
219 | movl %ecx, %ebp | |
220 | movl %edx, %edi | |
221 | ||
c012be6f UD |
222 | movl $2, %edx |
223 | xchgl %edx, (%ebp) | |
224 | ||
225 | test %edx, %edx | |
226 | je 6f | |
227 | ||
71451de2 UD |
228 | 1: |
229 | /* Get current time. */ | |
230 | movl %esp, %ebx | |
231 | xorl %ecx, %ecx | |
e51deae7 | 232 | movl $__NR_gettimeofday, %eax |
71451de2 UD |
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 | |
c012be6f | 247 | js 2f /* Time is already up. */ |
71451de2 UD |
248 | |
249 | /* Store relative timeout. */ | |
250 | movl %ecx, (%esp) | |
251 | movl %edx, 4(%esp) | |
252 | ||
c012be6f | 253 | /* Futex call. */ |
71451de2 | 254 | movl %ebp, %ebx |
71451de2 | 255 | movl $2, %edx |
71451de2 | 256 | movl %esp, %esi |
e51deae7 | 257 | movl 16(%esp), %ecx |
5a8075b1 | 258 | LOAD_FUTEX_WAIT (%ecx) |
71451de2 UD |
259 | movl $SYS_futex, %eax |
260 | ENTER_KERNEL | |
71451de2 | 261 | |
c012be6f UD |
262 | /* NB: %edx == 2 */ |
263 | xchgl %edx, (%ebp) | |
71451de2 | 264 | |
c012be6f UD |
265 | testl %edx, %edx |
266 | je 6f | |
267 | ||
268 | cmpl $-ETIMEDOUT, %eax | |
269 | jne 1b | |
270 | 2: movl $ETIMEDOUT, %edx | |
71451de2 UD |
271 | |
272 | 6: addl $8, %esp | |
cd248c3f | 273 | cfi_adjust_cfa_offset(-8) |
45f77606 | 274 | popl %edi |
cd248c3f | 275 | cfi_adjust_cfa_offset(-4) |
45f77606 | 276 | cfi_restore(%edi) |
71451de2 | 277 | popl %esi |
cd248c3f UD |
278 | cfi_adjust_cfa_offset(-4) |
279 | cfi_restore(%esi) | |
45f77606 | 280 | 7: popl %ebx |
cd248c3f | 281 | cfi_adjust_cfa_offset(-4) |
45f77606 UD |
282 | cfi_restore(%ebx) |
283 | popl %ebp | |
284 | cfi_adjust_cfa_offset(-4) | |
285 | cfi_restore(%ebp) | |
c012be6f | 286 | movl %edx, %eax |
71451de2 UD |
287 | ret |
288 | ||
45f77606 UD |
289 | 3: movl $EINVAL, %edx |
290 | jmp 7b | |
291 | # endif | |
cd248c3f | 292 | cfi_endproc |
e51deae7 | 293 | .size __lll_timedlock_wait,.-__lll_timedlock_wait |
71451de2 | 294 | #endif |
76a50749 | 295 | |
e51deae7 UD |
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 | |
76a50749 | 331 | |
4f41c682 | 332 | #if !IS_IN (libc) |
e51deae7 UD |
333 | .globl __lll_unlock_wake |
334 | .type __lll_unlock_wake,@function | |
335 | .hidden __lll_unlock_wake | |
bd8bb78b | 336 | .align 16 |
e51deae7 | 337 | __lll_unlock_wake: |
cd248c3f | 338 | cfi_startproc |
76a50749 | 339 | pushl %ebx |
cd248c3f | 340 | cfi_adjust_cfa_offset(4) |
76a50749 | 341 | pushl %ecx |
cd248c3f | 342 | cfi_adjust_cfa_offset(4) |
76a50749 | 343 | pushl %edx |
cd248c3f UD |
344 | cfi_adjust_cfa_offset(4) |
345 | cfi_offset(%ebx, -8) | |
346 | cfi_offset(%ecx, -12) | |
347 | cfi_offset(%edx, -16) | |
76a50749 UD |
348 | |
349 | movl %eax, %ebx | |
71451de2 | 350 | movl $0, (%eax) |
5a8075b1 | 351 | LOAD_FUTEX_WAKE (%ecx) |
76a50749 | 352 | movl $1, %edx /* Wake one thread. */ |
76a50749 | 353 | movl $SYS_futex, %eax |
097eca29 | 354 | ENTER_KERNEL |
76a50749 UD |
355 | |
356 | popl %edx | |
cd248c3f UD |
357 | cfi_adjust_cfa_offset(-4) |
358 | cfi_restore(%edx) | |
76a50749 | 359 | popl %ecx |
cd248c3f UD |
360 | cfi_adjust_cfa_offset(-4) |
361 | cfi_restore(%ecx) | |
76a50749 | 362 | popl %ebx |
cd248c3f UD |
363 | cfi_adjust_cfa_offset(-4) |
364 | cfi_restore(%ebx) | |
76a50749 | 365 | ret |
cd248c3f | 366 | cfi_endproc |
e51deae7 | 367 | .size __lll_unlock_wake,.-__lll_unlock_wake |
76a50749 | 368 | |
76a50749 UD |
369 | .globl __lll_timedwait_tid |
370 | .type __lll_timedwait_tid,@function | |
371 | .hidden __lll_timedwait_tid | |
bd8bb78b | 372 | .align 16 |
76a50749 UD |
373 | __lll_timedwait_tid: |
374 | pushl %edi | |
375 | pushl %esi | |
376 | pushl %ebx | |
377 | pushl %ebp | |
378 | ||
379 | movl %eax, %ebp | |
380 | movl %edx, %edi | |
381 | subl $8, %esp | |
382 | ||
383 | /* Get current time. */ | |
384 | 2: movl %esp, %ebx | |
385 | xorl %ecx, %ecx | |
e51deae7 | 386 | movl $__NR_gettimeofday, %eax |
097eca29 | 387 | ENTER_KERNEL |
76a50749 UD |
388 | |
389 | /* Compute relative timeout. */ | |
390 | movl 4(%esp), %eax | |
391 | movl $1000, %edx | |
392 | mul %edx /* Milli seconds to nano seconds. */ | |
393 | movl (%edi), %ecx | |
394 | movl 4(%edi), %edx | |
395 | subl (%esp), %ecx | |
396 | subl %eax, %edx | |
397 | jns 5f | |
398 | addl $1000000000, %edx | |
ccf1d573 | 399 | subl $1, %ecx |
76a50749 UD |
400 | 5: testl %ecx, %ecx |
401 | js 6f /* Time is already up. */ | |
402 | ||
403 | movl %ecx, (%esp) /* Store relative timeout. */ | |
404 | movl %edx, 4(%esp) | |
405 | ||
406 | movl (%ebp), %edx | |
407 | testl %edx, %edx | |
408 | jz 4f | |
409 | ||
410 | movl %esp, %esi | |
5a8075b1 UD |
411 | /* XXX The kernel so far uses global futex for the wakeup at |
412 | all times. */ | |
76a50749 UD |
413 | xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */ |
414 | movl %ebp, %ebx | |
415 | movl $SYS_futex, %eax | |
097eca29 | 416 | ENTER_KERNEL |
76a50749 | 417 | |
76a50749 UD |
418 | cmpl $0, (%ebx) |
419 | jne 1f | |
420 | 4: xorl %eax, %eax | |
421 | ||
422 | 3: addl $8, %esp | |
423 | popl %ebp | |
424 | popl %ebx | |
425 | popl %esi | |
426 | popl %edi | |
427 | ret | |
428 | ||
3273832c | 429 | 1: cmpl $-ETIMEDOUT, %eax |
76a50749 UD |
430 | jne 2b |
431 | 6: movl $ETIMEDOUT, %eax | |
432 | jmp 3b | |
433 | .size __lll_timedwait_tid,.-__lll_timedwait_tid | |
9356d063 | 434 | #endif |