Support requeueing for condvars using PI mutex. x86-64 only.
[glibc.git] / nptl / sysdeps / unix / sysv / linux / x86_64 / pthread_cond_timedwait.S
blobf81466e1a5cf995a52b911639f83485de9074775
1 /* Copyright (C) 2002-2005, 2007, 2009 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)
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         cmpq    $-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         movq    %rsi, dep_mutex(%rdi)
106 #ifndef __ASSUME_FUTEX_CLOCK_REALTIME
107 #  ifdef PIC
108         cmpl    $0, __have_futex_clock_realtime(%rip)
109 #  else
110         cmpl    $0, __have_futex_clock_realtime
111 #  endif
112         je      .Lreltmo
113 #endif
115         /* Get internal lock.  */
116         movl    $1, %esi
117         xorl    %eax, %eax
118         LOCK
119 #if cond_lock == 0
120         cmpxchgl %esi, (%rdi)
121 #else
122         cmpxchgl %esi, cond_lock(%rdi)
123 #endif
124         jnz     31f
126         /* Unlock the mutex.  */
127 32:     movq    16(%rsp), %rdi
128         xorl    %esi, %esi
129         callq   __pthread_mutex_unlock_usercnt
131         testl   %eax, %eax
132         jne     46f
134         movq    8(%rsp), %rdi
135         incq    total_seq(%rdi)
136         incl    cond_futex(%rdi)
137         addl    $(1 << nwaiters_shift), cond_nwaiters(%rdi)
139         /* Get and store current wakeup_seq value.  */
140         movq    8(%rsp), %rdi
141         movq    wakeup_seq(%rdi), %r9
142         movl    broadcast_seq(%rdi), %edx
143         movq    %r9, 24(%rsp)
144         movl    %edx, 4(%rsp)
146 38:     movl    cond_futex(%rdi), %r12d
148         /* Unlock.  */
149         LOCK
150 #if cond_lock == 0
151         decl    (%rdi)
152 #else
153         decl    cond_lock(%rdi)
154 #endif
155         jne     33f
157 .LcleanupSTART1:
158 34:     callq   __pthread_enable_asynccancel
159         movl    %eax, (%rsp)
160         movq    8(%rsp), %rdi
162         movq    %r13, %r10
163         cmpq    $-1, dep_mutex(%rdi)
164         movl    $FUTEX_WAIT_BITSET, %eax
165         movl    $(FUTEX_WAIT_BITSET|FUTEX_PRIVATE_FLAG), %esi
166         cmove   %eax, %esi
167         je      60f
169         movq    dep_mutex(%rdi), %r8
170         /* Requeue to a PI mutex if the PI bit is set.  */
171         testl   $PI_BIT, MUTEX_KIND(%r8)
172         je      60f
174         movl    $(FUTEX_WAIT_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %esi
175         xorl    %eax, %eax
176         /* The following only works like this because we only support
177            two clocks, represented using a single bit.  */
178         testl   $1, cond_nwaiters(%rdi)
179         movl    $FUTEX_CLOCK_REALTIME, %edx
180         cmove   %edx, %eax
181         orl     %eax, %esi
182         movq    %r12, %rdx
183         addq    $cond_futex, %rdi
184         movl    $SYS_futex, %eax
185         syscall
187         movl    $1, %r15d
188 #ifdef __ASSUME_REQUEUE_PI
189         jmp     62f
190 #else
191         cmpq    $-4095, %rax
192         jnae    62f
194         movl    $(FUTEX_WAIT_BITSET|FUTEX_PRIVATE_FLAG), %esi
195         subq    $cond_futex, %rdi
196 #endif
198 60:     xorl    %r15d, %r15d
199         xorl    %eax, %eax
200         /* The following only works like this because we only support
201            two clocks, represented using a single bit.  */
202         testl   $1, cond_nwaiters(%rdi)
203         movl    $FUTEX_CLOCK_REALTIME, %edx
204         movl    $0xffffffff, %r9d
205         cmove   %edx, %eax
206         orl     %eax, %esi
207         movq    %r12, %rdx
208         addq    $cond_futex, %rdi
209         movl    $SYS_futex, %eax
210         syscall
211 62:     movq    %rax, %r14
213         movl    (%rsp), %edi
214         callq   __pthread_disable_asynccancel
215 .LcleanupEND1:
217         /* Lock.  */
218         movq    8(%rsp), %rdi
219         movl    $1, %esi
220         xorl    %eax, %eax
221         LOCK
222 #if cond_lock == 0
223         cmpxchgl %esi, (%rdi)
224 #else
225         cmpxchgl %esi, cond_lock(%rdi)
226 #endif
227         jne     35f
229 36:     movl    broadcast_seq(%rdi), %edx
231         movq    woken_seq(%rdi), %rax
233         movq    wakeup_seq(%rdi), %r9
235         cmpl    4(%rsp), %edx
236         jne     53f
238         cmpq    24(%rsp), %r9
239         jbe     45f
241         cmpq    %rax, %r9
242         ja      39f
244 45:     cmpq    $-ETIMEDOUT, %r14
245         jne     38b
247 99:     incq    wakeup_seq(%rdi)
248         incl    cond_futex(%rdi)
249         movl    $ETIMEDOUT, %r14d
250         jmp     44f
252 53:     xorq    %r14, %r14
253         jmp     54f
255 39:     xorq    %r14, %r14
256 44:     incq    woken_seq(%rdi)
258 54:     subl    $(1 << nwaiters_shift), cond_nwaiters(%rdi)
260         /* Wake up a thread which wants to destroy the condvar object.  */
261         cmpq    $0xffffffffffffffff, total_seq(%rdi)
262         jne     55f
263         movl    cond_nwaiters(%rdi), %eax
264         andl    $~((1 << nwaiters_shift) - 1), %eax
265         jne     55f
267         addq    $cond_nwaiters, %rdi
268         cmpq    $-1, dep_mutex-cond_nwaiters(%rdi)
269         movl    $1, %edx
270 #ifdef __ASSUME_PRIVATE_FUTEX
271         movl    $FUTEX_WAKE, %eax
272         movl    $(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi
273         cmove   %eax, %esi
274 #else
275         movl    $0, %eax
276         movl    %fs:PRIVATE_FUTEX, %esi
277         cmove   %eax, %esi
278         orl     $FUTEX_WAKE, %esi
279 #endif
280         movl    $SYS_futex, %eax
281         syscall
282         subq    $cond_nwaiters, %rdi
284 55:     LOCK
285 #if cond_lock == 0
286         decl    (%rdi)
287 #else
288         decl    cond_lock(%rdi)
289 #endif
290         jne     40f
292         /* If requeue_pi is used the kernel performs the locking of the
293            mutex. */
294 41:     xorl    %eax, %eax
295         testl   %r15d, %r15d
296         jnz     63f
298         movq    16(%rsp), %rdi
299         callq   __pthread_mutex_cond_lock
301 63:     testq   %rax, %rax
302         cmoveq  %r14, %rax
304 48:     addq    $FRAME_SIZE, %rsp
305         cfi_adjust_cfa_offset(-FRAME_SIZE)
306         popq    %r15
307         cfi_adjust_cfa_offset(-8)
308         cfi_restore(%r15)
309         popq    %r14
310         cfi_adjust_cfa_offset(-8)
311         cfi_restore(%r14)
312         popq    %r13
313         cfi_adjust_cfa_offset(-8)
314         cfi_restore(%r13)
315         popq    %r12
316         cfi_adjust_cfa_offset(-8)
317         cfi_restore(%r12)
319         retq
321         /* Initial locking failed.  */
322 31:     cfi_adjust_cfa_offset(4 * 8 + FRAME_SIZE)
323         cfi_rel_offset(%r12, FRAME_SIZE + 24)
324         cfi_rel_offset(%r13, FRAME_SIZE + 16)
325         cfi_rel_offset(%r14, FRAME_SIZE + 8)
326         cfi_rel_offset(%r15, FRAME_SIZE)
327 #if cond_lock != 0
328         addq    $cond_lock, %rdi
329 #endif
330         cmpq    $-1, dep_mutex-cond_lock(%rdi)
331         movl    $LLL_PRIVATE, %eax
332         movl    $LLL_SHARED, %esi
333         cmovne  %eax, %esi
334         callq   __lll_lock_wait
335         jmp     32b
337         /* Unlock in loop requires wakeup.  */
339 #if cond_lock != 0
340         addq    $cond_lock, %rdi
341 #endif
342         cmpq    $-1, dep_mutex-cond_lock(%rdi)
343         movl    $LLL_PRIVATE, %eax
344         movl    $LLL_SHARED, %esi
345         cmovne  %eax, %esi
346         callq   __lll_unlock_wake
347         jmp     34b
349         /* Locking in loop failed.  */
351 #if cond_lock != 0
352         addq    $cond_lock, %rdi
353 #endif
354         cmpq    $-1, dep_mutex-cond_lock(%rdi)
355         movl    $LLL_PRIVATE, %eax
356         movl    $LLL_SHARED, %esi
357         cmovne  %eax, %esi
358         callq   __lll_lock_wait
359 #if cond_lock != 0
360         subq    $cond_lock, %rdi
361 #endif
362         jmp     36b
364         /* Unlock after loop requires wakeup.  */
366 #if cond_lock != 0
367         addq    $cond_lock, %rdi
368 #endif
369         cmpq    $-1, dep_mutex-cond_lock(%rdi)
370         movl    $LLL_PRIVATE, %eax
371         movl    $LLL_SHARED, %esi
372         cmovne  %eax, %esi
373         callq   __lll_unlock_wake
374         jmp     41b
376         /* The initial unlocking of the mutex failed.  */
377 46:     movq    8(%rsp), %rdi
378         movq    %rax, (%rsp)
379         LOCK
380 #if cond_lock == 0
381         decl    (%rdi)
382 #else
383         decl    cond_lock(%rdi)
384 #endif
385         jne     47f
387 #if cond_lock != 0
388         addq    $cond_lock, %rdi
389 #endif
390         cmpq    $-1, dep_mutex-cond_lock(%rdi)
391         movl    $LLL_PRIVATE, %eax
392         movl    $LLL_SHARED, %esi
393         cmovne  %eax, %esi
394         callq   __lll_unlock_wake
396 47:     movq    (%rsp), %rax
397         jmp     48b
400 #ifndef __ASSUME_FUTEX_CLOCK_REALTIME
401 .Lreltmo:
402         xorl    %r15d, %r15d
404         /* Get internal lock.  */
405         movl    $1, %esi
406         xorl    %eax, %eax
407         LOCK
408 # if cond_lock == 0
409         cmpxchgl %esi, (%rdi)
410 # else
411         cmpxchgl %esi, cond_lock(%rdi)
412 # endif
413         jnz     1f
415         /* Unlock the mutex.  */
416 2:      movq    16(%rsp), %rdi
417         xorl    %esi, %esi
418         callq   __pthread_mutex_unlock_usercnt
420         testl   %eax, %eax
421         jne     46b
423         movq    8(%rsp), %rdi
424         incq    total_seq(%rdi)
425         incl    cond_futex(%rdi)
426         addl    $(1 << nwaiters_shift), cond_nwaiters(%rdi)
428         /* Get and store current wakeup_seq value.  */
429         movq    8(%rsp), %rdi
430         movq    wakeup_seq(%rdi), %r9
431         movl    broadcast_seq(%rdi), %edx
432         movq    %r9, 24(%rsp)
433         movl    %edx, 4(%rsp)
435         /* Get the current time.  */
437 # ifdef __NR_clock_gettime
438         /* Get the clock number.  Note that the field in the condvar
439            structure stores the number minus 1.  */
440         movq    8(%rsp), %rdi
441         movl    cond_nwaiters(%rdi), %edi
442         andl    $((1 << nwaiters_shift) - 1), %edi
443         /* Only clocks 0 and 1 are allowed so far.  Both are handled in the
444            kernel.  */
445         leaq    32(%rsp), %rsi
446 #  ifdef SHARED
447         movq    __vdso_clock_gettime@GOTPCREL(%rip), %rax
448         movq    (%rax), %rax
449         PTR_DEMANGLE (%rax)
450         jz      26f
451         call    *%rax
452         jmp     27f
453 #  endif
454 26:     movl    $__NR_clock_gettime, %eax
455         syscall
457 #  ifndef __ASSUME_POSIX_TIMERS
458         cmpq    $-ENOSYS, %rax
459         je      19f
460 #  endif
462         /* Compute relative timeout.  */
463         movq    (%r13), %rcx
464         movq    8(%r13), %rdx
465         subq    32(%rsp), %rcx
466         subq    40(%rsp), %rdx
467 # else
468         leaq    24(%rsp), %rdi
469         xorl    %esi, %esi
470         movq    $VSYSCALL_ADDR_vgettimeofday, %rax
471         callq   *%rax
473         /* Compute relative timeout.  */
474         movq    40(%rsp), %rax
475         movl    $1000, %edx
476         mul     %rdx            /* Milli seconds to nano seconds.  */
477         movq    (%r13), %rcx
478         movq    8(%r13), %rdx
479         subq    32(%rsp), %rcx
480         subq    %rax, %rdx
481 # endif
482         jns     12f
483         addq    $1000000000, %rdx
484         decq    %rcx
485 12:     testq   %rcx, %rcx
486         movq    8(%rsp), %rdi
487         movq    $-ETIMEDOUT, %r14
488         js      6f
490         /* Store relative timeout.  */
491 21:     movq    %rcx, 32(%rsp)
492         movq    %rdx, 40(%rsp)
494         movl    cond_futex(%rdi), %r12d
496         /* Unlock.  */
497         LOCK
498 # if cond_lock == 0
499         decl    (%rdi)
500 # else
501         decl    cond_lock(%rdi)
502 # endif
503         jne     3f
505 .LcleanupSTART2:
506 4:      callq   __pthread_enable_asynccancel
507         movl    %eax, (%rsp)
508         movq    8(%rsp), %rdi
510         leaq    32(%rsp), %r10
511         cmpq    $-1, dep_mutex(%rdi)
512         movq    %r12, %rdx
513 # ifdef __ASSUME_PRIVATE_FUTEX
514         movl    $FUTEX_WAIT, %eax
515         movl    $(FUTEX_WAIT|FUTEX_PRIVATE_FLAG), %esi
516         cmove   %eax, %esi
517 # else
518         movl    $0, %eax
519         movl    %fs:PRIVATE_FUTEX, %esi
520         cmove   %eax, %esi
521 #  if FUTEX_WAIT != 0
522         orl     $FUTEX_WAIT, %esi
523 #  endif
524 # endif
525         addq    $cond_futex, %rdi
526         movl    $SYS_futex, %eax
527         syscall
528         movq    %rax, %r14
530         movl    (%rsp), %edi
531         callq   __pthread_disable_asynccancel
532 .LcleanupEND2:
534         /* Lock.  */
535         movq    8(%rsp), %rdi
536         movl    $1, %esi
537         xorl    %eax, %eax
538         LOCK
539 # if cond_lock == 0
540         cmpxchgl %esi, (%rdi)
541 # else
542         cmpxchgl %esi, cond_lock(%rdi)
543 # endif
544         jne     5f
546 6:      movl    broadcast_seq(%rdi), %edx
548         movq    woken_seq(%rdi), %rax
550         movq    wakeup_seq(%rdi), %r9
552         cmpl    4(%rsp), %edx
553         jne     53b
555         cmpq    24(%rsp), %r9
556         jbe     45b
558         cmpq    %rax, %r9
559         ja      39b
561         cmpq    $-ETIMEDOUT, %r14
562         jne     8b
564         jmp     99b
566         /* Initial locking failed.  */
568 # if cond_lock != 0
569         addq    $cond_lock, %rdi
570 # endif
571         cmpq    $-1, dep_mutex-cond_lock(%rdi)
572         movl    $LLL_PRIVATE, %eax
573         movl    $LLL_SHARED, %esi
574         cmovne  %eax, %esi
575         callq   __lll_lock_wait
576         jmp     2b
578         /* Unlock in loop requires wakeup.  */
580 # if cond_lock != 0
581         addq    $cond_lock, %rdi
582 # endif
583         cmpq    $-1, dep_mutex-cond_lock(%rdi)
584         movl    $LLL_PRIVATE, %eax
585         movl    $LLL_SHARED, %esi
586         cmovne  %eax, %esi
587         callq   __lll_unlock_wake
588         jmp     4b
590         /* Locking in loop failed.  */
592 # if cond_lock != 0
593         addq    $cond_lock, %rdi
594 # endif
595         cmpq    $-1, dep_mutex-cond_lock(%rdi)
596         movl    $LLL_PRIVATE, %eax
597         movl    $LLL_SHARED, %esi
598         cmovne  %eax, %esi
599         callq   __lll_lock_wait
600 # if cond_lock != 0
601         subq    $cond_lock, %rdi
602 # endif
603         jmp     6b
605 # if defined __NR_clock_gettime && !defined __ASSUME_POSIX_TIMERS
606         /* clock_gettime not available.  */
607 19:     leaq    32(%rsp), %rdi
608         xorl    %esi, %esi
609         movq    $VSYSCALL_ADDR_vgettimeofday, %rax
610         callq   *%rax
612         /* Compute relative timeout.  */
613         movq    40(%rsp), %rax
614         movl    $1000, %edx
615         mul     %rdx            /* Milli seconds to nano seconds.  */
616         movq    (%r13), %rcx
617         movq    8(%r13), %rdx
618         subq    32(%rsp), %rcx
619         subq    %rax, %rdx
620         jns     20f
621         addq    $1000000000, %rdx
622         decq    %rcx
623 20:     testq   %rcx, %rcx
624         movq    8(%rsp), %rdi
625         movq    $-ETIMEDOUT, %r14
626         js      6b
627         jmp     21b
628 # endif
629 #endif
630         .size   __pthread_cond_timedwait, .-__pthread_cond_timedwait
631 versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
632                   GLIBC_2_3_2)
635         .align  16
636         .type   __condvar_cleanup2, @function
637 __condvar_cleanup2:
638         /* Stack frame:
640            rsp + 72
641                     +--------------------------+
642            rsp + 64 | %r12                     |
643                     +--------------------------+
644            rsp + 56 | %r13                     |
645                     +--------------------------+
646            rsp + 48 | %r14                     |
647                     +--------------------------+
648            rsp + 24 | unused                   |
649                     +--------------------------+
650            rsp + 16 | mutex pointer            |
651                     +--------------------------+
652            rsp +  8 | condvar pointer          |
653                     +--------------------------+
654            rsp +  4 | old broadcast_seq value  |
655                     +--------------------------+
656            rsp +  0 | old cancellation mode    |
657                     +--------------------------+
658         */
660         movq    %rax, 24(%rsp)
662         /* Get internal lock.  */
663         movq    8(%rsp), %rdi
664         movl    $1, %esi
665         xorl    %eax, %eax
666         LOCK
667 #if cond_lock == 0
668         cmpxchgl %esi, (%rdi)
669 #else
670         cmpxchgl %esi, cond_lock(%rdi)
671 #endif
672         jz      1f
674 #if cond_lock != 0
675         addq    $cond_lock, %rdi
676 #endif
677         cmpq    $-1, dep_mutex-cond_lock(%rdi)
678         movl    $LLL_PRIVATE, %eax
679         movl    $LLL_SHARED, %esi
680         cmovne  %eax, %esi
681         callq   __lll_lock_wait
682 #if cond_lock != 0
683         subq    $cond_lock, %rdi
684 #endif
686 1:      movl    broadcast_seq(%rdi), %edx
687         cmpl    4(%rsp), %edx
688         jne     3f
690         /* We increment the wakeup_seq counter only if it is lower than
691            total_seq.  If this is not the case the thread was woken and
692            then canceled.  In this case we ignore the signal.  */
693         movq    total_seq(%rdi), %rax
694         cmpq    wakeup_seq(%rdi), %rax
695         jbe     6f
696         incq    wakeup_seq(%rdi)
697         incl    cond_futex(%rdi)
698 6:      incq    woken_seq(%rdi)
700 3:      subl    $(1 << nwaiters_shift), cond_nwaiters(%rdi)
702         /* Wake up a thread which wants to destroy the condvar object.  */
703         xorq    %r12, %r12
704         cmpq    $0xffffffffffffffff, total_seq(%rdi)
705         jne     4f
706         movl    cond_nwaiters(%rdi), %eax
707         andl    $~((1 << nwaiters_shift) - 1), %eax
708         jne     4f
710         cmpq    $-1, dep_mutex(%rdi)
711         leaq    cond_nwaiters(%rdi), %rdi
712         movl    $1, %edx
713 #ifdef __ASSUME_PRIVATE_FUTEX
714         movl    $FUTEX_WAKE, %eax
715         movl    $(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi
716         cmove   %eax, %esi
717 #else
718         movl    $0, %eax
719         movl    %fs:PRIVATE_FUTEX, %esi
720         cmove   %eax, %esi
721         orl     $FUTEX_WAKE, %esi
722 #endif
723         movl    $SYS_futex, %eax
724         syscall
725         subq    $cond_nwaiters, %rdi
726         movl    $1, %r12d
728 4:      LOCK
729 #if cond_lock == 0
730         decl    (%rdi)
731 #else
732         decl    cond_lock(%rdi)
733 #endif
734         je      2f
735 #if cond_lock != 0
736         addq    $cond_lock, %rdi
737 #endif
738         cmpq    $-1, dep_mutex-cond_lock(%rdi)
739         movl    $LLL_PRIVATE, %eax
740         movl    $LLL_SHARED, %esi
741         cmovne  %eax, %esi
742         callq   __lll_unlock_wake
744         /* Wake up all waiters to make sure no signal gets lost.  */
745 2:      testq   %r12, %r12
746         jnz     5f
747         addq    $cond_futex, %rdi
748         cmpq    $-1, dep_mutex-cond_futex(%rdi)
749         movl    $0x7fffffff, %edx
750 #ifdef __ASSUME_PRIVATE_FUTEX
751         movl    $FUTEX_WAKE, %eax
752         movl    $(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi
753         cmove   %eax, %esi
754 #else
755         movl    $0, %eax
756         movl    %fs:PRIVATE_FUTEX, %esi
757         cmove   %eax, %esi
758         orl     $FUTEX_WAKE, %esi
759 #endif
760         movl    $SYS_futex, %eax
761         syscall
763 5:      movq    16(%rsp), %rdi
764         callq   __pthread_mutex_cond_lock
766         movq    24(%rsp), %rdi
767         movq    FRAME_SIZE(%rsp), %r15
768         movq    FRAME_SIZE+8(%rsp), %r14
769         movq    FRAME_SIZE+16(%rsp), %r13
770         movq    FRAME_SIZE+24(%rsp), %r12
771 .LcallUR:
772         call    _Unwind_Resume@PLT
773         hlt
774 .LENDCODE:
775         cfi_endproc
776         .size   __condvar_cleanup2, .-__condvar_cleanup2
779         .section .gcc_except_table,"a",@progbits
780 .LexceptSTART:
781         .byte   DW_EH_PE_omit                   # @LPStart format
782         .byte   DW_EH_PE_omit                   # @TType format
783         .byte   DW_EH_PE_uleb128                # call-site format
784         .uleb128 .Lcstend-.Lcstbegin
785 .Lcstbegin:
786         .uleb128 .LcleanupSTART1-.LSTARTCODE
787         .uleb128 .LcleanupEND1-.LcleanupSTART1
788         .uleb128 __condvar_cleanup2-.LSTARTCODE
789         .uleb128  0
790 #ifndef __ASSUME_FUTEX_CLOCK_REALTIME
791         .uleb128 .LcleanupSTART2-.LSTARTCODE
792         .uleb128 .LcleanupEND2-.LcleanupSTART2
793         .uleb128 __condvar_cleanup2-.LSTARTCODE
794         .uleb128  0
795 #endif
796         .uleb128 .LcallUR-.LSTARTCODE
797         .uleb128 .LENDCODE-.LcallUR
798         .uleb128 0
799         .uleb128  0
800 .Lcstend:
803 #ifdef SHARED
804         .hidden DW.ref.__gcc_personality_v0
805         .weak   DW.ref.__gcc_personality_v0
806         .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
807         .align  8
808         .type   DW.ref.__gcc_personality_v0, @object
809         .size   DW.ref.__gcc_personality_v0, 8
810 DW.ref.__gcc_personality_v0:
811         .quad   __gcc_personality_v0
812 #endif