Update copyright dates with scripts/update-copyrights.
[glibc.git] / sysdeps / unix / sysv / linux / i386 / i486 / pthread_cond_timedwait.S
blob130c090c9cc7b6180ab8d76657f0a072222a6fb2
1 /* Copyright (C) 2002-2015 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-errnos.h>
24 #include <pthread-pi-defines.h>
25 #include <kernel-features.h>
26 #include <stap-probe.h>
28         .text
30 /* int pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
31                                const struct timespec *abstime)  */
32         .globl  __pthread_cond_timedwait
33         .type   __pthread_cond_timedwait, @function
34         .align  16
35 __pthread_cond_timedwait:
36 .LSTARTCODE:
37         cfi_startproc
38 #ifdef SHARED
39         cfi_personality(DW_EH_PE_pcrel | DW_EH_PE_sdata4 | DW_EH_PE_indirect,
40                         DW.ref.__gcc_personality_v0)
41         cfi_lsda(DW_EH_PE_pcrel | DW_EH_PE_sdata4, .LexceptSTART)
42 #else
43         cfi_personality(DW_EH_PE_udata4, __gcc_personality_v0)
44         cfi_lsda(DW_EH_PE_udata4, .LexceptSTART)
45 #endif
47         pushl   %ebp
48         cfi_adjust_cfa_offset(4)
49         cfi_rel_offset(%ebp, 0)
50         pushl   %edi
51         cfi_adjust_cfa_offset(4)
52         cfi_rel_offset(%edi, 0)
53         pushl   %esi
54         cfi_adjust_cfa_offset(4)
55         cfi_rel_offset(%esi, 0)
56         pushl   %ebx
57         cfi_adjust_cfa_offset(4)
58         cfi_rel_offset(%ebx, 0)
60         movl    20(%esp), %ebx
61         movl    28(%esp), %ebp
63         LIBC_PROBE (cond_timedwait, 3, %ebx, 24(%esp), %ebp)
65         cmpl    $1000000000, 4(%ebp)
66         movl    $EINVAL, %eax
67         jae     18f
69         /* Stack frame:
71            esp + 32
72                     +--------------------------+
73            esp + 24 | timeout value            |
74                     +--------------------------+
75            esp + 20 | futex pointer            |
76                     +--------------------------+
77            esp + 16 | pi-requeued flag         |
78                     +--------------------------+
79            esp + 12 | old broadcast_seq value  |
80                     +--------------------------+
81            esp +  4 | old wake_seq value       |
82                     +--------------------------+
83            esp +  0 | old cancellation mode    |
84                     +--------------------------+
85         */
87 #ifndef __ASSUME_FUTEX_CLOCK_REALTIME
88 # ifdef PIC
89         LOAD_PIC_REG (cx)
90         cmpl    $0, __have_futex_clock_realtime@GOTOFF(%ecx)
91 # else
92         cmpl    $0, __have_futex_clock_realtime
93 # endif
94         je      .Lreltmo
95 #endif
97         /* Get internal lock.  */
98         movl    $1, %edx
99         xorl    %eax, %eax
100         LOCK
101 #if cond_lock == 0
102         cmpxchgl %edx, (%ebx)
103 #else
104         cmpxchgl %edx, cond_lock(%ebx)
105 #endif
106         jnz     1f
108         /* Store the reference to the mutex.  If there is already a
109            different value in there this is a bad user bug.  */
110 2:      cmpl    $-1, dep_mutex(%ebx)
111         movl    24(%esp), %eax
112         je      17f
113         movl    %eax, dep_mutex(%ebx)
115         /* Unlock the mutex.  */
116 17:     xorl    %edx, %edx
117         call    __pthread_mutex_unlock_usercnt
119         testl   %eax, %eax
120         jne     16f
122         addl    $1, total_seq(%ebx)
123         adcl    $0, total_seq+4(%ebx)
124         addl    $1, cond_futex(%ebx)
125         addl    $(1 << nwaiters_shift), cond_nwaiters(%ebx)
127 #ifdef __ASSUME_FUTEX_CLOCK_REALTIME
128 # define FRAME_SIZE 24
129 #else
130 # define FRAME_SIZE 32
131 #endif
132         subl    $FRAME_SIZE, %esp
133         cfi_adjust_cfa_offset(FRAME_SIZE)
134         cfi_remember_state
136         /* Get and store current wakeup_seq value.  */
137         movl    wakeup_seq(%ebx), %edi
138         movl    wakeup_seq+4(%ebx), %edx
139         movl    broadcast_seq(%ebx), %eax
140         movl    %edi, 4(%esp)
141         movl    %edx, 8(%esp)
142         movl    %eax, 12(%esp)
144         /* Reset the pi-requeued flag.  */
145         movl    $0, 16(%esp)
147         cmpl    $0, (%ebp)
148         movl    $-ETIMEDOUT, %esi
149         js      6f
151 8:      movl    cond_futex(%ebx), %edi
152         movl    %edi, 20(%esp)
154         /* Unlock.  */
155         LOCK
156 #if cond_lock == 0
157         subl    $1, (%ebx)
158 #else
159         subl    $1, cond_lock(%ebx)
160 #endif
161         jne     3f
163 .LcleanupSTART:
164 4:      call    __pthread_enable_asynccancel
165         movl    %eax, (%esp)
167         leal    (%ebp), %esi
168 #if FUTEX_PRIVATE_FLAG > 255
169         xorl    %ecx, %ecx
170 #endif
171         cmpl    $-1, dep_mutex(%ebx)
172         sete    %cl
173         je      40f
175         movl    dep_mutex(%ebx), %edi
176         /* Requeue to a non-robust PI mutex if the PI bit is set and
177            the robust bit is not set.  */
178         movl    MUTEX_KIND(%edi), %eax
179         andl    $(ROBUST_BIT|PI_BIT), %eax
180         cmpl    $PI_BIT, %eax
181         jne     40f
183         movl    $(FUTEX_WAIT_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %ecx
184         /* The following only works like this because we only support
185            two clocks, represented using a single bit.  */
186         testl   $1, cond_nwaiters(%ebx)
187         /* XXX Need to implement using sete instead of a jump.  */
188         jne     42f
189         orl     $FUTEX_CLOCK_REALTIME, %ecx
191 42:     movl    20(%esp), %edx
192         addl    $cond_futex, %ebx
193 .Ladd_cond_futex_pi:
194         movl    $SYS_futex, %eax
195         ENTER_KERNEL
196         subl    $cond_futex, %ebx
197 .Lsub_cond_futex_pi:
198         movl    %eax, %esi
199         /* Set the pi-requeued flag only if the kernel has returned 0. The
200            kernel does not hold the mutex on ETIMEDOUT or any other error.  */
201         cmpl    $0, %eax
202         sete    16(%esp)
203         je      41f
205         /* When a futex syscall with FUTEX_WAIT_REQUEUE_PI returns
206            successfully, it has already locked the mutex for us and the
207            pi_flag (16(%esp)) is set to denote that fact.  However, if another
208            thread changed the futex value before we entered the wait, the
209            syscall may return an EAGAIN and the mutex is not locked.  We go
210            ahead with a success anyway since later we look at the pi_flag to
211            decide if we got the mutex or not.  The sequence numbers then make
212            sure that only one of the threads actually wake up.  We retry using
213            normal FUTEX_WAIT only if the kernel returned ENOSYS, since normal
214            and PI futexes don't mix.
216            Note that we don't check for EAGAIN specifically; we assume that the
217            only other error the futex function could return is EAGAIN (barring
218            the ETIMEOUT of course, for the timeout case in futex) since
219            anything else would mean an error in our function.  It is too
220            expensive to do that check for every call (which is  quite common in
221            case of a large number of threads), so it has been skipped.  */
222         cmpl    $-ENOSYS, %eax
223         jne     41f
224         xorl    %ecx, %ecx
226 40:     subl    $1, %ecx
227         movl    $0, 16(%esp)
228 #ifdef __ASSUME_PRIVATE_FUTEX
229         andl    $FUTEX_PRIVATE_FLAG, %ecx
230 #else
231         andl    %gs:PRIVATE_FUTEX, %ecx
232 #endif
233         addl    $FUTEX_WAIT_BITSET, %ecx
234         /* The following only works like this because we only support
235            two clocks, represented using a single bit.  */
236         testl   $1, cond_nwaiters(%ebx)
237         jne     30f
238         orl     $FUTEX_CLOCK_REALTIME, %ecx
240         movl    20(%esp), %edx
241         movl    $0xffffffff, %ebp
242         addl    $cond_futex, %ebx
243 .Ladd_cond_futex:
244         movl    $SYS_futex, %eax
245         ENTER_KERNEL
246         subl    $cond_futex, %ebx
247 .Lsub_cond_futex:
248         movl    28+FRAME_SIZE(%esp), %ebp
249         movl    %eax, %esi
251 41:     movl    (%esp), %eax
252         call    __pthread_disable_asynccancel
253 .LcleanupEND:
255         /* Lock.  */
256         movl    $1, %edx
257         xorl    %eax, %eax
258         LOCK
259 #if cond_lock == 0
260         cmpxchgl %edx, (%ebx)
261 #else
262         cmpxchgl %edx, cond_lock(%ebx)
263 #endif
264         jnz     5f
266 6:      movl    broadcast_seq(%ebx), %eax
267         cmpl    12(%esp), %eax
268         jne     23f
270         movl    woken_seq(%ebx), %eax
271         movl    woken_seq+4(%ebx), %ecx
273         movl    wakeup_seq(%ebx), %edi
274         movl    wakeup_seq+4(%ebx), %edx
276         cmpl    8(%esp), %edx
277         jne     7f
278         cmpl    4(%esp), %edi
279         je      15f
281 7:      cmpl    %ecx, %edx
282         jne     9f
283         cmp     %eax, %edi
284         jne     9f
286 15:     cmpl    $-ETIMEDOUT, %esi
287         je      28f
289         /* We need to go back to futex_wait.  If we're using requeue_pi, then
290            release the mutex we had acquired and go back.  */
291         movl    16(%esp), %edx
292         test    %edx, %edx
293         jz      8b
295         /* Adjust the mutex values first and then unlock it.  The unlock
296            should always succeed or else the kernel did not lock the mutex
297            correctly.  */
298         movl    dep_mutex(%ebx), %eax
299         call    __pthread_mutex_cond_lock_adjust
300         xorl    %edx, %edx
301         call    __pthread_mutex_unlock_usercnt
302         jmp     8b
304 28:     addl    $1, wakeup_seq(%ebx)
305         adcl    $0, wakeup_seq+4(%ebx)
306         addl    $1, cond_futex(%ebx)
307         movl    $ETIMEDOUT, %esi
308         jmp     14f
310 23:     xorl    %esi, %esi
311         jmp     24f
313 9:      xorl    %esi, %esi
314 14:     addl    $1, woken_seq(%ebx)
315         adcl    $0, woken_seq+4(%ebx)
317 24:     subl    $(1 << nwaiters_shift), cond_nwaiters(%ebx)
319         /* Wake up a thread which wants to destroy the condvar object.  */
320         movl    total_seq(%ebx), %eax
321         andl    total_seq+4(%ebx), %eax
322         cmpl    $0xffffffff, %eax
323         jne     25f
324         movl    cond_nwaiters(%ebx), %eax
325         andl    $~((1 << nwaiters_shift) - 1), %eax
326         jne     25f
328         addl    $cond_nwaiters, %ebx
329         movl    $SYS_futex, %eax
330 #if FUTEX_PRIVATE_FLAG > 255
331         xorl    %ecx, %ecx
332 #endif
333         cmpl    $-1, dep_mutex-cond_nwaiters(%ebx)
334         sete    %cl
335         subl    $1, %ecx
336 #ifdef __ASSUME_PRIVATE_FUTEX
337         andl    $FUTEX_PRIVATE_FLAG, %ecx
338 #else
339         andl    %gs:PRIVATE_FUTEX, %ecx
340 #endif
341         addl    $FUTEX_WAKE, %ecx
342         movl    $1, %edx
343         ENTER_KERNEL
344         subl    $cond_nwaiters, %ebx
346 25:     LOCK
347 #if cond_lock == 0
348         subl    $1, (%ebx)
349 #else
350         subl    $1, cond_lock(%ebx)
351 #endif
352         jne     10f
354 11:     movl    24+FRAME_SIZE(%esp), %eax
355         /* With requeue_pi, the mutex lock is held in the kernel.  */
356         movl    16(%esp), %ecx
357         testl   %ecx, %ecx
358         jnz     27f
360         call    __pthread_mutex_cond_lock
361 26:     addl    $FRAME_SIZE, %esp
362         cfi_adjust_cfa_offset(-FRAME_SIZE)
364         /* We return the result of the mutex_lock operation if it failed.  */
365         testl   %eax, %eax
366 #ifdef HAVE_CMOV
367         cmovel  %esi, %eax
368 #else
369         jne     22f
370         movl    %esi, %eax
372 #endif
374 18:     popl    %ebx
375         cfi_adjust_cfa_offset(-4)
376         cfi_restore(%ebx)
377         popl    %esi
378         cfi_adjust_cfa_offset(-4)
379         cfi_restore(%esi)
380         popl    %edi
381         cfi_adjust_cfa_offset(-4)
382         cfi_restore(%edi)
383         popl    %ebp
384         cfi_adjust_cfa_offset(-4)
385         cfi_restore(%ebp)
387         ret
389         cfi_restore_state
391 27:     call    __pthread_mutex_cond_lock_adjust
392         xorl    %eax, %eax
393         jmp     26b
395         cfi_adjust_cfa_offset(-FRAME_SIZE);
396         /* Initial locking failed.  */
398 #if cond_lock == 0
399         movl    %ebx, %edx
400 #else
401         leal    cond_lock(%ebx), %edx
402 #endif
403 #if (LLL_SHARED-LLL_PRIVATE) > 255
404         xorl    %ecx, %ecx
405 #endif
406         cmpl    $-1, dep_mutex(%ebx)
407         setne   %cl
408         subl    $1, %ecx
409         andl    $(LLL_SHARED-LLL_PRIVATE), %ecx
410 #if LLL_PRIVATE != 0
411         addl    $LLL_PRIVATE, %ecx
412 #endif
413         call    __lll_lock_wait
414         jmp     2b
416         /* The initial unlocking of the mutex failed.  */
418         LOCK
419 #if cond_lock == 0
420         subl    $1, (%ebx)
421 #else
422         subl    $1, cond_lock(%ebx)
423 #endif
424         jne     18b
426         movl    %eax, %esi
427 #if cond_lock == 0
428         movl    %ebx, %eax
429 #else
430         leal    cond_lock(%ebx), %eax
431 #endif
432 #if (LLL_SHARED-LLL_PRIVATE) > 255
433         xorl    %ecx, %ecx
434 #endif
435         cmpl    $-1, dep_mutex(%ebx)
436         setne   %cl
437         subl    $1, %ecx
438         andl    $(LLL_SHARED-LLL_PRIVATE), %ecx
439 #if LLL_PRIVATE != 0
440         addl    $LLL_PRIVATE, %ecx
441 #endif
442         call    __lll_unlock_wake
444         movl    %esi, %eax
445         jmp     18b
447         cfi_adjust_cfa_offset(FRAME_SIZE)
449         /* Unlock in loop requires wakeup.  */
451 #if cond_lock == 0
452         movl    %ebx, %eax
453 #else
454         leal    cond_lock(%ebx), %eax
455 #endif
456 #if (LLL_SHARED-LLL_PRIVATE) > 255
457         xorl    %ecx, %ecx
458 #endif
459         cmpl    $-1, dep_mutex(%ebx)
460         setne   %cl
461         subl    $1, %ecx
462         andl    $(LLL_SHARED-LLL_PRIVATE), %ecx
463 #if LLL_PRIVATE != 0
464         addl    $LLL_PRIVATE, %ecx
465 #endif
466         call    __lll_unlock_wake
467         jmp     4b
469         /* Locking in loop failed.  */
471 #if cond_lock == 0
472         movl    %ebx, %edx
473 #else
474         leal    cond_lock(%ebx), %edx
475 #endif
476 #if (LLL_SHARED-LLL_PRIVATE) > 255
477         xorl    %ecx, %ecx
478 #endif
479         cmpl    $-1, dep_mutex(%ebx)
480         setne   %cl
481         subl    $1, %ecx
482         andl    $(LLL_SHARED-LLL_PRIVATE), %ecx
483 #if LLL_PRIVATE != 0
484         addl    $LLL_PRIVATE, %ecx
485 #endif
486         call    __lll_lock_wait
487         jmp     6b
489         /* Unlock after loop requires wakeup.  */
491 #if cond_lock == 0
492         movl    %ebx, %eax
493 #else
494         leal    cond_lock(%ebx), %eax
495 #endif
496 #if (LLL_SHARED-LLL_PRIVATE) > 255
497         xorl    %ecx, %ecx
498 #endif
499         cmpl    $-1, dep_mutex(%ebx)
500         setne   %cl
501         subl    $1, %ecx
502         andl    $(LLL_SHARED-LLL_PRIVATE), %ecx
503 #if LLL_PRIVATE != 0
504         addl    $LLL_PRIVATE, %ecx
505 #endif
506         call    __lll_unlock_wake
507         jmp     11b
509 #ifndef __ASSUME_FUTEX_CLOCK_REALTIME
510         cfi_adjust_cfa_offset(-FRAME_SIZE)
511 .Lreltmo:
512         /* Get internal lock.  */
513         movl    $1, %edx
514         xorl    %eax, %eax
515         LOCK
516 # if cond_lock == 0
517         cmpxchgl %edx, (%ebx)
518 # else
519         cmpxchgl %edx, cond_lock(%ebx)
520 # endif
521         jnz     101f
523         /* Store the reference to the mutex.  If there is already a
524            different value in there this is a bad user bug.  */
525 102:    cmpl    $-1, dep_mutex(%ebx)
526         movl    24(%esp), %eax
527         je      117f
528         movl    %eax, dep_mutex(%ebx)
530         /* Unlock the mutex.  */
531 117:    xorl    %edx, %edx
532         call    __pthread_mutex_unlock_usercnt
534         testl   %eax, %eax
535         jne     16b
537         addl    $1, total_seq(%ebx)
538         adcl    $0, total_seq+4(%ebx)
539         addl    $1, cond_futex(%ebx)
540         addl    $(1 << nwaiters_shift), cond_nwaiters(%ebx)
542         subl    $FRAME_SIZE, %esp
543         cfi_adjust_cfa_offset(FRAME_SIZE)
545         /* Get and store current wakeup_seq value.  */
546         movl    wakeup_seq(%ebx), %edi
547         movl    wakeup_seq+4(%ebx), %edx
548         movl    broadcast_seq(%ebx), %eax
549         movl    %edi, 4(%esp)
550         movl    %edx, 8(%esp)
551         movl    %eax, 12(%esp)
553         /* Reset the pi-requeued flag.  */
554         movl    $0, 16(%esp)
556         /* Get the current time.  */
557 108:    movl    %ebx, %edx
558 # ifdef __NR_clock_gettime
559         /* Get the clock number.  */
560         movl    cond_nwaiters(%ebx), %ebx
561         andl    $((1 << nwaiters_shift) - 1), %ebx
562         /* Only clocks 0 and 1 are allowed so far.  Both are handled in the
563            kernel.  */
564         leal    24(%esp), %ecx
565         movl    $__NR_clock_gettime, %eax
566         ENTER_KERNEL
567         movl    %edx, %ebx
569         /* Compute relative timeout.  */
570         movl    (%ebp), %ecx
571         movl    4(%ebp), %edx
572         subl    24(%esp), %ecx
573         subl    28(%esp), %edx
574 # else
575         /* Get the current time.  */
576         leal    24(%esp), %ebx
577         xorl    %ecx, %ecx
578         movl    $__NR_gettimeofday, %eax
579         ENTER_KERNEL
580         movl    %edx, %ebx
582         /* Compute relative timeout.  */
583         movl    28(%esp), %eax
584         movl    $1000, %edx
585         mul     %edx            /* Milli seconds to nano seconds.  */
586         movl    (%ebp), %ecx
587         movl    4(%ebp), %edx
588         subl    24(%esp), %ecx
589         subl    %eax, %edx
590 # endif
591         jns     112f
592         addl    $1000000000, %edx
593         subl    $1, %ecx
594 112:    testl   %ecx, %ecx
595         movl    $-ETIMEDOUT, %esi
596         js      106f
598         /* Store relative timeout.  */
599 121:    movl    %ecx, 24(%esp)
600         movl    %edx, 28(%esp)
602         movl    cond_futex(%ebx), %edi
603         movl    %edi, 20(%esp)
605         /* Unlock.  */
606         LOCK
607 # if cond_lock == 0
608         subl    $1, (%ebx)
609 # else
610         subl    $1, cond_lock(%ebx)
611 # endif
612         jne     103f
614 .LcleanupSTART2:
615 104:    call    __pthread_enable_asynccancel
616         movl    %eax, (%esp)
618         leal    24(%esp), %esi
619 # if FUTEX_PRIVATE_FLAG > 255
620         xorl    %ecx, %ecx
621 # endif
622         cmpl    $-1, dep_mutex(%ebx)
623         sete    %cl
624         subl    $1, %ecx
625 # ifdef __ASSUME_PRIVATE_FUTEX
626         andl    $FUTEX_PRIVATE_FLAG, %ecx
627 # else
628         andl    %gs:PRIVATE_FUTEX, %ecx
629 # endif
630 # if FUTEX_WAIT != 0
631         addl    $FUTEX_WAIT, %ecx
632 # endif
633         movl    20(%esp), %edx
634         addl    $cond_futex, %ebx
635 .Ladd_cond_futex2:
636         movl    $SYS_futex, %eax
637         ENTER_KERNEL
638         subl    $cond_futex, %ebx
639 .Lsub_cond_futex2:
640         movl    %eax, %esi
642 141:    movl    (%esp), %eax
643         call    __pthread_disable_asynccancel
644 .LcleanupEND2:
647         /* Lock.  */
648         movl    $1, %edx
649         xorl    %eax, %eax
650         LOCK
651 # if cond_lock == 0
652         cmpxchgl %edx, (%ebx)
653 # else
654         cmpxchgl %edx, cond_lock(%ebx)
655 # endif
656         jnz     105f
658 106:    movl    broadcast_seq(%ebx), %eax
659         cmpl    12(%esp), %eax
660         jne     23b
662         movl    woken_seq(%ebx), %eax
663         movl    woken_seq+4(%ebx), %ecx
665         movl    wakeup_seq(%ebx), %edi
666         movl    wakeup_seq+4(%ebx), %edx
668         cmpl    8(%esp), %edx
669         jne     107f
670         cmpl    4(%esp), %edi
671         je      115f
673 107:    cmpl    %ecx, %edx
674         jne     9b
675         cmp     %eax, %edi
676         jne     9b
678 115:    cmpl    $-ETIMEDOUT, %esi
679         je      28b
681         jmp     8b
683         cfi_adjust_cfa_offset(-FRAME_SIZE)
684         /* Initial locking failed.  */
685 101:
686 # if cond_lock == 0
687         movl    %ebx, %edx
688 # else
689         leal    cond_lock(%ebx), %edx
690 # endif
691 # if (LLL_SHARED-LLL_PRIVATE) > 255
692         xorl    %ecx, %ecx
693 # endif
694         cmpl    $-1, dep_mutex(%ebx)
695         setne   %cl
696         subl    $1, %ecx
697         andl    $(LLL_SHARED-LLL_PRIVATE), %ecx
698 # if LLL_PRIVATE != 0
699         addl    $LLL_PRIVATE, %ecx
700 # endif
701         call    __lll_lock_wait
702         jmp     102b
704         cfi_adjust_cfa_offset(FRAME_SIZE)
706         /* Unlock in loop requires wakeup.  */
707 103:
708 # if cond_lock == 0
709         movl    %ebx, %eax
710 # else
711         leal    cond_lock(%ebx), %eax
712 # endif
713 # if (LLL_SHARED-LLL_PRIVATE) > 255
714         xorl    %ecx, %ecx
715 # endif
716         cmpl    $-1, dep_mutex(%ebx)
717         setne   %cl
718         subl    $1, %ecx
719         andl    $(LLL_SHARED-LLL_PRIVATE), %ecx
720 # if LLL_PRIVATE != 0
721         addl    $LLL_PRIVATE, %ecx
722 # endif
723         call    __lll_unlock_wake
724         jmp     104b
726         /* Locking in loop failed.  */
727 105:
728 # if cond_lock == 0
729         movl    %ebx, %edx
730 # else
731         leal    cond_lock(%ebx), %edx
732 # endif
733 # if (LLL_SHARED-LLL_PRIVATE) > 255
734         xorl    %ecx, %ecx
735 # endif
736         cmpl    $-1, dep_mutex(%ebx)
737         setne   %cl
738         subl    $1, %ecx
739         andl    $(LLL_SHARED-LLL_PRIVATE), %ecx
740 # if LLL_PRIVATE != 0
741         addl    $LLL_PRIVATE, %ecx
742 # endif
743         call    __lll_lock_wait
744         jmp     106b
745 #endif
747         .size   __pthread_cond_timedwait, .-__pthread_cond_timedwait
748 versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
749                   GLIBC_2_3_2)
752         .type   __condvar_tw_cleanup2, @function
753 __condvar_tw_cleanup2:
754         subl    $cond_futex, %ebx
755         .size   __condvar_tw_cleanup2, .-__condvar_tw_cleanup2
756         .type   __condvar_tw_cleanup, @function
757 __condvar_tw_cleanup:
758         movl    %eax, %esi
760         /* Get internal lock.  */
761         movl    $1, %edx
762         xorl    %eax, %eax
763         LOCK
764 #if cond_lock == 0
765         cmpxchgl %edx, (%ebx)
766 #else
767         cmpxchgl %edx, cond_lock(%ebx)
768 #endif
769         jz      1f
771 #if cond_lock == 0
772         movl    %ebx, %edx
773 #else
774         leal    cond_lock(%ebx), %edx
775 #endif
776 #if (LLL_SHARED-LLL_PRIVATE) > 255
777         xorl    %ecx, %ecx
778 #endif
779         cmpl    $-1, dep_mutex(%ebx)
780         setne   %cl
781         subl    $1, %ecx
782         andl    $(LLL_SHARED-LLL_PRIVATE), %ecx
783 #if LLL_PRIVATE != 0
784         addl    $LLL_PRIVATE, %ecx
785 #endif
786         call    __lll_lock_wait
788 1:      movl    broadcast_seq(%ebx), %eax
789         cmpl    12(%esp), %eax
790         jne     3f
792         /* We increment the wakeup_seq counter only if it is lower than
793            total_seq.  If this is not the case the thread was woken and
794            then canceled.  In this case we ignore the signal.  */
795         movl    total_seq(%ebx), %eax
796         movl    total_seq+4(%ebx), %edi
797         cmpl    wakeup_seq+4(%ebx), %edi
798         jb      6f
799         ja      7f
800         cmpl    wakeup_seq(%ebx), %eax
801         jbe     7f
803 6:      addl    $1, wakeup_seq(%ebx)
804         adcl    $0, wakeup_seq+4(%ebx)
805         addl    $1, cond_futex(%ebx)
807 7:      addl    $1, woken_seq(%ebx)
808         adcl    $0, woken_seq+4(%ebx)
810 3:      subl    $(1 << nwaiters_shift), cond_nwaiters(%ebx)
812         /* Wake up a thread which wants to destroy the condvar object.  */
813         xorl    %edi, %edi
814         movl    total_seq(%ebx), %eax
815         andl    total_seq+4(%ebx), %eax
816         cmpl    $0xffffffff, %eax
817         jne     4f
818         movl    cond_nwaiters(%ebx), %eax
819         andl    $~((1 << nwaiters_shift) - 1), %eax
820         jne     4f
822         addl    $cond_nwaiters, %ebx
823         movl    $SYS_futex, %eax
824 #if FUTEX_PRIVATE_FLAG > 255
825         xorl    %ecx, %ecx
826 #endif
827         cmpl    $-1, dep_mutex-cond_nwaiters(%ebx)
828         sete    %cl
829         subl    $1, %ecx
830 #ifdef __ASSUME_PRIVATE_FUTEX
831         andl    $FUTEX_PRIVATE_FLAG, %ecx
832 #else
833         andl    %gs:PRIVATE_FUTEX, %ecx
834 #endif
835         addl    $FUTEX_WAKE, %ecx
836         movl    $1, %edx
837         ENTER_KERNEL
838         subl    $cond_nwaiters, %ebx
839         movl    $1, %edi
841 4:      LOCK
842 #if cond_lock == 0
843         subl    $1, (%ebx)
844 #else
845         subl    $1, cond_lock(%ebx)
846 #endif
847         je      2f
849 #if cond_lock == 0
850         movl    %ebx, %eax
851 #else
852         leal    cond_lock(%ebx), %eax
853 #endif
854 #if (LLL_SHARED-LLL_PRIVATE) > 255
855         xorl    %ecx, %ecx
856 #endif
857         cmpl    $-1, dep_mutex(%ebx)
858         setne   %cl
859         subl    $1, %ecx
860         andl    $(LLL_SHARED-LLL_PRIVATE), %ecx
861 #if LLL_PRIVATE != 0
862         addl    $LLL_PRIVATE, %ecx
863 #endif
864         call    __lll_unlock_wake
866         /* Wake up all waiters to make sure no signal gets lost.  */
867 2:      testl   %edi, %edi
868         jnz     5f
869         addl    $cond_futex, %ebx
870 #if FUTEX_PRIVATE_FLAG > 255
871         xorl    %ecx, %ecx
872 #endif
873         cmpl    $-1, dep_mutex-cond_futex(%ebx)
874         sete    %cl
875         subl    $1, %ecx
876 #ifdef __ASSUME_PRIVATE_FUTEX
877         andl    $FUTEX_PRIVATE_FLAG, %ecx
878 #else
879         andl    %gs:PRIVATE_FUTEX, %ecx
880 #endif
881         addl    $FUTEX_WAKE, %ecx
882         movl    $SYS_futex, %eax
883         movl    $0x7fffffff, %edx
884         ENTER_KERNEL
886         /* Lock the mutex only if we don't own it already.  This only happens
887            in case of PI mutexes, if we got cancelled after a successful
888            return of the futex syscall and before disabling async
889            cancellation.  */
890 5:      movl    24+FRAME_SIZE(%esp), %eax
891         movl    MUTEX_KIND(%eax), %ebx
892         andl    $(ROBUST_BIT|PI_BIT), %ebx
893         cmpl    $PI_BIT, %ebx
894         jne     8f
896         movl    (%eax), %ebx
897         andl    $TID_MASK, %ebx
898         cmpl    %ebx, %gs:TID
899         jne     8f
900         /* We managed to get the lock.  Fix it up before returning.  */
901         call    __pthread_mutex_cond_lock_adjust
902         jmp     9f
904 8:      call    __pthread_mutex_cond_lock
906 9:      movl    %esi, (%esp)
907 .LcallUR:
908         call    _Unwind_Resume
909         hlt
910 .LENDCODE:
911         cfi_endproc
912         .size   __condvar_tw_cleanup, .-__condvar_tw_cleanup
915         .section .gcc_except_table,"a",@progbits
916 .LexceptSTART:
917         .byte   DW_EH_PE_omit                   # @LPStart format (omit)
918         .byte   DW_EH_PE_omit                   # @TType format (omit)
919         .byte   DW_EH_PE_sdata4                 # call-site format
920                                                 # DW_EH_PE_sdata4
921         .uleb128 .Lcstend-.Lcstbegin
922 .Lcstbegin:
923         .long   .LcleanupSTART-.LSTARTCODE
924         .long   .Ladd_cond_futex_pi-.LcleanupSTART
925         .long   __condvar_tw_cleanup-.LSTARTCODE
926         .uleb128  0
927         .long   .Ladd_cond_futex_pi-.LSTARTCODE
928         .long   .Lsub_cond_futex_pi-.Ladd_cond_futex_pi
929         .long   __condvar_tw_cleanup2-.LSTARTCODE
930         .uleb128  0
931         .long   .Lsub_cond_futex_pi-.LSTARTCODE
932         .long   .Ladd_cond_futex-.Lsub_cond_futex_pi
933         .long   __condvar_tw_cleanup-.LSTARTCODE
934         .uleb128  0
935         .long   .Ladd_cond_futex-.LSTARTCODE
936         .long   .Lsub_cond_futex-.Ladd_cond_futex
937         .long   __condvar_tw_cleanup2-.LSTARTCODE
938         .uleb128  0
939         .long   .Lsub_cond_futex-.LSTARTCODE
940         .long   .LcleanupEND-.Lsub_cond_futex
941         .long   __condvar_tw_cleanup-.LSTARTCODE
942         .uleb128  0
943 #ifndef __ASSUME_FUTEX_CLOCK_REALTIME
944         .long   .LcleanupSTART2-.LSTARTCODE
945         .long   .Ladd_cond_futex2-.LcleanupSTART2
946         .long   __condvar_tw_cleanup-.LSTARTCODE
947         .uleb128  0
948         .long   .Ladd_cond_futex2-.LSTARTCODE
949         .long   .Lsub_cond_futex2-.Ladd_cond_futex2
950         .long   __condvar_tw_cleanup2-.LSTARTCODE
951         .uleb128  0
952         .long   .Lsub_cond_futex2-.LSTARTCODE
953         .long   .LcleanupEND2-.Lsub_cond_futex2
954         .long   __condvar_tw_cleanup-.LSTARTCODE
955         .uleb128  0
956 #endif
957         .long   .LcallUR-.LSTARTCODE
958         .long   .LENDCODE-.LcallUR
959         .long   0
960         .uleb128  0
961 .Lcstend:
964 #ifdef SHARED
965         .hidden DW.ref.__gcc_personality_v0
966         .weak   DW.ref.__gcc_personality_v0
967         .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
968         .align  4
969         .type   DW.ref.__gcc_personality_v0, @object
970         .size   DW.ref.__gcc_personality_v0, 4
971 DW.ref.__gcc_personality_v0:
972         .long   __gcc_personality_v0
973 #endif