]>
Commit | Line | Data |
---|---|---|
b168057a | 1 | /* Copyright (C) 2002-2015 Free Software Foundation, Inc. |
1d087a7e UD |
2 | This file is part of the GNU C Library. |
3 | Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. | |
4 | ||
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. | |
9 | ||
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. | |
14 | ||
15 | You should have received a copy of the GNU Lesser General Public | |
59ba27a6 PE |
16 | License along with the GNU C Library; if not, see |
17 | <http://www.gnu.org/licenses/>. */ | |
1d087a7e UD |
18 | |
19 | #include <sysdep.h> | |
20 | #include <shlib-compat.h> | |
e51deae7 | 21 | #include <lowlevellock.h> |
1d087a7e | 22 | #include <lowlevelcond.h> |
69431c9a | 23 | #include <kernel-features.h> |
df47504c | 24 | #include <pthread-pi-defines.h> |
e51deae7 | 25 | #include <pthread-errnos.h> |
17557282 | 26 | #include <stap-probe.h> |
1d087a7e UD |
27 | |
28 | .text | |
29 | ||
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: | |
62605cbf | 35 | cfi_startproc |
1d087a7e | 36 | pushl %ebx |
62605cbf | 37 | cfi_adjust_cfa_offset(4) |
dd7106b3 | 38 | cfi_rel_offset(%ebx, 0) |
69431c9a | 39 | pushl %esi |
62605cbf | 40 | cfi_adjust_cfa_offset(4) |
dd7106b3 | 41 | cfi_rel_offset(%esi, 0) |
69431c9a | 42 | pushl %edi |
62605cbf | 43 | cfi_adjust_cfa_offset(4) |
dd7106b3 | 44 | cfi_rel_offset(%edi, 0) |
75fccede | 45 | pushl %ebp |
62605cbf | 46 | cfi_adjust_cfa_offset(4) |
dd7106b3 DG |
47 | cfi_rel_offset(%ebp, 0) |
48 | cfi_remember_state | |
1d087a7e | 49 | |
75fccede | 50 | movl 20(%esp), %ebx |
1d087a7e | 51 | |
17557282 RH |
52 | LIBC_PROBE (cond_broadcast, 1, %edx) |
53 | ||
1d087a7e | 54 | /* Get internal lock. */ |
71451de2 UD |
55 | movl $1, %edx |
56 | xorl %eax, %eax | |
1d087a7e UD |
57 | LOCK |
58 | #if cond_lock == 0 | |
71451de2 | 59 | cmpxchgl %edx, (%ebx) |
1d087a7e | 60 | #else |
71451de2 | 61 | cmpxchgl %edx, cond_lock(%ebx) |
1d087a7e | 62 | #endif |
3a226d33 | 63 | jnz 1f |
1d087a7e | 64 | |
75fccede UD |
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 | |
1d087a7e UD |
69 | ja 3f |
70 | jb 4f | |
75fccede | 71 | cmpl wakeup_seq-cond_futex(%ebx), %ebp |
1d087a7e UD |
72 | jna 4f |
73 | ||
a1ea4c06 UD |
74 | /* Cause all currently waiting threads to recognize they are |
75 | woken up. */ | |
75fccede UD |
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) | |
80 | addl %ebp, %ebp | |
81 | addl $1, broadcast_seq-cond_futex(%ebx) | |
82 | movl %ebp, (%ebx) | |
1d087a7e | 83 | |
69431c9a | 84 | /* Get the address of the mutex used. */ |
75fccede | 85 | movl dep_mutex-cond_futex(%ebx), %edi |
69431c9a | 86 | |
567fb22a UD |
87 | /* Unlock. */ |
88 | LOCK | |
75fccede | 89 | subl $1, cond_lock-cond_futex(%ebx) |
567fb22a UD |
90 | jne 7f |
91 | ||
e42a990e UD |
92 | /* Don't use requeue for pshared condvars. */ |
93 | 8: cmpl $-1, %edi | |
94 | je 9f | |
95 | ||
75956694 DG |
96 | /* Do not use requeue for pshared condvars. */ |
97 | testl $PS_BIT, MUTEX_KIND(%edi) | |
df47504c UD |
98 | jne 9f |
99 | ||
75956694 DG |
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 | |
104 | cmpl $PI_BIT, %eax | |
105 | je 81f | |
106 | ||
1d087a7e | 107 | /* Wake up all threads. */ |
22502ea2 UD |
108 | #ifdef __ASSUME_PRIVATE_FUTEX |
109 | movl $(FUTEX_CMP_REQUEUE|FUTEX_PRIVATE_FLAG), %ecx | |
110 | #else | |
111 | movl %gs:PRIVATE_FUTEX, %ecx | |
112 | orl $FUTEX_CMP_REQUEUE, %ecx | |
113 | #endif | |
1d087a7e | 114 | movl $SYS_futex, %eax |
69431c9a UD |
115 | movl $0x7fffffff, %esi |
116 | movl $1, %edx | |
117 | /* Get the address of the futex involved. */ | |
118 | # if MUTEX_FUTEX != 0 | |
119 | addl $MUTEX_FUTEX, %edi | |
120 | # endif | |
75fccede UD |
121 | /* FIXME: Until Ingo fixes 4G/4G vDSO, 6 arg syscalls are broken for sysenter. |
122 | ENTER_KERNEL */ | |
123 | int $0x80 | |
1d087a7e | 124 | |
75fccede UD |
125 | /* For any kind of error, which mainly is EAGAIN, we try again |
126 | with WAKE. The general test also covers running on old | |
127 | kernels. */ | |
128 | cmpl $0xfffff001, %eax | |
129 | jae 9f | |
69431c9a | 130 | |
dd7106b3 | 131 | 6: xorl %eax, %eax |
75fccede | 132 | popl %ebp |
62605cbf UD |
133 | cfi_adjust_cfa_offset(-4) |
134 | cfi_restore(%ebp) | |
69431c9a | 135 | popl %edi |
62605cbf UD |
136 | cfi_adjust_cfa_offset(-4) |
137 | cfi_restore(%edi) | |
69431c9a | 138 | popl %esi |
62605cbf UD |
139 | cfi_adjust_cfa_offset(-4) |
140 | cfi_restore(%esi) | |
567fb22a | 141 | popl %ebx |
62605cbf UD |
142 | cfi_adjust_cfa_offset(-4) |
143 | cfi_restore(%ebx) | |
567fb22a UD |
144 | ret |
145 | ||
dd7106b3 DG |
146 | cfi_restore_state |
147 | ||
75956694 DG |
148 | 81: movl $(FUTEX_CMP_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %ecx |
149 | movl $SYS_futex, %eax | |
150 | movl $0x7fffffff, %esi | |
151 | movl $1, %edx | |
152 | /* Get the address of the futex involved. */ | |
153 | # if MUTEX_FUTEX != 0 | |
154 | addl $MUTEX_FUTEX, %edi | |
155 | # endif | |
156 | int $0x80 | |
157 | ||
158 | /* For any kind of error, which mainly is EAGAIN, we try again | |
159 | with WAKE. The general test also covers running on old | |
160 | kernels. */ | |
161 | cmpl $0xfffff001, %eax | |
162 | jb 6b | |
163 | jmp 9f | |
164 | ||
1d087a7e UD |
165 | /* Initial locking failed. */ |
166 | 1: | |
167 | #if cond_lock == 0 | |
e51deae7 | 168 | movl %ebx, %edx |
1d087a7e | 169 | #else |
e51deae7 | 170 | leal cond_lock(%ebx), %edx |
1d087a7e | 171 | #endif |
22502ea2 UD |
172 | #if (LLL_SHARED-LLL_PRIVATE) > 255 |
173 | xorl %ecx, %ecx | |
174 | #endif | |
175 | cmpl $-1, dep_mutex(%ebx) | |
176 | setne %cl | |
177 | subl $1, %ecx | |
178 | andl $(LLL_SHARED-LLL_PRIVATE), %ecx | |
179 | #if LLL_PRIVATE != 0 | |
180 | addl $LLL_PRIVATE, %ecx | |
181 | #endif | |
e51deae7 | 182 | call __lll_lock_wait |
1d087a7e UD |
183 | jmp 2b |
184 | ||
dfedb126 UD |
185 | .align 16 |
186 | /* Unlock. */ | |
187 | 4: LOCK | |
188 | subl $1, cond_lock-cond_futex(%ebx) | |
189 | je 6b | |
190 | ||
191 | /* Unlock in loop requires wakeup. */ | |
75fccede | 192 | 5: leal cond_lock-cond_futex(%ebx), %eax |
22502ea2 UD |
193 | #if (LLL_SHARED-LLL_PRIVATE) > 255 |
194 | xorl %ecx, %ecx | |
195 | #endif | |
196 | cmpl $-1, dep_mutex-cond_futex(%ebx) | |
197 | setne %cl | |
198 | subl $1, %ecx | |
199 | andl $(LLL_SHARED-LLL_PRIVATE), %ecx | |
200 | #if LLL_PRIVATE != 0 | |
201 | addl $LLL_PRIVATE, %ecx | |
202 | #endif | |
e51deae7 | 203 | call __lll_unlock_wake |
1d087a7e | 204 | jmp 6b |
567fb22a | 205 | |
dfedb126 | 206 | /* Unlock in loop requires wakeup. */ |
75fccede | 207 | 7: leal cond_lock-cond_futex(%ebx), %eax |
22502ea2 UD |
208 | #if (LLL_SHARED-LLL_PRIVATE) > 255 |
209 | xorl %ecx, %ecx | |
210 | #endif | |
211 | cmpl $-1, dep_mutex-cond_futex(%ebx) | |
212 | setne %cl | |
213 | subl $1, %ecx | |
214 | andl $(LLL_SHARED-LLL_PRIVATE), %ecx | |
215 | #if LLL_PRIVATE != 0 | |
216 | addl $LLL_PRIVATE, %ecx | |
217 | #endif | |
e51deae7 | 218 | call __lll_unlock_wake |
567fb22a | 219 | jmp 8b |
69431c9a | 220 | |
69431c9a UD |
221 | 9: /* The futex requeue functionality is not available. */ |
222 | movl $0x7fffffff, %edx | |
22502ea2 UD |
223 | #if FUTEX_PRIVATE_FLAG > 255 |
224 | xorl %ecx, %ecx | |
225 | #endif | |
226 | cmpl $-1, dep_mutex-cond_futex(%ebx) | |
227 | sete %cl | |
228 | subl $1, %ecx | |
229 | #ifdef __ASSUME_PRIVATE_FUTEX | |
230 | andl $FUTEX_PRIVATE_FLAG, %ecx | |
231 | #else | |
232 | andl %gs:PRIVATE_FUTEX, %ecx | |
233 | #endif | |
234 | addl $FUTEX_WAKE, %ecx | |
69431c9a UD |
235 | movl $SYS_futex, %eax |
236 | ENTER_KERNEL | |
dd7106b3 | 237 | jmp 6b |
62605cbf | 238 | cfi_endproc |
1d087a7e UD |
239 | .size __pthread_cond_broadcast, .-__pthread_cond_broadcast |
240 | versioned_symbol (libpthread, __pthread_cond_broadcast, pthread_cond_broadcast, | |
241 | GLIBC_2_3_2) |