Update copyright dates with scripts/update-copyrights.
[glibc.git] / sysdeps / unix / sysv / linux / x86_64 / pthread_cond_broadcast.S
blobdf635af7ed910269a8002666f0e0963293095629
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 <kernel-features.h>
24 #include <pthread-pi-defines.h>
25 #include <pthread-errnos.h>
26 #include <stap-probe.h>
28         .text
30         /* int pthread_cond_broadcast (pthread_cond_t *cond) */
31         .globl  __pthread_cond_broadcast
32         .type   __pthread_cond_broadcast, @function
33         .align  16
34 __pthread_cond_broadcast:
36         LIBC_PROBE (cond_broadcast, 1, %rdi)
38         /* Get internal lock.  */
39         movl    $1, %esi
40         xorl    %eax, %eax
41         LOCK
42 #if cond_lock == 0
43         cmpxchgl %esi, (%rdi)
44 #else
45         cmpxchgl %esi, cond_lock(%rdi)
46 #endif
47         jnz     1f
49 2:      addq    $cond_futex, %rdi
50         movq    total_seq-cond_futex(%rdi), %r9
51         cmpq    wakeup_seq-cond_futex(%rdi), %r9
52         jna     4f
54         /* Cause all currently waiting threads to recognize they are
55            woken up.  */
56         movq    %r9, wakeup_seq-cond_futex(%rdi)
57         movq    %r9, woken_seq-cond_futex(%rdi)
58         addq    %r9, %r9
59         movl    %r9d, (%rdi)
60         incl    broadcast_seq-cond_futex(%rdi)
62         /* Get the address of the mutex used.  */
63         mov     dep_mutex-cond_futex(%rdi), %R8_LP
65         /* Unlock.  */
66         LOCK
67         decl    cond_lock-cond_futex(%rdi)
68         jne     7f
70 8:      cmp     $-1, %R8_LP
71         je      9f
73         /* Do not use requeue for pshared condvars.  */
74         testl   $PS_BIT, MUTEX_KIND(%r8)
75         jne     9f
77         /* Requeue to a PI mutex if the PI bit is set.  */
78         movl    MUTEX_KIND(%r8), %eax
79         andl    $(ROBUST_BIT|PI_BIT), %eax
80         cmpl    $PI_BIT, %eax
81         je      81f
83         /* Wake up all threads.  */
84 #ifdef __ASSUME_PRIVATE_FUTEX
85         movl    $(FUTEX_CMP_REQUEUE|FUTEX_PRIVATE_FLAG), %esi
86 #else
87         movl    %fs:PRIVATE_FUTEX, %esi
88         orl     $FUTEX_CMP_REQUEUE, %esi
89 #endif
90         movl    $SYS_futex, %eax
91         movl    $1, %edx
92         movl    $0x7fffffff, %r10d
93         syscall
95         /* For any kind of error, which mainly is EAGAIN, we try again
96            with WAKE.  The general test also covers running on old
97            kernels.  */
98         cmpq    $-4095, %rax
99         jae     9f
101 10:     xorl    %eax, %eax
102         retq
104         /* Wake up all threads.  */
105 81:     movl    $(FUTEX_CMP_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %esi
106         movl    $SYS_futex, %eax
107         movl    $1, %edx
108         movl    $0x7fffffff, %r10d
109         syscall
111         /* For any kind of error, which mainly is EAGAIN, we try again
112            with WAKE.  The general test also covers running on old
113            kernels.  */
114         cmpq    $-4095, %rax
115         jb      10b
116         jmp     9f
118         .align  16
119         /* Unlock.  */
120 4:      LOCK
121         decl    cond_lock-cond_futex(%rdi)
122         jne     5f
124 6:      xorl    %eax, %eax
125         retq
127         /* Initial locking failed.  */
129 #if cond_lock != 0
130         addq    $cond_lock, %rdi
131 #endif
132         LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
133         movl    $LLL_PRIVATE, %eax
134         movl    $LLL_SHARED, %esi
135         cmovne  %eax, %esi
136         callq   __lll_lock_wait
137 #if cond_lock != 0
138         subq    $cond_lock, %rdi
139 #endif
140         jmp     2b
142         /* Unlock in loop requires wakeup.  */
143 5:      addq    $cond_lock-cond_futex, %rdi
144         LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
145         movl    $LLL_PRIVATE, %eax
146         movl    $LLL_SHARED, %esi
147         cmovne  %eax, %esi
148         callq   __lll_unlock_wake
149         jmp     6b
151         /* Unlock in loop requires wakeup.  */
152 7:      addq    $cond_lock-cond_futex, %rdi
153         cmp     $-1, %R8_LP
154         movl    $LLL_PRIVATE, %eax
155         movl    $LLL_SHARED, %esi
156         cmovne  %eax, %esi
157         callq   __lll_unlock_wake
158         subq    $cond_lock-cond_futex, %rdi
159         jmp     8b
161 9:      /* The futex requeue functionality is not available.  */
162         cmp     $-1, %R8_LP
163         movl    $0x7fffffff, %edx
164 #ifdef __ASSUME_PRIVATE_FUTEX
165         movl    $FUTEX_WAKE, %eax
166         movl    $(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi
167         cmove   %eax, %esi
168 #else
169         movl    $0, %eax
170         movl    %fs:PRIVATE_FUTEX, %esi
171         cmove   %eax, %esi
172         orl     $FUTEX_WAKE, %esi
173 #endif
174         movl    $SYS_futex, %eax
175         syscall
176         jmp     10b
177         .size   __pthread_cond_broadcast, .-__pthread_cond_broadcast
178 versioned_symbol (libpthread, __pthread_cond_broadcast, pthread_cond_broadcast,
179                   GLIBC_2_3_2)