Replace FSF snail mail address with URLs.
[glibc.git] / nptl / sysdeps / unix / sysv / linux / i386 / i486 / pthread_cond_broadcast.S
blob71a668686f96e64370c15d4340f097a442acebd8
1 /* Copyright (C) 2002,2003,2004,2006,2007,2009 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>
27         .text
29         /* int pthread_cond_broadcast (pthread_cond_t *cond) */
30         .globl  __pthread_cond_broadcast
31         .type   __pthread_cond_broadcast, @function
32         .align  16
33 __pthread_cond_broadcast:
34         cfi_startproc
35         pushl   %ebx
36         cfi_adjust_cfa_offset(4)
37         cfi_rel_offset(%ebx, 0)
38         pushl   %esi
39         cfi_adjust_cfa_offset(4)
40         cfi_rel_offset(%esi, 0)
41         pushl   %edi
42         cfi_adjust_cfa_offset(4)
43         cfi_rel_offset(%edi, 0)
44         pushl   %ebp
45         cfi_adjust_cfa_offset(4)
46         cfi_rel_offset(%ebp, 0)
47         cfi_remember_state
49         movl    20(%esp), %ebx
51         /* Get internal lock.  */
52         movl    $1, %edx
53         xorl    %eax, %eax
54         LOCK
55 #if cond_lock == 0
56         cmpxchgl %edx, (%ebx)
57 #else
58         cmpxchgl %edx, cond_lock(%ebx)
59 #endif
60         jnz     1f
62 2:      addl    $cond_futex, %ebx
63         movl    total_seq+4-cond_futex(%ebx), %eax
64         movl    total_seq-cond_futex(%ebx), %ebp
65         cmpl    wakeup_seq+4-cond_futex(%ebx), %eax
66         ja      3f
67         jb      4f
68         cmpl    wakeup_seq-cond_futex(%ebx), %ebp
69         jna     4f
71         /* Cause all currently waiting threads to recognize they are
72            woken up.  */
73 3:      movl    %ebp, wakeup_seq-cond_futex(%ebx)
74         movl    %eax, wakeup_seq-cond_futex+4(%ebx)
75         movl    %ebp, woken_seq-cond_futex(%ebx)
76         movl    %eax, woken_seq-cond_futex+4(%ebx)
77         addl    %ebp, %ebp
78         addl    $1, broadcast_seq-cond_futex(%ebx)
79         movl    %ebp, (%ebx)
81         /* Get the address of the mutex used.  */
82         movl    dep_mutex-cond_futex(%ebx), %edi
84         /* Unlock.  */
85         LOCK
86         subl    $1, cond_lock-cond_futex(%ebx)
87         jne     7f
89         /* Don't use requeue for pshared condvars.  */
90 8:      cmpl    $-1, %edi
91         je      9f
93         /* Do not use requeue for pshared condvars.  */
94         testl   $PS_BIT, MUTEX_KIND(%edi)
95         jne     9f
97         /* Requeue to a non-robust PI mutex if the PI bit is set and
98            the robust bit is not set.  */
99         movl    MUTEX_KIND(%edi), %eax
100         andl    $(ROBUST_BIT|PI_BIT), %eax
101         cmpl    $PI_BIT, %eax
102         je      81f
104         /* Wake up all threads.  */
105 #ifdef __ASSUME_PRIVATE_FUTEX
106         movl    $(FUTEX_CMP_REQUEUE|FUTEX_PRIVATE_FLAG), %ecx
107 #else
108         movl    %gs:PRIVATE_FUTEX, %ecx
109         orl     $FUTEX_CMP_REQUEUE, %ecx
110 #endif
111         movl    $SYS_futex, %eax
112         movl    $0x7fffffff, %esi
113         movl    $1, %edx
114         /* Get the address of the futex involved.  */
115 # if MUTEX_FUTEX != 0
116         addl    $MUTEX_FUTEX, %edi
117 # endif
118 /* FIXME: Until Ingo fixes 4G/4G vDSO, 6 arg syscalls are broken for sysenter.
119         ENTER_KERNEL  */
120         int     $0x80
122         /* For any kind of error, which mainly is EAGAIN, we try again
123            with WAKE.  The general test also covers running on old
124            kernels.  */
125         cmpl    $0xfffff001, %eax
126         jae     9f
128 6:      xorl    %eax, %eax
129         popl    %ebp
130         cfi_adjust_cfa_offset(-4)
131         cfi_restore(%ebp)
132         popl    %edi
133         cfi_adjust_cfa_offset(-4)
134         cfi_restore(%edi)
135         popl    %esi
136         cfi_adjust_cfa_offset(-4)
137         cfi_restore(%esi)
138         popl    %ebx
139         cfi_adjust_cfa_offset(-4)
140         cfi_restore(%ebx)
141         ret
143         cfi_restore_state
145 81:     movl    $(FUTEX_CMP_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %ecx
146         movl    $SYS_futex, %eax
147         movl    $0x7fffffff, %esi
148         movl    $1, %edx
149         /* Get the address of the futex involved.  */
150 # if MUTEX_FUTEX != 0
151         addl    $MUTEX_FUTEX, %edi
152 # endif
153         int     $0x80
155         /* For any kind of error, which mainly is EAGAIN, we try again
156         with WAKE.  The general test also covers running on old
157         kernels.  */
158         cmpl    $0xfffff001, %eax
159         jb      6b
160         jmp     9f
162         /* Initial locking failed.  */
164 #if cond_lock == 0
165         movl    %ebx, %edx
166 #else
167         leal    cond_lock(%ebx), %edx
168 #endif
169 #if (LLL_SHARED-LLL_PRIVATE) > 255
170         xorl    %ecx, %ecx
171 #endif
172         cmpl    $-1, dep_mutex(%ebx)
173         setne   %cl
174         subl    $1, %ecx
175         andl    $(LLL_SHARED-LLL_PRIVATE), %ecx
176 #if LLL_PRIVATE != 0
177         addl    $LLL_PRIVATE, %ecx
178 #endif
179         call    __lll_lock_wait
180         jmp     2b
182         .align  16
183         /* Unlock.  */
184 4:      LOCK
185         subl    $1, cond_lock-cond_futex(%ebx)
186         je      6b
188         /* Unlock in loop requires wakeup.  */
189 5:      leal    cond_lock-cond_futex(%ebx), %eax
190 #if (LLL_SHARED-LLL_PRIVATE) > 255
191         xorl    %ecx, %ecx
192 #endif
193         cmpl    $-1, dep_mutex-cond_futex(%ebx)
194         setne   %cl
195         subl    $1, %ecx
196         andl    $(LLL_SHARED-LLL_PRIVATE), %ecx
197 #if LLL_PRIVATE != 0
198         addl    $LLL_PRIVATE, %ecx
199 #endif
200         call    __lll_unlock_wake
201         jmp     6b
203         /* Unlock in loop requires wakeup.  */
204 7:      leal    cond_lock-cond_futex(%ebx), %eax
205 #if (LLL_SHARED-LLL_PRIVATE) > 255
206         xorl    %ecx, %ecx
207 #endif
208         cmpl    $-1, dep_mutex-cond_futex(%ebx)
209         setne   %cl
210         subl    $1, %ecx
211         andl    $(LLL_SHARED-LLL_PRIVATE), %ecx
212 #if LLL_PRIVATE != 0
213         addl    $LLL_PRIVATE, %ecx
214 #endif
215         call    __lll_unlock_wake
216         jmp     8b
218 9:      /* The futex requeue functionality is not available.  */
219         movl    $0x7fffffff, %edx
220 #if FUTEX_PRIVATE_FLAG > 255
221         xorl    %ecx, %ecx
222 #endif
223         cmpl    $-1, dep_mutex-cond_futex(%ebx)
224         sete    %cl
225         subl    $1, %ecx
226 #ifdef __ASSUME_PRIVATE_FUTEX
227         andl    $FUTEX_PRIVATE_FLAG, %ecx
228 #else
229         andl    %gs:PRIVATE_FUTEX, %ecx
230 #endif
231         addl    $FUTEX_WAKE, %ecx
232         movl    $SYS_futex, %eax
233         ENTER_KERNEL
234         jmp     6b
235         cfi_endproc
236         .size   __pthread_cond_broadcast, .-__pthread_cond_broadcast
237 versioned_symbol (libpthread, __pthread_cond_broadcast, pthread_cond_broadcast,
238                   GLIBC_2_3_2)