]>
Commit | Line | Data |
---|---|---|
f7a9f785 | 1 | /* Copyright (C) 2002-2016 Free Software Foundation, Inc. |
1d087a7e 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/>. */ | |
1d087a7e UD |
18 | |
19 | #include <sysdep.h> | |
20 | #include <shlib-compat.h> | |
e51deae7 | 21 | #include <lowlevellock.h> |
1d087a7e | 22 | #include <lowlevelcond.h> |
a7720b5e | 23 | #include <tcb-offsets.h> |
75956694 DG |
24 | #include <pthread-errnos.h> |
25 | #include <pthread-pi-defines.h> | |
22502ea2 | 26 | #include <kernel-features.h> |
17557282 | 27 | #include <stap-probe.h> |
1d087a7e | 28 | |
1d087a7e UD |
29 | |
30 | .text | |
31 | ||
1d087a7e UD |
32 | /* int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex) */ |
33 | .globl __pthread_cond_wait | |
34 | .type __pthread_cond_wait, @function | |
35 | .align 16 | |
36 | __pthread_cond_wait: | |
08c765fa | 37 | .LSTARTCODE: |
f8c10bb4 UD |
38 | cfi_startproc |
39 | #ifdef SHARED | |
40 | cfi_personality(DW_EH_PE_pcrel | DW_EH_PE_sdata4 | DW_EH_PE_indirect, | |
41 | DW.ref.__gcc_personality_v0) | |
42 | cfi_lsda(DW_EH_PE_pcrel | DW_EH_PE_sdata4, .LexceptSTART) | |
43 | #else | |
44 | cfi_personality(DW_EH_PE_udata4, __gcc_personality_v0) | |
45 | cfi_lsda(DW_EH_PE_udata4, .LexceptSTART) | |
46 | #endif | |
1d087a7e | 47 | |
75956694 DG |
48 | pushl %ebp |
49 | cfi_adjust_cfa_offset(4) | |
50 | cfi_rel_offset(%ebp, 0) | |
1d087a7e | 51 | pushl %edi |
f8c10bb4 UD |
52 | cfi_adjust_cfa_offset(4) |
53 | cfi_rel_offset(%edi, 0) | |
1d087a7e | 54 | pushl %esi |
f8c10bb4 UD |
55 | cfi_adjust_cfa_offset(4) |
56 | cfi_rel_offset(%esi, 0) | |
1d087a7e | 57 | pushl %ebx |
f8c10bb4 UD |
58 | cfi_adjust_cfa_offset(4) |
59 | cfi_rel_offset(%ebx, 0) | |
1d087a7e UD |
60 | |
61 | xorl %esi, %esi | |
75956694 | 62 | movl 20(%esp), %ebx |
1d087a7e | 63 | |
17557282 RH |
64 | LIBC_PROBE (cond_wait, 2, 24(%esp), %ebx) |
65 | ||
1d087a7e | 66 | /* Get internal lock. */ |
71451de2 UD |
67 | movl $1, %edx |
68 | xorl %eax, %eax | |
1d087a7e UD |
69 | LOCK |
70 | #if cond_lock == 0 | |
71451de2 | 71 | cmpxchgl %edx, (%ebx) |
1d087a7e | 72 | #else |
71451de2 | 73 | cmpxchgl %edx, cond_lock(%ebx) |
1d087a7e | 74 | #endif |
3a226d33 | 75 | jnz 1f |
1d087a7e | 76 | |
69431c9a UD |
77 | /* Store the reference to the mutex. If there is already a |
78 | different value in there this is a bad user bug. */ | |
e42a990e | 79 | 2: cmpl $-1, dep_mutex(%ebx) |
75956694 | 80 | movl 24(%esp), %eax |
e42a990e | 81 | je 15f |
69431c9a UD |
82 | movl %eax, dep_mutex(%ebx) |
83 | ||
1d087a7e | 84 | /* Unlock the mutex. */ |
e42a990e | 85 | 15: xorl %edx, %edx |
61623643 | 86 | call __pthread_mutex_unlock_usercnt |
1d087a7e | 87 | |
a7720b5e UD |
88 | testl %eax, %eax |
89 | jne 12f | |
90 | ||
1d087a7e UD |
91 | addl $1, total_seq(%ebx) |
92 | adcl $0, total_seq+4(%ebx) | |
75fccede | 93 | addl $1, cond_futex(%ebx) |
ee5d5755 | 94 | addl $(1 << nwaiters_shift), cond_nwaiters(%ebx) |
1d087a7e | 95 | |
75956694 | 96 | #define FRAME_SIZE 20 |
4123718e | 97 | subl $FRAME_SIZE, %esp |
f8c10bb4 | 98 | cfi_adjust_cfa_offset(FRAME_SIZE) |
893549c5 | 99 | cfi_remember_state |
1d087a7e UD |
100 | |
101 | /* Get and store current wakeup_seq value. */ | |
102 | movl wakeup_seq(%ebx), %edi | |
103 | movl wakeup_seq+4(%ebx), %edx | |
893a3511 | 104 | movl broadcast_seq(%ebx), %eax |
67b78ef9 UD |
105 | movl %edi, 4(%esp) |
106 | movl %edx, 8(%esp) | |
893a3511 | 107 | movl %eax, 12(%esp) |
1d087a7e | 108 | |
75956694 DG |
109 | /* Reset the pi-requeued flag. */ |
110 | 8: movl $0, 16(%esp) | |
23b85756 | 111 | movl cond_futex(%ebx), %ebp |
5a9e37df | 112 | |
1d087a7e | 113 | /* Unlock. */ |
75fccede | 114 | LOCK |
1d087a7e | 115 | #if cond_lock == 0 |
ccf1d573 | 116 | subl $1, (%ebx) |
1d087a7e | 117 | #else |
ccf1d573 | 118 | subl $1, cond_lock(%ebx) |
1d087a7e UD |
119 | #endif |
120 | jne 3f | |
121 | ||
67b78ef9 | 122 | .LcleanupSTART: |
69431c9a | 123 | 4: call __pthread_enable_asynccancel |
67b78ef9 | 124 | movl %eax, (%esp) |
1d087a7e | 125 | |
22502ea2 | 126 | xorl %ecx, %ecx |
22502ea2 UD |
127 | cmpl $-1, dep_mutex(%ebx) |
128 | sete %cl | |
23b85756 | 129 | je 18f |
75956694 DG |
130 | |
131 | movl dep_mutex(%ebx), %edi | |
132 | /* Requeue to a non-robust PI mutex if the PI bit is set and | |
133 | the robust bit is not set. */ | |
134 | movl MUTEX_KIND(%edi), %eax | |
135 | andl $(ROBUST_BIT|PI_BIT), %eax | |
136 | cmpl $PI_BIT, %eax | |
137 | jne 18f | |
5a9e37df | 138 | |
75956694 DG |
139 | movl $(FUTEX_WAIT_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %ecx |
140 | movl %ebp, %edx | |
141 | xorl %esi, %esi | |
142 | addl $cond_futex, %ebx | |
55a051c9 | 143 | .Ladd_cond_futex_pi: |
75956694 DG |
144 | movl $SYS_futex, %eax |
145 | ENTER_KERNEL | |
146 | subl $cond_futex, %ebx | |
55a051c9 | 147 | .Lsub_cond_futex_pi: |
75956694 DG |
148 | /* Set the pi-requeued flag only if the kernel has returned 0. The |
149 | kernel does not hold the mutex on error. */ | |
150 | cmpl $0, %eax | |
151 | sete 16(%esp) | |
152 | je 19f | |
153 | ||
c30e8edf SP |
154 | /* When a futex syscall with FUTEX_WAIT_REQUEUE_PI returns |
155 | successfully, it has already locked the mutex for us and the | |
156 | pi_flag (16(%esp)) is set to denote that fact. However, if another | |
157 | thread changed the futex value before we entered the wait, the | |
158 | syscall may return an EAGAIN and the mutex is not locked. We go | |
159 | ahead with a success anyway since later we look at the pi_flag to | |
160 | decide if we got the mutex or not. The sequence numbers then make | |
161 | sure that only one of the threads actually wake up. We retry using | |
162 | normal FUTEX_WAIT only if the kernel returned ENOSYS, since normal | |
163 | and PI futexes don't mix. | |
164 | ||
165 | Note that we don't check for EAGAIN specifically; we assume that the | |
166 | only other error the futex function could return is EAGAIN since | |
167 | anything else would mean an error in our function. It is too | |
168 | expensive to do that check for every call (which is quite common in | |
169 | case of a large number of threads), so it has been skipped. */ | |
75956694 DG |
170 | cmpl $-ENOSYS, %eax |
171 | jne 19f | |
172 | xorl %ecx, %ecx | |
5a9e37df | 173 | |
75956694 | 174 | 18: subl $1, %ecx |
22502ea2 UD |
175 | #ifdef __ASSUME_PRIVATE_FUTEX |
176 | andl $FUTEX_PRIVATE_FLAG, %ecx | |
177 | #else | |
178 | andl %gs:PRIVATE_FUTEX, %ecx | |
179 | #endif | |
180 | #if FUTEX_WAIT != 0 | |
181 | addl $FUTEX_WAIT, %ecx | |
182 | #endif | |
75956694 | 183 | movl %ebp, %edx |
75fccede UD |
184 | addl $cond_futex, %ebx |
185 | .Ladd_cond_futex: | |
1d087a7e UD |
186 | movl $SYS_futex, %eax |
187 | ENTER_KERNEL | |
75fccede UD |
188 | subl $cond_futex, %ebx |
189 | .Lsub_cond_futex: | |
1d087a7e | 190 | |
75956694 | 191 | 19: movl (%esp), %eax |
1d087a7e | 192 | call __pthread_disable_asynccancel |
67b78ef9 | 193 | .LcleanupEND: |
1d087a7e UD |
194 | |
195 | /* Lock. */ | |
71451de2 UD |
196 | movl $1, %edx |
197 | xorl %eax, %eax | |
1d087a7e UD |
198 | LOCK |
199 | #if cond_lock == 0 | |
71451de2 | 200 | cmpxchgl %edx, (%ebx) |
1d087a7e | 201 | #else |
71451de2 | 202 | cmpxchgl %edx, cond_lock(%ebx) |
1d087a7e | 203 | #endif |
3a226d33 | 204 | jnz 5f |
1d087a7e | 205 | |
893a3511 UD |
206 | 6: movl broadcast_seq(%ebx), %eax |
207 | cmpl 12(%esp), %eax | |
208 | jne 16f | |
209 | ||
210 | movl woken_seq(%ebx), %eax | |
1d087a7e UD |
211 | movl woken_seq+4(%ebx), %ecx |
212 | ||
213 | movl wakeup_seq(%ebx), %edi | |
214 | movl wakeup_seq+4(%ebx), %edx | |
215 | ||
67b78ef9 | 216 | cmpl 8(%esp), %edx |
cff08c81 | 217 | jne 7f |
67b78ef9 | 218 | cmpl 4(%esp), %edi |
c30e8edf | 219 | je 22f |
1d087a7e UD |
220 | |
221 | 7: cmpl %ecx, %edx | |
cff08c81 | 222 | jne 9f |
1d087a7e | 223 | cmp %eax, %edi |
c30e8edf | 224 | je 22f |
1d087a7e UD |
225 | |
226 | 9: addl $1, woken_seq(%ebx) | |
227 | adcl $0, woken_seq+4(%ebx) | |
228 | ||
893a3511 | 229 | /* Unlock */ |
ee5d5755 | 230 | 16: subl $(1 << nwaiters_shift), cond_nwaiters(%ebx) |
73f7c32c UD |
231 | |
232 | /* Wake up a thread which wants to destroy the condvar object. */ | |
233 | movl total_seq(%ebx), %eax | |
234 | andl total_seq+4(%ebx), %eax | |
235 | cmpl $0xffffffff, %eax | |
236 | jne 17f | |
237 | movl cond_nwaiters(%ebx), %eax | |
ee5d5755 | 238 | andl $~((1 << nwaiters_shift) - 1), %eax |
73f7c32c UD |
239 | jne 17f |
240 | ||
241 | addl $cond_nwaiters, %ebx | |
242 | movl $SYS_futex, %eax | |
22502ea2 UD |
243 | #if FUTEX_PRIVATE_FLAG > 255 |
244 | xorl %ecx, %ecx | |
245 | #endif | |
246 | cmpl $-1, dep_mutex-cond_nwaiters(%ebx) | |
247 | sete %cl | |
248 | subl $1, %ecx | |
249 | #ifdef __ASSUME_PRIVATE_FUTEX | |
250 | andl $FUTEX_PRIVATE_FLAG, %ecx | |
251 | #else | |
252 | andl %gs:PRIVATE_FUTEX, %ecx | |
253 | #endif | |
254 | addl $FUTEX_WAKE, %ecx | |
73f7c32c UD |
255 | movl $1, %edx |
256 | ENTER_KERNEL | |
257 | subl $cond_nwaiters, %ebx | |
258 | ||
259 | 17: LOCK | |
1d087a7e | 260 | #if cond_lock == 0 |
ccf1d573 | 261 | subl $1, (%ebx) |
1d087a7e | 262 | #else |
ccf1d573 | 263 | subl $1, cond_lock(%ebx) |
1d087a7e UD |
264 | #endif |
265 | jne 10f | |
266 | ||
75956694 | 267 | /* With requeue_pi, the mutex lock is held in the kernel. */ |
893549c5 | 268 | 11: movl 24+FRAME_SIZE(%esp), %eax |
75956694 DG |
269 | movl 16(%esp), %ecx |
270 | testl %ecx, %ecx | |
893549c5 | 271 | jnz 21f |
75956694 | 272 | |
69431c9a | 273 | call __pthread_mutex_cond_lock |
75956694 | 274 | 20: addl $FRAME_SIZE, %esp |
f8c10bb4 | 275 | cfi_adjust_cfa_offset(-FRAME_SIZE); |
1d087a7e | 276 | |
a7720b5e | 277 | 14: popl %ebx |
f8c10bb4 UD |
278 | cfi_adjust_cfa_offset(-4) |
279 | cfi_restore(%ebx) | |
1d087a7e | 280 | popl %esi |
f8c10bb4 UD |
281 | cfi_adjust_cfa_offset(-4) |
282 | cfi_restore(%esi) | |
1d087a7e | 283 | popl %edi |
f8c10bb4 UD |
284 | cfi_adjust_cfa_offset(-4) |
285 | cfi_restore(%edi) | |
75956694 DG |
286 | popl %ebp |
287 | cfi_adjust_cfa_offset(-4) | |
288 | cfi_restore(%ebp) | |
1d087a7e UD |
289 | |
290 | /* We return the result of the mutex_lock operation. */ | |
291 | ret | |
292 | ||
f8c10bb4 UD |
293 | cfi_restore_state |
294 | ||
75956694 DG |
295 | 21: call __pthread_mutex_cond_lock_adjust |
296 | xorl %eax, %eax | |
297 | jmp 20b | |
298 | ||
893549c5 | 299 | cfi_adjust_cfa_offset(-FRAME_SIZE); |
c30e8edf SP |
300 | |
301 | /* We need to go back to futex_wait. If we're using requeue_pi, then | |
302 | release the mutex we had acquired and go back. */ | |
303 | 22: movl 16(%esp), %edx | |
304 | test %edx, %edx | |
305 | jz 8b | |
306 | ||
307 | /* Adjust the mutex values first and then unlock it. The unlock | |
308 | should always succeed or else the kernel did not lock the mutex | |
309 | correctly. */ | |
310 | movl dep_mutex(%ebx), %eax | |
311 | call __pthread_mutex_cond_lock_adjust | |
312 | xorl %edx, %edx | |
313 | call __pthread_mutex_unlock_usercnt | |
314 | jmp 8b | |
315 | ||
1d087a7e UD |
316 | /* Initial locking failed. */ |
317 | 1: | |
318 | #if cond_lock == 0 | |
e51deae7 | 319 | movl %ebx, %edx |
1d087a7e | 320 | #else |
e51deae7 | 321 | leal cond_lock(%ebx), %edx |
1d087a7e | 322 | #endif |
22502ea2 UD |
323 | #if (LLL_SHARED-LLL_PRIVATE) > 255 |
324 | xorl %ecx, %ecx | |
325 | #endif | |
326 | cmpl $-1, dep_mutex(%ebx) | |
327 | setne %cl | |
328 | subl $1, %ecx | |
329 | andl $(LLL_SHARED-LLL_PRIVATE), %ecx | |
330 | #if LLL_PRIVATE != 0 | |
331 | addl $LLL_PRIVATE, %ecx | |
332 | #endif | |
e51deae7 | 333 | call __lll_lock_wait |
1d087a7e UD |
334 | jmp 2b |
335 | ||
f8c10bb4 UD |
336 | /* The initial unlocking of the mutex failed. */ |
337 | 12: | |
338 | LOCK | |
339 | #if cond_lock == 0 | |
340 | subl $1, (%ebx) | |
341 | #else | |
342 | subl $1, cond_lock(%ebx) | |
343 | #endif | |
344 | jne 14b | |
345 | ||
346 | movl %eax, %esi | |
1d087a7e UD |
347 | #if cond_lock == 0 |
348 | movl %ebx, %eax | |
349 | #else | |
350 | leal cond_lock(%ebx), %eax | |
351 | #endif | |
22502ea2 UD |
352 | #if (LLL_SHARED-LLL_PRIVATE) > 255 |
353 | xorl %ecx, %ecx | |
354 | #endif | |
355 | cmpl $-1, dep_mutex(%ebx) | |
356 | setne %cl | |
357 | subl $1, %ecx | |
358 | andl $(LLL_SHARED-LLL_PRIVATE), %ecx | |
359 | #if LLL_PRIVATE != 0 | |
360 | addl $LLL_PRIVATE, %ecx | |
361 | #endif | |
e51deae7 | 362 | call __lll_unlock_wake |
1d087a7e | 363 | |
f8c10bb4 UD |
364 | movl %esi, %eax |
365 | jmp 14b | |
366 | ||
367 | cfi_adjust_cfa_offset(FRAME_SIZE) | |
368 | ||
369 | /* Unlock in loop requires wakeup. */ | |
370 | 3: | |
1d087a7e | 371 | #if cond_lock == 0 |
f8c10bb4 | 372 | movl %ebx, %eax |
1d087a7e | 373 | #else |
f8c10bb4 | 374 | leal cond_lock(%ebx), %eax |
1d087a7e | 375 | #endif |
22502ea2 UD |
376 | #if (LLL_SHARED-LLL_PRIVATE) > 255 |
377 | xorl %ecx, %ecx | |
378 | #endif | |
379 | cmpl $-1, dep_mutex(%ebx) | |
380 | setne %cl | |
381 | subl $1, %ecx | |
382 | andl $(LLL_SHARED-LLL_PRIVATE), %ecx | |
383 | #if LLL_PRIVATE != 0 | |
384 | addl $LLL_PRIVATE, %ecx | |
385 | #endif | |
f8c10bb4 UD |
386 | call __lll_unlock_wake |
387 | jmp 4b | |
1d087a7e | 388 | |
f8c10bb4 UD |
389 | /* Locking in loop failed. */ |
390 | 5: | |
1d087a7e | 391 | #if cond_lock == 0 |
f8c10bb4 | 392 | movl %ebx, %edx |
1d087a7e | 393 | #else |
f8c10bb4 | 394 | leal cond_lock(%ebx), %edx |
1d087a7e | 395 | #endif |
22502ea2 UD |
396 | #if (LLL_SHARED-LLL_PRIVATE) > 255 |
397 | xorl %ecx, %ecx | |
398 | #endif | |
399 | cmpl $-1, dep_mutex(%ebx) | |
400 | setne %cl | |
401 | subl $1, %ecx | |
402 | andl $(LLL_SHARED-LLL_PRIVATE), %ecx | |
403 | #if LLL_PRIVATE != 0 | |
404 | addl $LLL_PRIVATE, %ecx | |
405 | #endif | |
f8c10bb4 UD |
406 | call __lll_lock_wait |
407 | jmp 6b | |
a7720b5e | 408 | |
f8c10bb4 UD |
409 | /* Unlock after loop requires wakeup. */ |
410 | 10: | |
a7720b5e UD |
411 | #if cond_lock == 0 |
412 | movl %ebx, %eax | |
413 | #else | |
414 | leal cond_lock(%ebx), %eax | |
415 | #endif | |
22502ea2 UD |
416 | #if (LLL_SHARED-LLL_PRIVATE) > 255 |
417 | xorl %ecx, %ecx | |
418 | #endif | |
419 | cmpl $-1, dep_mutex(%ebx) | |
420 | setne %cl | |
421 | subl $1, %ecx | |
422 | andl $(LLL_SHARED-LLL_PRIVATE), %ecx | |
423 | #if LLL_PRIVATE != 0 | |
424 | addl $LLL_PRIVATE, %ecx | |
425 | #endif | |
e51deae7 | 426 | call __lll_unlock_wake |
f8c10bb4 | 427 | jmp 11b |
c5a0802a | 428 | |
1d087a7e UD |
429 | .size __pthread_cond_wait, .-__pthread_cond_wait |
430 | versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait, | |
431 | GLIBC_2_3_2) | |
432 | ||
433 | ||
7539c7ec UD |
434 | .type __condvar_w_cleanup2, @function |
435 | __condvar_w_cleanup2: | |
75fccede | 436 | subl $cond_futex, %ebx |
7539c7ec | 437 | .size __condvar_w_cleanup2, .-__condvar_w_cleanup2 |
67b78ef9 | 438 | .LSbl4: |
7539c7ec UD |
439 | .type __condvar_w_cleanup, @function |
440 | __condvar_w_cleanup: | |
67b78ef9 UD |
441 | movl %eax, %esi |
442 | ||
443 | /* Get internal lock. */ | |
71451de2 UD |
444 | movl $1, %edx |
445 | xorl %eax, %eax | |
67b78ef9 UD |
446 | LOCK |
447 | #if cond_lock == 0 | |
71451de2 | 448 | cmpxchgl %edx, (%ebx) |
67b78ef9 | 449 | #else |
71451de2 | 450 | cmpxchgl %edx, cond_lock(%ebx) |
67b78ef9 | 451 | #endif |
3a226d33 | 452 | jz 1f |
67b78ef9 UD |
453 | |
454 | #if cond_lock == 0 | |
e51deae7 | 455 | movl %ebx, %edx |
67b78ef9 | 456 | #else |
e51deae7 | 457 | leal cond_lock(%ebx), %edx |
67b78ef9 | 458 | #endif |
22502ea2 UD |
459 | #if (LLL_SHARED-LLL_PRIVATE) > 255 |
460 | xorl %ecx, %ecx | |
461 | #endif | |
462 | cmpl $-1, dep_mutex(%ebx) | |
463 | setne %cl | |
464 | subl $1, %ecx | |
465 | andl $(LLL_SHARED-LLL_PRIVATE), %ecx | |
466 | #if LLL_PRIVATE != 0 | |
467 | addl $LLL_PRIVATE, %ecx | |
468 | #endif | |
e51deae7 | 469 | call __lll_lock_wait |
67b78ef9 | 470 | |
893a3511 UD |
471 | 1: movl broadcast_seq(%ebx), %eax |
472 | cmpl 12(%esp), %eax | |
473 | jne 3f | |
474 | ||
2b6a801e | 475 | /* We increment the wakeup_seq counter only if it is lower than |
346e6ad4 UD |
476 | total_seq. If this is not the case the thread was woken and |
477 | then canceled. In this case we ignore the signal. */ | |
478 | movl total_seq(%ebx), %eax | |
479 | movl total_seq+4(%ebx), %edi | |
480 | cmpl wakeup_seq+4(%ebx), %edi | |
481 | jb 6f | |
482 | ja 7f | |
483 | cmpl wakeup_seq(%ebx), %eax | |
484 | jbe 7f | |
485 | ||
486 | 6: addl $1, wakeup_seq(%ebx) | |
67b78ef9 | 487 | adcl $0, wakeup_seq+4(%ebx) |
2b6a801e | 488 | addl $1, cond_futex(%ebx) |
a334319f | 489 | |
2b6a801e | 490 | 7: addl $1, woken_seq(%ebx) |
67b78ef9 UD |
491 | adcl $0, woken_seq+4(%ebx) |
492 | ||
ee5d5755 | 493 | 3: subl $(1 << nwaiters_shift), cond_nwaiters(%ebx) |
73f7c32c UD |
494 | |
495 | /* Wake up a thread which wants to destroy the condvar object. */ | |
496 | xorl %edi, %edi | |
497 | movl total_seq(%ebx), %eax | |
498 | andl total_seq+4(%ebx), %eax | |
499 | cmpl $0xffffffff, %eax | |
500 | jne 4f | |
501 | movl cond_nwaiters(%ebx), %eax | |
ee5d5755 | 502 | andl $~((1 << nwaiters_shift) - 1), %eax |
73f7c32c UD |
503 | jne 4f |
504 | ||
505 | addl $cond_nwaiters, %ebx | |
506 | movl $SYS_futex, %eax | |
22502ea2 UD |
507 | #if FUTEX_PRIVATE_FLAG > 255 |
508 | xorl %ecx, %ecx | |
509 | #endif | |
510 | cmpl $-1, dep_mutex-cond_nwaiters(%ebx) | |
511 | sete %cl | |
512 | subl $1, %ecx | |
513 | #ifdef __ASSUME_PRIVATE_FUTEX | |
514 | andl $FUTEX_PRIVATE_FLAG, %ecx | |
515 | #else | |
516 | andl %gs:PRIVATE_FUTEX, %ecx | |
517 | #endif | |
518 | addl $FUTEX_WAKE, %ecx | |
73f7c32c UD |
519 | movl $1, %edx |
520 | ENTER_KERNEL | |
521 | subl $cond_nwaiters, %ebx | |
522 | movl $1, %edi | |
523 | ||
524 | 4: LOCK | |
71451de2 UD |
525 | #if cond_lock == 0 |
526 | subl $1, (%ebx) | |
527 | #else | |
67b78ef9 | 528 | subl $1, cond_lock(%ebx) |
71451de2 | 529 | #endif |
67b78ef9 UD |
530 | je 2f |
531 | ||
532 | #if cond_lock == 0 | |
533 | movl %ebx, %eax | |
534 | #else | |
535 | leal cond_lock(%ebx), %eax | |
536 | #endif | |
22502ea2 UD |
537 | #if (LLL_SHARED-LLL_PRIVATE) > 255 |
538 | xorl %ecx, %ecx | |
539 | #endif | |
540 | cmpl $-1, dep_mutex(%ebx) | |
541 | setne %cl | |
542 | subl $1, %ecx | |
543 | andl $(LLL_SHARED-LLL_PRIVATE), %ecx | |
544 | #if LLL_PRIVATE != 0 | |
545 | addl $LLL_PRIVATE, %ecx | |
546 | #endif | |
e51deae7 | 547 | call __lll_unlock_wake |
67b78ef9 UD |
548 | |
549 | /* Wake up all waiters to make sure no signal gets lost. */ | |
73f7c32c UD |
550 | 2: testl %edi, %edi |
551 | jnz 5f | |
552 | addl $cond_futex, %ebx | |
22502ea2 UD |
553 | #if FUTEX_PRIVATE_FLAG > 255 |
554 | xorl %ecx, %ecx | |
555 | #endif | |
556 | cmpl $-1, dep_mutex-cond_futex(%ebx) | |
557 | sete %cl | |
558 | subl $1, %ecx | |
559 | #ifdef __ASSUME_PRIVATE_FUTEX | |
560 | andl $FUTEX_PRIVATE_FLAG, %ecx | |
561 | #else | |
562 | andl %gs:PRIVATE_FUTEX, %ecx | |
563 | #endif | |
564 | addl $FUTEX_WAKE, %ecx | |
67b78ef9 UD |
565 | movl $SYS_futex, %eax |
566 | movl $0x7fffffff, %edx | |
567 | ENTER_KERNEL | |
568 | ||
0e3b5d6a SP |
569 | /* Lock the mutex only if we don't own it already. This only happens |
570 | in case of PI mutexes, if we got cancelled after a successful | |
571 | return of the futex syscall and before disabling async | |
572 | cancellation. */ | |
75956694 | 573 | 5: movl 24+FRAME_SIZE(%esp), %eax |
0e3b5d6a SP |
574 | movl MUTEX_KIND(%eax), %ebx |
575 | andl $(ROBUST_BIT|PI_BIT), %ebx | |
576 | cmpl $PI_BIT, %ebx | |
577 | jne 8f | |
578 | ||
579 | movl (%eax), %ebx | |
580 | andl $TID_MASK, %ebx | |
581 | cmpl %ebx, %gs:TID | |
9485a404 SP |
582 | jne 8f |
583 | /* We managed to get the lock. Fix it up before returning. */ | |
584 | call __pthread_mutex_cond_lock_adjust | |
585 | jmp 9f | |
0e3b5d6a SP |
586 | |
587 | 8: call __pthread_mutex_cond_lock | |
67b78ef9 | 588 | |
0e3b5d6a | 589 | 9: movl %esi, (%esp) |
67b78ef9 UD |
590 | .LcallUR: |
591 | call _Unwind_Resume | |
592 | hlt | |
593 | .LENDCODE: | |
f8c10bb4 | 594 | cfi_endproc |
7539c7ec | 595 | .size __condvar_w_cleanup, .-__condvar_w_cleanup |
67b78ef9 UD |
596 | |
597 | ||
598 | .section .gcc_except_table,"a",@progbits | |
599 | .LexceptSTART: | |
f8c10bb4 UD |
600 | .byte DW_EH_PE_omit # @LPStart format (omit) |
601 | .byte DW_EH_PE_omit # @TType format (omit) | |
602 | .byte DW_EH_PE_sdata4 # call-site format | |
67b78ef9 UD |
603 | # DW_EH_PE_sdata4 |
604 | .uleb128 .Lcstend-.Lcstbegin | |
605 | .Lcstbegin: | |
606 | .long .LcleanupSTART-.LSTARTCODE | |
55a051c9 SP |
607 | .long .Ladd_cond_futex_pi-.LcleanupSTART |
608 | .long __condvar_w_cleanup-.LSTARTCODE | |
609 | .uleb128 0 | |
610 | .long .Ladd_cond_futex_pi-.LSTARTCODE | |
611 | .long .Lsub_cond_futex_pi-.Ladd_cond_futex_pi | |
612 | .long __condvar_w_cleanup2-.LSTARTCODE | |
613 | .uleb128 0 | |
614 | .long .Lsub_cond_futex_pi-.LSTARTCODE | |
615 | .long .Ladd_cond_futex-.Lsub_cond_futex_pi | |
7539c7ec | 616 | .long __condvar_w_cleanup-.LSTARTCODE |
67b78ef9 | 617 | .uleb128 0 |
75fccede UD |
618 | .long .Ladd_cond_futex-.LSTARTCODE |
619 | .long .Lsub_cond_futex-.Ladd_cond_futex | |
7539c7ec | 620 | .long __condvar_w_cleanup2-.LSTARTCODE |
67b78ef9 | 621 | .uleb128 0 |
75fccede UD |
622 | .long .Lsub_cond_futex-.LSTARTCODE |
623 | .long .LcleanupEND-.Lsub_cond_futex | |
7539c7ec | 624 | .long __condvar_w_cleanup-.LSTARTCODE |
67b78ef9 UD |
625 | .uleb128 0 |
626 | .long .LcallUR-.LSTARTCODE | |
627 | .long .LENDCODE-.LcallUR | |
628 | .long 0 | |
629 | .uleb128 0 | |
630 | .Lcstend: | |
631 | ||
67b78ef9 UD |
632 | #ifdef SHARED |
633 | .hidden DW.ref.__gcc_personality_v0 | |
634 | .weak DW.ref.__gcc_personality_v0 | |
635 | .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits | |
636 | .align 4 | |
637 | .type DW.ref.__gcc_personality_v0, @object | |
638 | .size DW.ref.__gcc_personality_v0, 4 | |
639 | DW.ref.__gcc_personality_v0: | |
640 | .long __gcc_personality_v0 | |
641 | #endif |