Update copyright dates with scripts/update-copyrights.
[glibc.git] / sysdeps / unix / sysv / linux / i386 / i486 / pthread_cond_broadcast.S
blob5ddd5ac592c911003164fe253fbb533fdc6d0364
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:
35         cfi_startproc
36         pushl   %ebx
37         cfi_adjust_cfa_offset(4)
38         cfi_rel_offset(%ebx, 0)
39         pushl   %esi
40         cfi_adjust_cfa_offset(4)
41         cfi_rel_offset(%esi, 0)
42         pushl   %edi
43         cfi_adjust_cfa_offset(4)
44         cfi_rel_offset(%edi, 0)
45         pushl   %ebp
46         cfi_adjust_cfa_offset(4)
47         cfi_rel_offset(%ebp, 0)
48         cfi_remember_state
50         movl    20(%esp), %ebx
52         LIBC_PROBE (cond_broadcast, 1, %edx)
54         /* Get internal lock.  */
55         movl    $1, %edx
56         xorl    %eax, %eax
57         LOCK
58 #if cond_lock == 0
59         cmpxchgl %edx, (%ebx)
60 #else
61         cmpxchgl %edx, cond_lock(%ebx)
62 #endif
63         jnz     1f
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
69         ja      3f
70         jb      4f
71         cmpl    wakeup_seq-cond_futex(%ebx), %ebp
72         jna     4f
74         /* Cause all currently waiting threads to recognize they are
75            woken up.  */
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)
84         /* Get the address of the mutex used.  */
85         movl    dep_mutex-cond_futex(%ebx), %edi
87         /* Unlock.  */
88         LOCK
89         subl    $1, cond_lock-cond_futex(%ebx)
90         jne     7f
92         /* Don't use requeue for pshared condvars.  */
93 8:      cmpl    $-1, %edi
94         je      9f
96         /* Do not use requeue for pshared condvars.  */
97         testl   $PS_BIT, MUTEX_KIND(%edi)
98         jne     9f
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
107         /* Wake up all threads.  */
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
114         movl    $SYS_futex, %eax
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
121 /* FIXME: Until Ingo fixes 4G/4G vDSO, 6 arg syscalls are broken for sysenter.
122         ENTER_KERNEL  */
123         int     $0x80
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
131 6:      xorl    %eax, %eax
132         popl    %ebp
133         cfi_adjust_cfa_offset(-4)
134         cfi_restore(%ebp)
135         popl    %edi
136         cfi_adjust_cfa_offset(-4)
137         cfi_restore(%edi)
138         popl    %esi
139         cfi_adjust_cfa_offset(-4)
140         cfi_restore(%esi)
141         popl    %ebx
142         cfi_adjust_cfa_offset(-4)
143         cfi_restore(%ebx)
144         ret
146         cfi_restore_state
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
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
165         /* Initial locking failed.  */
167 #if cond_lock == 0
168         movl    %ebx, %edx
169 #else
170         leal    cond_lock(%ebx), %edx
171 #endif
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
182         call    __lll_lock_wait
183         jmp     2b
185         .align  16
186         /* Unlock.  */
187 4:      LOCK
188         subl    $1, cond_lock-cond_futex(%ebx)
189         je      6b
191         /* Unlock in loop requires wakeup.  */
192 5:      leal    cond_lock-cond_futex(%ebx), %eax
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
203         call    __lll_unlock_wake
204         jmp     6b
206         /* Unlock in loop requires wakeup.  */
207 7:      leal    cond_lock-cond_futex(%ebx), %eax
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
218         call    __lll_unlock_wake
219         jmp     8b
221 9:      /* The futex requeue functionality is not available.  */
222         movl    $0x7fffffff, %edx
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
235         movl    $SYS_futex, %eax
236         ENTER_KERNEL
237         jmp     6b
238         cfi_endproc
239         .size   __pthread_cond_broadcast, .-__pthread_cond_broadcast
240 versioned_symbol (libpthread, __pthread_cond_broadcast, pthread_cond_broadcast,
241                   GLIBC_2_3_2)