Update copyright notices with scripts/update-copyrights
[glibc.git] / nptl / sysdeps / unix / sysv / linux / x86_64 / pthread_cond_timedwait.S
blob0dc23405b07a451a4b28609eb2e2be35cc505862
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.
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.
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.
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/>.  */
19 #include <sysdep.h>
20 #include <shlib-compat.h>
21 #include <lowlevellock.h>
22 #include <lowlevelcond.h>
23 #include <pthread-pi-defines.h>
24 #include <pthread-errnos.h>
25 #include <stap-probe.h>
27 #include <kernel-features.h>
30         .text
33 /* int pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
34                                const struct timespec *abstime)  */
35         .globl  __pthread_cond_timedwait
36         .type   __pthread_cond_timedwait, @function
37         .align  16
38 __pthread_cond_timedwait:
39 .LSTARTCODE:
40         cfi_startproc
41 #ifdef SHARED
42         cfi_personality(DW_EH_PE_pcrel | DW_EH_PE_sdata4 | DW_EH_PE_indirect,
43                         DW.ref.__gcc_personality_v0)
44         cfi_lsda(DW_EH_PE_pcrel | DW_EH_PE_sdata4, .LexceptSTART)
45 #else
46         cfi_personality(DW_EH_PE_udata4, __gcc_personality_v0)
47         cfi_lsda(DW_EH_PE_udata4, .LexceptSTART)
48 #endif
50         pushq   %r12
51         cfi_adjust_cfa_offset(8)
52         cfi_rel_offset(%r12, 0)
53         pushq   %r13
54         cfi_adjust_cfa_offset(8)
55         cfi_rel_offset(%r13, 0)
56         pushq   %r14
57         cfi_adjust_cfa_offset(8)
58         cfi_rel_offset(%r14, 0)
59         pushq   %r15
60         cfi_adjust_cfa_offset(8)
61         cfi_rel_offset(%r15, 0)
62 #ifdef __ASSUME_FUTEX_CLOCK_REALTIME
63 # define FRAME_SIZE (32+8)
64 #else
65 # define FRAME_SIZE (48+8)
66 #endif
67         subq    $FRAME_SIZE, %rsp
68         cfi_adjust_cfa_offset(FRAME_SIZE)
69         cfi_remember_state
71         LIBC_PROBE (cond_timedwait, 3, %rdi, %rsi, %rdx)
73         cmpq    $1000000000, 8(%rdx)
74         movl    $EINVAL, %eax
75         jae     48f
77         /* Stack frame:
79            rsp + 48
80                     +--------------------------+
81            rsp + 32 | timeout value            |
82                     +--------------------------+
83            rsp + 24 | old wake_seq value       |
84                     +--------------------------+
85            rsp + 16 | mutex pointer            |
86                     +--------------------------+
87            rsp +  8 | condvar pointer          |
88                     +--------------------------+
89            rsp +  4 | old broadcast_seq value  |
90                     +--------------------------+
91            rsp +  0 | old cancellation mode    |
92                     +--------------------------+
93         */
95         LP_OP(cmp) $-1, dep_mutex(%rdi)
97         /* Prepare structure passed to cancellation handler.  */
98         movq    %rdi, 8(%rsp)
99         movq    %rsi, 16(%rsp)
100         movq    %rdx, %r13
102         je      22f
103         mov     %RSI_LP, dep_mutex(%rdi)
106         xorb    %r15b, %r15b
108 #ifndef __ASSUME_FUTEX_CLOCK_REALTIME
109 #  ifdef PIC
110         cmpl    $0, __have_futex_clock_realtime(%rip)
111 #  else
112         cmpl    $0, __have_futex_clock_realtime
113 #  endif
114         je      .Lreltmo
115 #endif
117         /* Get internal lock.  */
118         movl    $1, %esi
119         xorl    %eax, %eax
120         LOCK
121 #if cond_lock == 0
122         cmpxchgl %esi, (%rdi)
123 #else
124         cmpxchgl %esi, cond_lock(%rdi)
125 #endif
126         jnz     31f
128         /* Unlock the mutex.  */
129 32:     movq    16(%rsp), %rdi
130         xorl    %esi, %esi
131         callq   __pthread_mutex_unlock_usercnt
133         testl   %eax, %eax
134         jne     46f
136         movq    8(%rsp), %rdi
137         incq    total_seq(%rdi)
138         incl    cond_futex(%rdi)
139         addl    $(1 << nwaiters_shift), cond_nwaiters(%rdi)
141         /* Get and store current wakeup_seq value.  */
142         movq    8(%rsp), %rdi
143         movq    wakeup_seq(%rdi), %r9
144         movl    broadcast_seq(%rdi), %edx
145         movq    %r9, 24(%rsp)
146         movl    %edx, 4(%rsp)
148         cmpq    $0, (%r13)
149         movq    $-ETIMEDOUT, %r14
150         js      36f
152 38:     movl    cond_futex(%rdi), %r12d
154         /* Unlock.  */
155         LOCK
156 #if cond_lock == 0
157         decl    (%rdi)
158 #else
159         decl    cond_lock(%rdi)
160 #endif
161         jne     33f
163 .LcleanupSTART1:
164 34:     callq   __pthread_enable_asynccancel
165         movl    %eax, (%rsp)
167         movq    %r13, %r10
168         movl    $FUTEX_WAIT_BITSET, %esi
169         LP_OP(cmp) $-1, dep_mutex(%rdi)
170         je      60f
172         mov     dep_mutex(%rdi), %R8_LP
173         /* Requeue to a non-robust PI mutex if the PI bit is set and
174         the robust bit is not set.  */
175         movl    MUTEX_KIND(%r8), %eax
176         andl    $(ROBUST_BIT|PI_BIT), %eax
177         cmpl    $PI_BIT, %eax
178         jne     61f
180         movl    $(FUTEX_WAIT_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %esi
181         xorl    %eax, %eax
182         /* The following only works like this because we only support
183            two clocks, represented using a single bit.  */
184         testl   $1, cond_nwaiters(%rdi)
185         movl    $FUTEX_CLOCK_REALTIME, %edx
186         cmove   %edx, %eax
187         orl     %eax, %esi
188         movq    %r12, %rdx
189         addq    $cond_futex, %rdi
190         movl    $SYS_futex, %eax
191         syscall
193         cmpl    $0, %eax
194         sete    %r15b
196 #ifdef __ASSUME_REQUEUE_PI
197         jmp     62f
198 #else
199         je      62f
201         /* When a futex syscall with FUTEX_WAIT_REQUEUE_PI returns
202            successfully, it has already locked the mutex for us and the
203            pi_flag (%r15b) is set to denote that fact.  However, if another
204            thread changed the futex value before we entered the wait, the
205            syscall may return an EAGAIN and the mutex is not locked.  We go
206            ahead with a success anyway since later we look at the pi_flag to
207            decide if we got the mutex or not.  The sequence numbers then make
208            sure that only one of the threads actually wake up.  We retry using
209            normal FUTEX_WAIT only if the kernel returned ENOSYS, since normal
210            and PI futexes don't mix.
212            Note that we don't check for EAGAIN specifically; we assume that the
213            only other error the futex function could return is EAGAIN (barring
214            the ETIMEOUT of course, for the timeout case in futex) since
215            anything else would mean an error in our function.  It is too
216            expensive to do that check for every call (which is  quite common in
217            case of a large number of threads), so it has been skipped.  */
218         cmpl    $-ENOSYS, %eax
219         jne     62f
221         subq    $cond_futex, %rdi
222 #endif
224 61:     movl    $(FUTEX_WAIT_BITSET|FUTEX_PRIVATE_FLAG), %esi
225 60:     xorb    %r15b, %r15b
226         xorl    %eax, %eax
227         /* The following only works like this because we only support
228            two clocks, represented using a single bit.  */
229         testl   $1, cond_nwaiters(%rdi)
230         movl    $FUTEX_CLOCK_REALTIME, %edx
231         movl    $0xffffffff, %r9d
232         cmove   %edx, %eax
233         orl     %eax, %esi
234         movq    %r12, %rdx
235         addq    $cond_futex, %rdi
236         movl    $SYS_futex, %eax
237         syscall
238 62:     movq    %rax, %r14
240         movl    (%rsp), %edi
241         callq   __pthread_disable_asynccancel
242 .LcleanupEND1:
244         /* Lock.  */
245         movq    8(%rsp), %rdi
246         movl    $1, %esi
247         xorl    %eax, %eax
248         LOCK
249 #if cond_lock == 0
250         cmpxchgl %esi, (%rdi)
251 #else
252         cmpxchgl %esi, cond_lock(%rdi)
253 #endif
254         jne     35f
256 36:     movl    broadcast_seq(%rdi), %edx
258         movq    woken_seq(%rdi), %rax
260         movq    wakeup_seq(%rdi), %r9
262         cmpl    4(%rsp), %edx
263         jne     53f
265         cmpq    24(%rsp), %r9
266         jbe     45f
268         cmpq    %rax, %r9
269         ja      39f
271 45:     cmpq    $-ETIMEDOUT, %r14
272         je      99f
274         /* We need to go back to futex_wait.  If we're using requeue_pi, then
275            release the mutex we had acquired and go back.  */
276         test    %r15b, %r15b
277         jz      38b
279         /* Adjust the mutex values first and then unlock it.  The unlock
280            should always succeed or else the kernel did not lock the
281            mutex correctly.  */
282         movq    %r8, %rdi
283         callq   __pthread_mutex_cond_lock_adjust
284         xorl    %esi, %esi
285         callq   __pthread_mutex_unlock_usercnt
286         /* Reload cond_var.  */
287         movq    8(%rsp), %rdi
288         jmp     38b
290 99:     incq    wakeup_seq(%rdi)
291         incl    cond_futex(%rdi)
292         movl    $ETIMEDOUT, %r14d
293         jmp     44f
295 53:     xorq    %r14, %r14
296         jmp     54f
298 39:     xorq    %r14, %r14
299 44:     incq    woken_seq(%rdi)
301 54:     subl    $(1 << nwaiters_shift), cond_nwaiters(%rdi)
303         /* Wake up a thread which wants to destroy the condvar object.  */
304         cmpq    $0xffffffffffffffff, total_seq(%rdi)
305         jne     55f
306         movl    cond_nwaiters(%rdi), %eax
307         andl    $~((1 << nwaiters_shift) - 1), %eax
308         jne     55f
310         addq    $cond_nwaiters, %rdi
311         LP_OP(cmp) $-1, dep_mutex-cond_nwaiters(%rdi)
312         movl    $1, %edx
313 #ifdef __ASSUME_PRIVATE_FUTEX
314         movl    $FUTEX_WAKE, %eax
315         movl    $(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi
316         cmove   %eax, %esi
317 #else
318         movl    $0, %eax
319         movl    %fs:PRIVATE_FUTEX, %esi
320         cmove   %eax, %esi
321         orl     $FUTEX_WAKE, %esi
322 #endif
323         movl    $SYS_futex, %eax
324         syscall
325         subq    $cond_nwaiters, %rdi
327 55:     LOCK
328 #if cond_lock == 0
329         decl    (%rdi)
330 #else
331         decl    cond_lock(%rdi)
332 #endif
333         jne     40f
335         /* If requeue_pi is used the kernel performs the locking of the
336            mutex. */
337 41:     movq    16(%rsp), %rdi
338         testb   %r15b, %r15b
339         jnz     64f
341         callq   __pthread_mutex_cond_lock
343 63:     testq   %rax, %rax
344         cmoveq  %r14, %rax
346 48:     addq    $FRAME_SIZE, %rsp
347         cfi_adjust_cfa_offset(-FRAME_SIZE)
348         popq    %r15
349         cfi_adjust_cfa_offset(-8)
350         cfi_restore(%r15)
351         popq    %r14
352         cfi_adjust_cfa_offset(-8)
353         cfi_restore(%r14)
354         popq    %r13
355         cfi_adjust_cfa_offset(-8)
356         cfi_restore(%r13)
357         popq    %r12
358         cfi_adjust_cfa_offset(-8)
359         cfi_restore(%r12)
361         retq
363         cfi_restore_state
365 64:     callq   __pthread_mutex_cond_lock_adjust
366         movq    %r14, %rax
367         jmp     48b
369         /* Initial locking failed.  */
371 #if cond_lock != 0
372         addq    $cond_lock, %rdi
373 #endif
374         LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
375         movl    $LLL_PRIVATE, %eax
376         movl    $LLL_SHARED, %esi
377         cmovne  %eax, %esi
378         callq   __lll_lock_wait
379         jmp     32b
381         /* Unlock in loop requires wakeup.  */
383 #if cond_lock != 0
384         addq    $cond_lock, %rdi
385 #endif
386         LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
387         movl    $LLL_PRIVATE, %eax
388         movl    $LLL_SHARED, %esi
389         cmovne  %eax, %esi
390         callq   __lll_unlock_wake
391         jmp     34b
393         /* Locking in loop failed.  */
395 #if cond_lock != 0
396         addq    $cond_lock, %rdi
397 #endif
398         LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
399         movl    $LLL_PRIVATE, %eax
400         movl    $LLL_SHARED, %esi
401         cmovne  %eax, %esi
402         callq   __lll_lock_wait
403 #if cond_lock != 0
404         subq    $cond_lock, %rdi
405 #endif
406         jmp     36b
408         /* Unlock after loop requires wakeup.  */
410 #if cond_lock != 0
411         addq    $cond_lock, %rdi
412 #endif
413         LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
414         movl    $LLL_PRIVATE, %eax
415         movl    $LLL_SHARED, %esi
416         cmovne  %eax, %esi
417         callq   __lll_unlock_wake
418         jmp     41b
420         /* The initial unlocking of the mutex failed.  */
421 46:     movq    8(%rsp), %rdi
422         movq    %rax, (%rsp)
423         LOCK
424 #if cond_lock == 0
425         decl    (%rdi)
426 #else
427         decl    cond_lock(%rdi)
428 #endif
429         jne     47f
431 #if cond_lock != 0
432         addq    $cond_lock, %rdi
433 #endif
434         LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
435         movl    $LLL_PRIVATE, %eax
436         movl    $LLL_SHARED, %esi
437         cmovne  %eax, %esi
438         callq   __lll_unlock_wake
440 47:     movq    (%rsp), %rax
441         jmp     48b
444 #ifndef __ASSUME_FUTEX_CLOCK_REALTIME
445 .Lreltmo:
446         /* Get internal lock.  */
447         movl    $1, %esi
448         xorl    %eax, %eax
449         LOCK
450 # if cond_lock == 0
451         cmpxchgl %esi, (%rdi)
452 # else
453         cmpxchgl %esi, cond_lock(%rdi)
454 # endif
455         jnz     1f
457         /* Unlock the mutex.  */
458 2:      movq    16(%rsp), %rdi
459         xorl    %esi, %esi
460         callq   __pthread_mutex_unlock_usercnt
462         testl   %eax, %eax
463         jne     46b
465         movq    8(%rsp), %rdi
466         incq    total_seq(%rdi)
467         incl    cond_futex(%rdi)
468         addl    $(1 << nwaiters_shift), cond_nwaiters(%rdi)
470         /* Get and store current wakeup_seq value.  */
471         movq    8(%rsp), %rdi
472         movq    wakeup_seq(%rdi), %r9
473         movl    broadcast_seq(%rdi), %edx
474         movq    %r9, 24(%rsp)
475         movl    %edx, 4(%rsp)
477         /* Get the current time.  */
479 # ifdef __NR_clock_gettime
480         /* Get the clock number.  Note that the field in the condvar
481            structure stores the number minus 1.  */
482         movq    8(%rsp), %rdi
483         movl    cond_nwaiters(%rdi), %edi
484         andl    $((1 << nwaiters_shift) - 1), %edi
485         /* Only clocks 0 and 1 are allowed so far.  Both are handled in the
486            kernel.  */
487         leaq    32(%rsp), %rsi
488 #  ifdef SHARED
489         mov     __vdso_clock_gettime@GOTPCREL(%rip), %RAX_LP
490         mov     (%rax), %RAX_LP
491         PTR_DEMANGLE (%RAX_LP)
492         call    *%rax
493 #  else
494         movl    $__NR_clock_gettime, %eax
495         syscall
496 #  endif
498         /* Compute relative timeout.  */
499         movq    (%r13), %rcx
500         movq    8(%r13), %rdx
501         subq    32(%rsp), %rcx
502         subq    40(%rsp), %rdx
503 # else
504         leaq    24(%rsp), %rdi
505         xorl    %esi, %esi
506         /* This call works because we directly jump to a system call entry
507            which preserves all the registers.  */
508         call    JUMPTARGET(__gettimeofday)
510         /* Compute relative timeout.  */
511         movq    40(%rsp), %rax
512         movl    $1000, %edx
513         mul     %rdx            /* Milli seconds to nano seconds.  */
514         movq    (%r13), %rcx
515         movq    8(%r13), %rdx
516         subq    32(%rsp), %rcx
517         subq    %rax, %rdx
518 # endif
519         jns     12f
520         addq    $1000000000, %rdx
521         decq    %rcx
522 12:     testq   %rcx, %rcx
523         movq    8(%rsp), %rdi
524         movq    $-ETIMEDOUT, %r14
525         js      6f
527         /* Store relative timeout.  */
528 21:     movq    %rcx, 32(%rsp)
529         movq    %rdx, 40(%rsp)
531         movl    cond_futex(%rdi), %r12d
533         /* Unlock.  */
534         LOCK
535 # if cond_lock == 0
536         decl    (%rdi)
537 # else
538         decl    cond_lock(%rdi)
539 # endif
540         jne     3f
542 .LcleanupSTART2:
543 4:      callq   __pthread_enable_asynccancel
544         movl    %eax, (%rsp)
546         leaq    32(%rsp), %r10
547         LP_OP(cmp) $-1, dep_mutex(%rdi)
548         movq    %r12, %rdx
549 # ifdef __ASSUME_PRIVATE_FUTEX
550         movl    $FUTEX_WAIT, %eax
551         movl    $(FUTEX_WAIT|FUTEX_PRIVATE_FLAG), %esi
552         cmove   %eax, %esi
553 # else
554         movl    $0, %eax
555         movl    %fs:PRIVATE_FUTEX, %esi
556         cmove   %eax, %esi
557 #  if FUTEX_WAIT != 0
558         orl     $FUTEX_WAIT, %esi
559 #  endif
560 # endif
561         addq    $cond_futex, %rdi
562         movl    $SYS_futex, %eax
563         syscall
564         movq    %rax, %r14
566         movl    (%rsp), %edi
567         callq   __pthread_disable_asynccancel
568 .LcleanupEND2:
570         /* Lock.  */
571         movq    8(%rsp), %rdi
572         movl    $1, %esi
573         xorl    %eax, %eax
574         LOCK
575 # if cond_lock == 0
576         cmpxchgl %esi, (%rdi)
577 # else
578         cmpxchgl %esi, cond_lock(%rdi)
579 # endif
580         jne     5f
582 6:      movl    broadcast_seq(%rdi), %edx
584         movq    woken_seq(%rdi), %rax
586         movq    wakeup_seq(%rdi), %r9
588         cmpl    4(%rsp), %edx
589         jne     53b
591         cmpq    24(%rsp), %r9
592         jbe     15f
594         cmpq    %rax, %r9
595         ja      39b
597 15:     cmpq    $-ETIMEDOUT, %r14
598         jne     8b
600         jmp     99b
602         /* Initial locking failed.  */
604 # if cond_lock != 0
605         addq    $cond_lock, %rdi
606 # endif
607         LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
608         movl    $LLL_PRIVATE, %eax
609         movl    $LLL_SHARED, %esi
610         cmovne  %eax, %esi
611         callq   __lll_lock_wait
612         jmp     2b
614         /* Unlock in loop requires wakeup.  */
616 # if cond_lock != 0
617         addq    $cond_lock, %rdi
618 # endif
619         LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
620         movl    $LLL_PRIVATE, %eax
621         movl    $LLL_SHARED, %esi
622         cmovne  %eax, %esi
623         callq   __lll_unlock_wake
624         jmp     4b
626         /* Locking in loop failed.  */
628 # if cond_lock != 0
629         addq    $cond_lock, %rdi
630 # endif
631         LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
632         movl    $LLL_PRIVATE, %eax
633         movl    $LLL_SHARED, %esi
634         cmovne  %eax, %esi
635         callq   __lll_lock_wait
636 # if cond_lock != 0
637         subq    $cond_lock, %rdi
638 # endif
639         jmp     6b
640 #endif
641         .size   __pthread_cond_timedwait, .-__pthread_cond_timedwait
642 versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
643                   GLIBC_2_3_2)
646         .align  16
647         .type   __condvar_cleanup2, @function
648 __condvar_cleanup2:
649         /* Stack frame:
651            rsp + 72
652                     +--------------------------+
653            rsp + 64 | %r12                     |
654                     +--------------------------+
655            rsp + 56 | %r13                     |
656                     +--------------------------+
657            rsp + 48 | %r14                     |
658                     +--------------------------+
659            rsp + 24 | unused                   |
660                     +--------------------------+
661            rsp + 16 | mutex pointer            |
662                     +--------------------------+
663            rsp +  8 | condvar pointer          |
664                     +--------------------------+
665            rsp +  4 | old broadcast_seq value  |
666                     +--------------------------+
667            rsp +  0 | old cancellation mode    |
668                     +--------------------------+
669         */
671         movq    %rax, 24(%rsp)
673         /* Get internal lock.  */
674         movq    8(%rsp), %rdi
675         movl    $1, %esi
676         xorl    %eax, %eax
677         LOCK
678 #if cond_lock == 0
679         cmpxchgl %esi, (%rdi)
680 #else
681         cmpxchgl %esi, cond_lock(%rdi)
682 #endif
683         jz      1f
685 #if cond_lock != 0
686         addq    $cond_lock, %rdi
687 #endif
688         LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
689         movl    $LLL_PRIVATE, %eax
690         movl    $LLL_SHARED, %esi
691         cmovne  %eax, %esi
692         callq   __lll_lock_wait
693 #if cond_lock != 0
694         subq    $cond_lock, %rdi
695 #endif
697 1:      movl    broadcast_seq(%rdi), %edx
698         cmpl    4(%rsp), %edx
699         jne     3f
701         /* We increment the wakeup_seq counter only if it is lower than
702            total_seq.  If this is not the case the thread was woken and
703            then canceled.  In this case we ignore the signal.  */
704         movq    total_seq(%rdi), %rax
705         cmpq    wakeup_seq(%rdi), %rax
706         jbe     6f
707         incq    wakeup_seq(%rdi)
708         incl    cond_futex(%rdi)
709 6:      incq    woken_seq(%rdi)
711 3:      subl    $(1 << nwaiters_shift), cond_nwaiters(%rdi)
713         /* Wake up a thread which wants to destroy the condvar object.  */
714         xorq    %r12, %r12
715         cmpq    $0xffffffffffffffff, total_seq(%rdi)
716         jne     4f
717         movl    cond_nwaiters(%rdi), %eax
718         andl    $~((1 << nwaiters_shift) - 1), %eax
719         jne     4f
721         LP_OP(cmp) $-1, dep_mutex(%rdi)
722         leaq    cond_nwaiters(%rdi), %rdi
723         movl    $1, %edx
724 #ifdef __ASSUME_PRIVATE_FUTEX
725         movl    $FUTEX_WAKE, %eax
726         movl    $(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi
727         cmove   %eax, %esi
728 #else
729         movl    $0, %eax
730         movl    %fs:PRIVATE_FUTEX, %esi
731         cmove   %eax, %esi
732         orl     $FUTEX_WAKE, %esi
733 #endif
734         movl    $SYS_futex, %eax
735         syscall
736         subq    $cond_nwaiters, %rdi
737         movl    $1, %r12d
739 4:      LOCK
740 #if cond_lock == 0
741         decl    (%rdi)
742 #else
743         decl    cond_lock(%rdi)
744 #endif
745         je      2f
746 #if cond_lock != 0
747         addq    $cond_lock, %rdi
748 #endif
749         LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
750         movl    $LLL_PRIVATE, %eax
751         movl    $LLL_SHARED, %esi
752         cmovne  %eax, %esi
753         callq   __lll_unlock_wake
755         /* Wake up all waiters to make sure no signal gets lost.  */
756 2:      testq   %r12, %r12
757         jnz     5f
758         addq    $cond_futex, %rdi
759         LP_OP(cmp) $-1, dep_mutex-cond_futex(%rdi)
760         movl    $0x7fffffff, %edx
761 #ifdef __ASSUME_PRIVATE_FUTEX
762         movl    $FUTEX_WAKE, %eax
763         movl    $(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi
764         cmove   %eax, %esi
765 #else
766         movl    $0, %eax
767         movl    %fs:PRIVATE_FUTEX, %esi
768         cmove   %eax, %esi
769         orl     $FUTEX_WAKE, %esi
770 #endif
771         movl    $SYS_futex, %eax
772         syscall
774         /* Lock the mutex only if we don't own it already.  This only happens
775            in case of PI mutexes, if we got cancelled after a successful
776            return of the futex syscall and before disabling async
777            cancellation.  */
778 5:      movq    16(%rsp), %rdi
779         movl    MUTEX_KIND(%rdi), %eax
780         andl    $(ROBUST_BIT|PI_BIT), %eax
781         cmpl    $PI_BIT, %eax
782         jne     7f
784         movl    (%rdi), %eax
785         andl    $TID_MASK, %eax
786         cmpl    %eax, %fs:TID
787         jne     7f
788         /* We managed to get the lock.  Fix it up before returning.  */
789         callq   __pthread_mutex_cond_lock_adjust
790         jmp     8f
792 7:      callq   __pthread_mutex_cond_lock
794 8:      movq    24(%rsp), %rdi
795         movq    FRAME_SIZE(%rsp), %r15
796         movq    FRAME_SIZE+8(%rsp), %r14
797         movq    FRAME_SIZE+16(%rsp), %r13
798         movq    FRAME_SIZE+24(%rsp), %r12
799 .LcallUR:
800         call    _Unwind_Resume@PLT
801         hlt
802 .LENDCODE:
803         cfi_endproc
804         .size   __condvar_cleanup2, .-__condvar_cleanup2
807         .section .gcc_except_table,"a",@progbits
808 .LexceptSTART:
809         .byte   DW_EH_PE_omit                   # @LPStart format
810         .byte   DW_EH_PE_omit                   # @TType format
811         .byte   DW_EH_PE_uleb128                # call-site format
812         .uleb128 .Lcstend-.Lcstbegin
813 .Lcstbegin:
814         .uleb128 .LcleanupSTART1-.LSTARTCODE
815         .uleb128 .LcleanupEND1-.LcleanupSTART1
816         .uleb128 __condvar_cleanup2-.LSTARTCODE
817         .uleb128  0
818 #ifndef __ASSUME_FUTEX_CLOCK_REALTIME
819         .uleb128 .LcleanupSTART2-.LSTARTCODE
820         .uleb128 .LcleanupEND2-.LcleanupSTART2
821         .uleb128 __condvar_cleanup2-.LSTARTCODE
822         .uleb128  0
823 #endif
824         .uleb128 .LcallUR-.LSTARTCODE
825         .uleb128 .LENDCODE-.LcallUR
826         .uleb128 0
827         .uleb128  0
828 .Lcstend:
831 #ifdef SHARED
832         .hidden DW.ref.__gcc_personality_v0
833         .weak   DW.ref.__gcc_personality_v0
834         .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
835         .align  LP_SIZE
836         .type   DW.ref.__gcc_personality_v0, @object
837         .size   DW.ref.__gcc_personality_v0, LP_SIZE
838 DW.ref.__gcc_personality_v0:
839         ASM_ADDR __gcc_personality_v0
840 #endif