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/>. */
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>
30 /* int pthread_cond_broadcast (pthread_cond_t *cond) */
31 .globl __pthread_cond_broadcast
32 .type __pthread_cond_broadcast, @function
34 __pthread_cond_broadcast:
37 cfi_adjust_cfa_offset(4)
38 cfi_rel_offset(%ebx, 0)
40 cfi_adjust_cfa_offset(4)
41 cfi_rel_offset(%esi, 0)
43 cfi_adjust_cfa_offset(4)
44 cfi_rel_offset(%edi, 0)
46 cfi_adjust_cfa_offset(4)
47 cfi_rel_offset(%ebp, 0)
52 LIBC_PROBE (cond_broadcast, 1, %edx)
54 /* Get internal lock. */
61 cmpxchgl %edx, cond_lock(%ebx)
65 2: addl $cond_futex, %ebx
66 movl total_seq+4-cond_futex(%ebx), %eax
67 movl total_seq-cond_futex(%ebx), %ebp
68 cmpl wakeup_seq+4-cond_futex(%ebx), %eax
71 cmpl wakeup_seq-cond_futex(%ebx), %ebp
74 /* Cause all currently waiting threads to recognize they are
76 3: movl %ebp, wakeup_seq-cond_futex(%ebx)
77 movl %eax, wakeup_seq-cond_futex+4(%ebx)
78 movl %ebp, woken_seq-cond_futex(%ebx)
79 movl %eax, woken_seq-cond_futex+4(%ebx)
81 addl $1, broadcast_seq-cond_futex(%ebx)
84 /* Get the address of the mutex used. */
85 movl dep_mutex-cond_futex(%ebx), %edi
89 subl $1, cond_lock-cond_futex(%ebx)
92 /* Don't use requeue for pshared condvars. */
96 /* Do not use requeue for pshared condvars. */
97 testl $PS_BIT, MUTEX_KIND(%edi)
100 /* Requeue to a non-robust PI mutex if the PI bit is set and
101 the robust bit is not set. */
102 movl MUTEX_KIND(%edi), %eax
103 andl $(ROBUST_BIT|PI_BIT), %eax
107 /* Wake up all threads. */
108 #ifdef __ASSUME_PRIVATE_FUTEX
109 movl $(FUTEX_CMP_REQUEUE|FUTEX_PRIVATE_FLAG), %ecx
111 movl %gs:PRIVATE_FUTEX, %ecx
112 orl $FUTEX_CMP_REQUEUE, %ecx
114 movl $SYS_futex, %eax
115 movl $0x7fffffff, %esi
117 /* Get the address of the futex involved. */
118 # if MUTEX_FUTEX != 0
119 addl $MUTEX_FUTEX, %edi
121 /* FIXME: Until Ingo fixes 4G/4G vDSO, 6 arg syscalls are broken for sysenter.
125 /* For any kind of error, which mainly is EAGAIN, we try again
126 with WAKE. The general test also covers running on old
128 cmpl $0xfffff001, %eax
133 cfi_adjust_cfa_offset(-4)
136 cfi_adjust_cfa_offset(-4)
139 cfi_adjust_cfa_offset(-4)
142 cfi_adjust_cfa_offset(-4)
148 81: movl $(FUTEX_CMP_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %ecx
149 movl $SYS_futex, %eax
150 movl $0x7fffffff, %esi
152 /* Get the address of the futex involved. */
153 # if MUTEX_FUTEX != 0
154 addl $MUTEX_FUTEX, %edi
158 /* For any kind of error, which mainly is EAGAIN, we try again
159 with WAKE. The general test also covers running on old
161 cmpl $0xfffff001, %eax
165 /* Initial locking failed. */
170 leal cond_lock(%ebx), %edx
172 #if (LLL_SHARED-LLL_PRIVATE) > 255
175 cmpl $-1, dep_mutex(%ebx)
178 andl $(LLL_SHARED-LLL_PRIVATE), %ecx
180 addl $LLL_PRIVATE, %ecx
188 subl $1, cond_lock-cond_futex(%ebx)
191 /* Unlock in loop requires wakeup. */
192 5: leal cond_lock-cond_futex(%ebx), %eax
193 #if (LLL_SHARED-LLL_PRIVATE) > 255
196 cmpl $-1, dep_mutex-cond_futex(%ebx)
199 andl $(LLL_SHARED-LLL_PRIVATE), %ecx
201 addl $LLL_PRIVATE, %ecx
203 call __lll_unlock_wake
206 /* Unlock in loop requires wakeup. */
207 7: leal cond_lock-cond_futex(%ebx), %eax
208 #if (LLL_SHARED-LLL_PRIVATE) > 255
211 cmpl $-1, dep_mutex-cond_futex(%ebx)
214 andl $(LLL_SHARED-LLL_PRIVATE), %ecx
216 addl $LLL_PRIVATE, %ecx
218 call __lll_unlock_wake
221 9: /* The futex requeue functionality is not available. */
222 movl $0x7fffffff, %edx
223 #if FUTEX_PRIVATE_FLAG > 255
226 cmpl $-1, dep_mutex-cond_futex(%ebx)
229 #ifdef __ASSUME_PRIVATE_FUTEX
230 andl $FUTEX_PRIVATE_FLAG, %ecx
232 andl %gs:PRIVATE_FUTEX, %ecx
234 addl $FUTEX_WAKE, %ecx
235 movl $SYS_futex, %eax
239 .size __pthread_cond_broadcast, .-__pthread_cond_broadcast
240 versioned_symbol (libpthread, __pthread_cond_broadcast, pthread_cond_broadcast,