Work around kernel rejecting valid absolute timestamps
[glibc.git] / nptl / sysdeps / unix / sysv / linux / x86_64 / pthread_cond_timedwait.S
blobe6535fb9a790dee1b6f855bde47249ad1911dd71
1 /* Copyright (C) 2002-2005, 2007, 2009, 2010 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, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
20 #include <sysdep.h>
21 #include <shlib-compat.h>
22 #include <lowlevellock.h>
23 #include <lowlevelcond.h>
24 #include <pthread-pi-defines.h>
25 #include <pthread-errnos.h>
27 #include <kernel-features.h>
29 /* For the calculation see asm/vsyscall.h.  */
30 #define VSYSCALL_ADDR_vgettimeofday     0xffffffffff600000
33         .text
36 /* int pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
37                                const struct timespec *abstime)  */
38         .globl  __pthread_cond_timedwait
39         .type   __pthread_cond_timedwait, @function
40         .align  16
41 __pthread_cond_timedwait:
42 .LSTARTCODE:
43         cfi_startproc
44 #ifdef SHARED
45         cfi_personality(DW_EH_PE_pcrel | DW_EH_PE_sdata4 | DW_EH_PE_indirect,
46                         DW.ref.__gcc_personality_v0)
47         cfi_lsda(DW_EH_PE_pcrel | DW_EH_PE_sdata4, .LexceptSTART)
48 #else
49         cfi_personality(DW_EH_PE_udata4, __gcc_personality_v0)
50         cfi_lsda(DW_EH_PE_udata4, .LexceptSTART)
51 #endif
53         pushq   %r12
54         cfi_adjust_cfa_offset(8)
55         cfi_rel_offset(%r12, 0)
56         pushq   %r13
57         cfi_adjust_cfa_offset(8)
58         cfi_rel_offset(%r13, 0)
59         pushq   %r14
60         cfi_adjust_cfa_offset(8)
61         cfi_rel_offset(%r14, 0)
62         pushq   %r15
63         cfi_adjust_cfa_offset(8)
64         cfi_rel_offset(%r15, 0)
65 #ifdef __ASSUME_FUTEX_CLOCK_REALTIME
66 # define FRAME_SIZE 32
67 #else
68 # define FRAME_SIZE 48
69 #endif
70         subq    $FRAME_SIZE, %rsp
71         cfi_adjust_cfa_offset(FRAME_SIZE)
72         cfi_remember_state
74         cmpq    $1000000000, 8(%rdx)
75         movl    $EINVAL, %eax
76         jae     48f
78         /* Stack frame:
80            rsp + 48
81                     +--------------------------+
82            rsp + 32 | timeout value            |
83                     +--------------------------+
84            rsp + 24 | old wake_seq value       |
85                     +--------------------------+
86            rsp + 16 | mutex pointer            |
87                     +--------------------------+
88            rsp +  8 | condvar pointer          |
89                     +--------------------------+
90            rsp +  4 | old broadcast_seq value  |
91                     +--------------------------+
92            rsp +  0 | old cancellation mode    |
93                     +--------------------------+
94         */
96         cmpq    $-1, dep_mutex(%rdi)
98         /* Prepare structure passed to cancellation handler.  */
99         movq    %rdi, 8(%rsp)
100         movq    %rsi, 16(%rsp)
101         movq    %rdx, %r13
103         je      22f
104         movq    %rsi, dep_mutex(%rdi)
107 #ifndef __ASSUME_FUTEX_CLOCK_REALTIME
108 #  ifdef PIC
109         cmpl    $0, __have_futex_clock_realtime(%rip)
110 #  else
111         cmpl    $0, __have_futex_clock_realtime
112 #  endif
113         je      .Lreltmo
114 #endif
116         /* Get internal lock.  */
117         movl    $1, %esi
118         xorl    %eax, %eax
119         LOCK
120 #if cond_lock == 0
121         cmpxchgl %esi, (%rdi)
122 #else
123         cmpxchgl %esi, cond_lock(%rdi)
124 #endif
125         jnz     31f
127         /* Unlock the mutex.  */
128 32:     movq    16(%rsp), %rdi
129         xorl    %esi, %esi
130         callq   __pthread_mutex_unlock_usercnt
132         testl   %eax, %eax
133         jne     46f
135         movq    8(%rsp), %rdi
136         incq    total_seq(%rdi)
137         incl    cond_futex(%rdi)
138         addl    $(1 << nwaiters_shift), cond_nwaiters(%rdi)
140         /* Get and store current wakeup_seq value.  */
141         movq    8(%rsp), %rdi
142         movq    wakeup_seq(%rdi), %r9
143         movl    broadcast_seq(%rdi), %edx
144         movq    %r9, 24(%rsp)
145         movl    %edx, 4(%rsp)
147         cmpq    $0, (%r13)
148         movq    $-ETIMEDOUT, %r14
149         js      36f
151 38:     movl    cond_futex(%rdi), %r12d
153         /* Unlock.  */
154         LOCK
155 #if cond_lock == 0
156         decl    (%rdi)
157 #else
158         decl    cond_lock(%rdi)
159 #endif
160         jne     33f
162 .LcleanupSTART1:
163 34:     callq   __pthread_enable_asynccancel
164         movl    %eax, (%rsp)
166         movq    %r13, %r10
167         movl    $FUTEX_WAIT_BITSET, %esi
168         cmpq    $-1, dep_mutex(%rdi)
169         je      60f
171         movq    dep_mutex(%rdi), %r8
172         /* Requeue to a non-robust PI mutex if the PI bit is set and
173         the robust bit is not set.  */
174         movl    MUTEX_KIND(%r8), %eax
175         andl    $(ROBUST_BIT|PI_BIT), %eax
176         cmpl    $PI_BIT, %eax
177         jne     61f
179         movl    $(FUTEX_WAIT_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %esi
180         xorl    %eax, %eax
181         /* The following only works like this because we only support
182            two clocks, represented using a single bit.  */
183         testl   $1, cond_nwaiters(%rdi)
184         movl    $FUTEX_CLOCK_REALTIME, %edx
185         cmove   %edx, %eax
186         orl     %eax, %esi
187         movq    %r12, %rdx
188         addq    $cond_futex, %rdi
189         movl    $SYS_futex, %eax
190         syscall
192         movl    $1, %r15d
193 #ifdef __ASSUME_REQUEUE_PI
194         jmp     62f
195 #else
196         cmpq    $-4095, %rax
197         jnae    62f
199         subq    $cond_futex, %rdi
200 #endif
202 61:     movl    $(FUTEX_WAIT_BITSET|FUTEX_PRIVATE_FLAG), %esi
203 60:     xorl    %r15d, %r15d
204         xorl    %eax, %eax
205         /* The following only works like this because we only support
206            two clocks, represented using a single bit.  */
207         testl   $1, cond_nwaiters(%rdi)
208         movl    $FUTEX_CLOCK_REALTIME, %edx
209         movl    $0xffffffff, %r9d
210         cmove   %edx, %eax
211         orl     %eax, %esi
212         movq    %r12, %rdx
213         addq    $cond_futex, %rdi
214         movl    $SYS_futex, %eax
215         syscall
216 62:     movq    %rax, %r14
218         movl    (%rsp), %edi
219         callq   __pthread_disable_asynccancel
220 .LcleanupEND1:
222         /* Lock.  */
223         movq    8(%rsp), %rdi
224         movl    $1, %esi
225         xorl    %eax, %eax
226         LOCK
227 #if cond_lock == 0
228         cmpxchgl %esi, (%rdi)
229 #else
230         cmpxchgl %esi, cond_lock(%rdi)
231 #endif
232         jne     35f
234 36:     movl    broadcast_seq(%rdi), %edx
236         movq    woken_seq(%rdi), %rax
238         movq    wakeup_seq(%rdi), %r9
240         cmpl    4(%rsp), %edx
241         jne     53f
243         cmpq    24(%rsp), %r9
244         jbe     45f
246         cmpq    %rax, %r9
247         ja      39f
249 45:     cmpq    $-ETIMEDOUT, %r14
250         jne     38b
252 99:     incq    wakeup_seq(%rdi)
253         incl    cond_futex(%rdi)
254         movl    $ETIMEDOUT, %r14d
255         jmp     44f
257 53:     xorq    %r14, %r14
258         jmp     54f
260 39:     xorq    %r14, %r14
261 44:     incq    woken_seq(%rdi)
263 54:     subl    $(1 << nwaiters_shift), cond_nwaiters(%rdi)
265         /* Wake up a thread which wants to destroy the condvar object.  */
266         cmpq    $0xffffffffffffffff, total_seq(%rdi)
267         jne     55f
268         movl    cond_nwaiters(%rdi), %eax
269         andl    $~((1 << nwaiters_shift) - 1), %eax
270         jne     55f
272         addq    $cond_nwaiters, %rdi
273         cmpq    $-1, dep_mutex-cond_nwaiters(%rdi)
274         movl    $1, %edx
275 #ifdef __ASSUME_PRIVATE_FUTEX
276         movl    $FUTEX_WAKE, %eax
277         movl    $(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi
278         cmove   %eax, %esi
279 #else
280         movl    $0, %eax
281         movl    %fs:PRIVATE_FUTEX, %esi
282         cmove   %eax, %esi
283         orl     $FUTEX_WAKE, %esi
284 #endif
285         movl    $SYS_futex, %eax
286         syscall
287         subq    $cond_nwaiters, %rdi
289 55:     LOCK
290 #if cond_lock == 0
291         decl    (%rdi)
292 #else
293         decl    cond_lock(%rdi)
294 #endif
295         jne     40f
297         /* If requeue_pi is used the kernel performs the locking of the
298            mutex. */
299 41:     movq    16(%rsp), %rdi
300         testl   %r15d, %r15d
301         jnz     64f
303         callq   __pthread_mutex_cond_lock
305 63:     testq   %rax, %rax
306         cmoveq  %r14, %rax
308 48:     addq    $FRAME_SIZE, %rsp
309         cfi_adjust_cfa_offset(-FRAME_SIZE)
310         popq    %r15
311         cfi_adjust_cfa_offset(-8)
312         cfi_restore(%r15)
313         popq    %r14
314         cfi_adjust_cfa_offset(-8)
315         cfi_restore(%r14)
316         popq    %r13
317         cfi_adjust_cfa_offset(-8)
318         cfi_restore(%r13)
319         popq    %r12
320         cfi_adjust_cfa_offset(-8)
321         cfi_restore(%r12)
323         retq
325         cfi_restore_state
327 64:     callq   __pthread_mutex_cond_lock_adjust
328         movq    %r14, %rax
329         jmp     48b
331         /* Initial locking failed.  */
333 #if cond_lock != 0
334         addq    $cond_lock, %rdi
335 #endif
336         cmpq    $-1, dep_mutex-cond_lock(%rdi)
337         movl    $LLL_PRIVATE, %eax
338         movl    $LLL_SHARED, %esi
339         cmovne  %eax, %esi
340         callq   __lll_lock_wait
341         jmp     32b
343         /* Unlock in loop requires wakeup.  */
345 #if cond_lock != 0
346         addq    $cond_lock, %rdi
347 #endif
348         cmpq    $-1, dep_mutex-cond_lock(%rdi)
349         movl    $LLL_PRIVATE, %eax
350         movl    $LLL_SHARED, %esi
351         cmovne  %eax, %esi
352         callq   __lll_unlock_wake
353         jmp     34b
355         /* Locking in loop failed.  */
357 #if cond_lock != 0
358         addq    $cond_lock, %rdi
359 #endif
360         cmpq    $-1, dep_mutex-cond_lock(%rdi)
361         movl    $LLL_PRIVATE, %eax
362         movl    $LLL_SHARED, %esi
363         cmovne  %eax, %esi
364         callq   __lll_lock_wait
365 #if cond_lock != 0
366         subq    $cond_lock, %rdi
367 #endif
368         jmp     36b
370         /* Unlock after loop requires wakeup.  */
372 #if cond_lock != 0
373         addq    $cond_lock, %rdi
374 #endif
375         cmpq    $-1, dep_mutex-cond_lock(%rdi)
376         movl    $LLL_PRIVATE, %eax
377         movl    $LLL_SHARED, %esi
378         cmovne  %eax, %esi
379         callq   __lll_unlock_wake
380         jmp     41b
382         /* The initial unlocking of the mutex failed.  */
383 46:     movq    8(%rsp), %rdi
384         movq    %rax, (%rsp)
385         LOCK
386 #if cond_lock == 0
387         decl    (%rdi)
388 #else
389         decl    cond_lock(%rdi)
390 #endif
391         jne     47f
393 #if cond_lock != 0
394         addq    $cond_lock, %rdi
395 #endif
396         cmpq    $-1, dep_mutex-cond_lock(%rdi)
397         movl    $LLL_PRIVATE, %eax
398         movl    $LLL_SHARED, %esi
399         cmovne  %eax, %esi
400         callq   __lll_unlock_wake
402 47:     movq    (%rsp), %rax
403         jmp     48b
406 #ifndef __ASSUME_FUTEX_CLOCK_REALTIME
407 .Lreltmo:
408         xorl    %r15d, %r15d
410         /* Get internal lock.  */
411         movl    $1, %esi
412         xorl    %eax, %eax
413         LOCK
414 # if cond_lock == 0
415         cmpxchgl %esi, (%rdi)
416 # else
417         cmpxchgl %esi, cond_lock(%rdi)
418 # endif
419         jnz     1f
421         /* Unlock the mutex.  */
422 2:      movq    16(%rsp), %rdi
423         xorl    %esi, %esi
424         callq   __pthread_mutex_unlock_usercnt
426         testl   %eax, %eax
427         jne     46b
429         movq    8(%rsp), %rdi
430         incq    total_seq(%rdi)
431         incl    cond_futex(%rdi)
432         addl    $(1 << nwaiters_shift), cond_nwaiters(%rdi)
434         /* Get and store current wakeup_seq value.  */
435         movq    8(%rsp), %rdi
436         movq    wakeup_seq(%rdi), %r9
437         movl    broadcast_seq(%rdi), %edx
438         movq    %r9, 24(%rsp)
439         movl    %edx, 4(%rsp)
441         /* Get the current time.  */
443 # ifdef __NR_clock_gettime
444         /* Get the clock number.  Note that the field in the condvar
445            structure stores the number minus 1.  */
446         movq    8(%rsp), %rdi
447         movl    cond_nwaiters(%rdi), %edi
448         andl    $((1 << nwaiters_shift) - 1), %edi
449         /* Only clocks 0 and 1 are allowed so far.  Both are handled in the
450            kernel.  */
451         leaq    32(%rsp), %rsi
452 #  ifdef SHARED
453         movq    __vdso_clock_gettime@GOTPCREL(%rip), %rax
454         movq    (%rax), %rax
455         PTR_DEMANGLE (%rax)
456         jz      26f
457         call    *%rax
458         jmp     27f
459 #  endif
460 26:     movl    $__NR_clock_gettime, %eax
461         syscall
463 #  ifndef __ASSUME_POSIX_TIMERS
464         cmpq    $-ENOSYS, %rax
465         je      19f
466 #  endif
468         /* Compute relative timeout.  */
469         movq    (%r13), %rcx
470         movq    8(%r13), %rdx
471         subq    32(%rsp), %rcx
472         subq    40(%rsp), %rdx
473 # else
474         leaq    24(%rsp), %rdi
475         xorl    %esi, %esi
476         movq    $VSYSCALL_ADDR_vgettimeofday, %rax
477         callq   *%rax
479         /* Compute relative timeout.  */
480         movq    40(%rsp), %rax
481         movl    $1000, %edx
482         mul     %rdx            /* Milli seconds to nano seconds.  */
483         movq    (%r13), %rcx
484         movq    8(%r13), %rdx
485         subq    32(%rsp), %rcx
486         subq    %rax, %rdx
487 # endif
488         jns     12f
489         addq    $1000000000, %rdx
490         decq    %rcx
491 12:     testq   %rcx, %rcx
492         movq    8(%rsp), %rdi
493         movq    $-ETIMEDOUT, %r14
494         js      6f
496         /* Store relative timeout.  */
497 21:     movq    %rcx, 32(%rsp)
498         movq    %rdx, 40(%rsp)
500         movl    cond_futex(%rdi), %r12d
502         /* Unlock.  */
503         LOCK
504 # if cond_lock == 0
505         decl    (%rdi)
506 # else
507         decl    cond_lock(%rdi)
508 # endif
509         jne     3f
511 .LcleanupSTART2:
512 4:      callq   __pthread_enable_asynccancel
513         movl    %eax, (%rsp)
515         leaq    32(%rsp), %r10
516         cmpq    $-1, dep_mutex(%rdi)
517         movq    %r12, %rdx
518 # ifdef __ASSUME_PRIVATE_FUTEX
519         movl    $FUTEX_WAIT, %eax
520         movl    $(FUTEX_WAIT|FUTEX_PRIVATE_FLAG), %esi
521         cmove   %eax, %esi
522 # else
523         movl    $0, %eax
524         movl    %fs:PRIVATE_FUTEX, %esi
525         cmove   %eax, %esi
526 #  if FUTEX_WAIT != 0
527         orl     $FUTEX_WAIT, %esi
528 #  endif
529 # endif
530         addq    $cond_futex, %rdi
531         movl    $SYS_futex, %eax
532         syscall
533         movq    %rax, %r14
535         movl    (%rsp), %edi
536         callq   __pthread_disable_asynccancel
537 .LcleanupEND2:
539         /* Lock.  */
540         movq    8(%rsp), %rdi
541         movl    $1, %esi
542         xorl    %eax, %eax
543         LOCK
544 # if cond_lock == 0
545         cmpxchgl %esi, (%rdi)
546 # else
547         cmpxchgl %esi, cond_lock(%rdi)
548 # endif
549         jne     5f
551 6:      movl    broadcast_seq(%rdi), %edx
553         movq    woken_seq(%rdi), %rax
555         movq    wakeup_seq(%rdi), %r9
557         cmpl    4(%rsp), %edx
558         jne     53b
560         cmpq    24(%rsp), %r9
561         jbe     15f
563         cmpq    %rax, %r9
564         ja      39b
566 15:     cmpq    $-ETIMEDOUT, %r14
567         jne     8b
569         jmp     99b
571         /* Initial locking failed.  */
573 # if cond_lock != 0
574         addq    $cond_lock, %rdi
575 # endif
576         cmpq    $-1, dep_mutex-cond_lock(%rdi)
577         movl    $LLL_PRIVATE, %eax
578         movl    $LLL_SHARED, %esi
579         cmovne  %eax, %esi
580         callq   __lll_lock_wait
581         jmp     2b
583         /* Unlock in loop requires wakeup.  */
585 # if cond_lock != 0
586         addq    $cond_lock, %rdi
587 # endif
588         cmpq    $-1, dep_mutex-cond_lock(%rdi)
589         movl    $LLL_PRIVATE, %eax
590         movl    $LLL_SHARED, %esi
591         cmovne  %eax, %esi
592         callq   __lll_unlock_wake
593         jmp     4b
595         /* Locking in loop failed.  */
597 # if cond_lock != 0
598         addq    $cond_lock, %rdi
599 # endif
600         cmpq    $-1, dep_mutex-cond_lock(%rdi)
601         movl    $LLL_PRIVATE, %eax
602         movl    $LLL_SHARED, %esi
603         cmovne  %eax, %esi
604         callq   __lll_lock_wait
605 # if cond_lock != 0
606         subq    $cond_lock, %rdi
607 # endif
608         jmp     6b
610 # if defined __NR_clock_gettime && !defined __ASSUME_POSIX_TIMERS
611         /* clock_gettime not available.  */
612 19:     leaq    32(%rsp), %rdi
613         xorl    %esi, %esi
614         movq    $VSYSCALL_ADDR_vgettimeofday, %rax
615         callq   *%rax
617         /* Compute relative timeout.  */
618         movq    40(%rsp), %rax
619         movl    $1000, %edx
620         mul     %rdx            /* Milli seconds to nano seconds.  */
621         movq    (%r13), %rcx
622         movq    8(%r13), %rdx
623         subq    32(%rsp), %rcx
624         subq    %rax, %rdx
625         jns     20f
626         addq    $1000000000, %rdx
627         decq    %rcx
628 20:     testq   %rcx, %rcx
629         movq    8(%rsp), %rdi
630         movq    $-ETIMEDOUT, %r14
631         js      6b
632         jmp     21b
633 # endif
634 #endif
635         .size   __pthread_cond_timedwait, .-__pthread_cond_timedwait
636 versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
637                   GLIBC_2_3_2)
640         .align  16
641         .type   __condvar_cleanup2, @function
642 __condvar_cleanup2:
643         /* Stack frame:
645            rsp + 72
646                     +--------------------------+
647            rsp + 64 | %r12                     |
648                     +--------------------------+
649            rsp + 56 | %r13                     |
650                     +--------------------------+
651            rsp + 48 | %r14                     |
652                     +--------------------------+
653            rsp + 24 | unused                   |
654                     +--------------------------+
655            rsp + 16 | mutex pointer            |
656                     +--------------------------+
657            rsp +  8 | condvar pointer          |
658                     +--------------------------+
659            rsp +  4 | old broadcast_seq value  |
660                     +--------------------------+
661            rsp +  0 | old cancellation mode    |
662                     +--------------------------+
663         */
665         movq    %rax, 24(%rsp)
667         /* Get internal lock.  */
668         movq    8(%rsp), %rdi
669         movl    $1, %esi
670         xorl    %eax, %eax
671         LOCK
672 #if cond_lock == 0
673         cmpxchgl %esi, (%rdi)
674 #else
675         cmpxchgl %esi, cond_lock(%rdi)
676 #endif
677         jz      1f
679 #if cond_lock != 0
680         addq    $cond_lock, %rdi
681 #endif
682         cmpq    $-1, dep_mutex-cond_lock(%rdi)
683         movl    $LLL_PRIVATE, %eax
684         movl    $LLL_SHARED, %esi
685         cmovne  %eax, %esi
686         callq   __lll_lock_wait
687 #if cond_lock != 0
688         subq    $cond_lock, %rdi
689 #endif
691 1:      movl    broadcast_seq(%rdi), %edx
692         cmpl    4(%rsp), %edx
693         jne     3f
695         /* We increment the wakeup_seq counter only if it is lower than
696            total_seq.  If this is not the case the thread was woken and
697            then canceled.  In this case we ignore the signal.  */
698         movq    total_seq(%rdi), %rax
699         cmpq    wakeup_seq(%rdi), %rax
700         jbe     6f
701         incq    wakeup_seq(%rdi)
702         incl    cond_futex(%rdi)
703 6:      incq    woken_seq(%rdi)
705 3:      subl    $(1 << nwaiters_shift), cond_nwaiters(%rdi)
707         /* Wake up a thread which wants to destroy the condvar object.  */
708         xorq    %r12, %r12
709         cmpq    $0xffffffffffffffff, total_seq(%rdi)
710         jne     4f
711         movl    cond_nwaiters(%rdi), %eax
712         andl    $~((1 << nwaiters_shift) - 1), %eax
713         jne     4f
715         cmpq    $-1, dep_mutex(%rdi)
716         leaq    cond_nwaiters(%rdi), %rdi
717         movl    $1, %edx
718 #ifdef __ASSUME_PRIVATE_FUTEX
719         movl    $FUTEX_WAKE, %eax
720         movl    $(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi
721         cmove   %eax, %esi
722 #else
723         movl    $0, %eax
724         movl    %fs:PRIVATE_FUTEX, %esi
725         cmove   %eax, %esi
726         orl     $FUTEX_WAKE, %esi
727 #endif
728         movl    $SYS_futex, %eax
729         syscall
730         subq    $cond_nwaiters, %rdi
731         movl    $1, %r12d
733 4:      LOCK
734 #if cond_lock == 0
735         decl    (%rdi)
736 #else
737         decl    cond_lock(%rdi)
738 #endif
739         je      2f
740 #if cond_lock != 0
741         addq    $cond_lock, %rdi
742 #endif
743         cmpq    $-1, dep_mutex-cond_lock(%rdi)
744         movl    $LLL_PRIVATE, %eax
745         movl    $LLL_SHARED, %esi
746         cmovne  %eax, %esi
747         callq   __lll_unlock_wake
749         /* Wake up all waiters to make sure no signal gets lost.  */
750 2:      testq   %r12, %r12
751         jnz     5f
752         addq    $cond_futex, %rdi
753         cmpq    $-1, dep_mutex-cond_futex(%rdi)
754         movl    $0x7fffffff, %edx
755 #ifdef __ASSUME_PRIVATE_FUTEX
756         movl    $FUTEX_WAKE, %eax
757         movl    $(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi
758         cmove   %eax, %esi
759 #else
760         movl    $0, %eax
761         movl    %fs:PRIVATE_FUTEX, %esi
762         cmove   %eax, %esi
763         orl     $FUTEX_WAKE, %esi
764 #endif
765         movl    $SYS_futex, %eax
766         syscall
768 5:      movq    16(%rsp), %rdi
769         callq   __pthread_mutex_cond_lock
771         movq    24(%rsp), %rdi
772         movq    FRAME_SIZE(%rsp), %r15
773         movq    FRAME_SIZE+8(%rsp), %r14
774         movq    FRAME_SIZE+16(%rsp), %r13
775         movq    FRAME_SIZE+24(%rsp), %r12
776 .LcallUR:
777         call    _Unwind_Resume@PLT
778         hlt
779 .LENDCODE:
780         cfi_endproc
781         .size   __condvar_cleanup2, .-__condvar_cleanup2
784         .section .gcc_except_table,"a",@progbits
785 .LexceptSTART:
786         .byte   DW_EH_PE_omit                   # @LPStart format
787         .byte   DW_EH_PE_omit                   # @TType format
788         .byte   DW_EH_PE_uleb128                # call-site format
789         .uleb128 .Lcstend-.Lcstbegin
790 .Lcstbegin:
791         .uleb128 .LcleanupSTART1-.LSTARTCODE
792         .uleb128 .LcleanupEND1-.LcleanupSTART1
793         .uleb128 __condvar_cleanup2-.LSTARTCODE
794         .uleb128  0
795 #ifndef __ASSUME_FUTEX_CLOCK_REALTIME
796         .uleb128 .LcleanupSTART2-.LSTARTCODE
797         .uleb128 .LcleanupEND2-.LcleanupSTART2
798         .uleb128 __condvar_cleanup2-.LSTARTCODE
799         .uleb128  0
800 #endif
801         .uleb128 .LcallUR-.LSTARTCODE
802         .uleb128 .LENDCODE-.LcallUR
803         .uleb128 0
804         .uleb128  0
805 .Lcstend:
808 #ifdef SHARED
809         .hidden DW.ref.__gcc_personality_v0
810         .weak   DW.ref.__gcc_personality_v0
811         .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
812         .align  8
813         .type   DW.ref.__gcc_personality_v0, @object
814         .size   DW.ref.__gcc_personality_v0, 8
815 DW.ref.__gcc_personality_v0:
816         .quad   __gcc_personality_v0
817 #endif