Fix some uses of ret in libpthread
[glibc/nacl-glibc.git] / nptl / sysdeps / unix / sysv / linux / i386 / i486 / pthread_cond_broadcast.S
blob2b7f7613a5fc02d74c6c27661c6ddb4097fd1cdb
1 /* Copyright (C) 2002, 2003, 2004, 2006, 2007 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, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
20 #include <sysdep.h>
21 #include <shlib-compat.h>
22 #include <lowlevellock.h>
23 #include <lowlevelcond.h>
24 #include <kernel-features.h>
25 #include <pthread-pi-defines.h>
26 #include <pthread-errnos.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         pushl   %esi
39         cfi_adjust_cfa_offset(4)
40         pushl   %edi
41         cfi_adjust_cfa_offset(4)
42         pushl   %ebp
43         cfi_adjust_cfa_offset(4)
44         cfi_offset(%ebx, -8)
45         cfi_offset(%esi, -12)
46         cfi_offset(%edi, -16)
47         cfi_offset(%ebp, -20)
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         /* XXX: The kernel so far doesn't support requeue to PI futex.  */
94         /* XXX: The kernel only supports FUTEX_CMP_REQUEUE to the same
95            type of futex (private resp. shared).  */
96         testl   $(PI_BIT | PS_BIT), MUTEX_KIND(%edi)
97         jne     9f
99         /* Wake up all threads.  */
100 #ifdef __ASSUME_PRIVATE_FUTEX
101         movl    $(FUTEX_CMP_REQUEUE|FUTEX_PRIVATE_FLAG), %ecx
102 #else
103         movl    %gs:PRIVATE_FUTEX, %ecx
104         orl     $FUTEX_CMP_REQUEUE, %ecx
105 #endif
106         movl    $SYS_futex, %eax
107         movl    $0x7fffffff, %esi
108         movl    $1, %edx
109         /* Get the address of the futex involved.  */
110 # if MUTEX_FUTEX != 0
111         addl    $MUTEX_FUTEX, %edi
112 # endif
113 /* FIXME: Until Ingo fixes 4G/4G vDSO, 6 arg syscalls are broken for sysenter.
114         ENTER_KERNEL  */
115         int     $0x80
117         /* For any kind of error, which mainly is EAGAIN, we try again
118            with WAKE.  The general test also covers running on old
119            kernels.  */
120         cmpl    $0xfffff001, %eax
121         jae     9f
123 10:     xorl    %eax, %eax
124         popl    %ebp
125         cfi_adjust_cfa_offset(-4)
126         cfi_restore(%ebp)
127         popl    %edi
128         cfi_adjust_cfa_offset(-4)
129         cfi_restore(%edi)
130         popl    %esi
131         cfi_adjust_cfa_offset(-4)
132         cfi_restore(%esi)
133         popl    %ebx
134         cfi_adjust_cfa_offset(-4)
135         cfi_restore(%ebx)
136         popl %ecx; nacljmp %ecx
138         cfi_adjust_cfa_offset(16)
139         cfi_offset(%ebx, -8)
140         cfi_offset(%esi, -12)
141         cfi_offset(%edi, -16)
142         cfi_offset(%ebp, -20)
143         .align  16
144         /* Unlock.  */
145 4:      LOCK
146         subl    $1, cond_lock-cond_futex(%ebx)
147         jne     5f
149 6:      xorl    %eax, %eax
150         popl    %ebp
151         cfi_adjust_cfa_offset(-4)
152         cfi_restore(%ebp)
153         popl    %edi
154         cfi_adjust_cfa_offset(-4)
155         cfi_restore(%edi)
156         popl    %esi
157         cfi_adjust_cfa_offset(-4)
158         cfi_restore(%esi)
159         popl    %ebx
160         cfi_adjust_cfa_offset(-4)
161         cfi_restore(%ebx)
162         popl %ecx; nacljmp %ecx
164         cfi_adjust_cfa_offset(16)
165         cfi_offset(%ebx, -8)
166         cfi_offset(%esi, -12)
167         cfi_offset(%edi, -16)
168         cfi_offset(%ebp, -20)
169         /* Initial locking failed.  */
171 #if cond_lock == 0
172         movl    %ebx, %edx
173 #else
174         leal    cond_lock(%ebx), %edx
175 #endif
176 #if (LLL_SHARED-LLL_PRIVATE) > 255
177         xorl    %ecx, %ecx
178 #endif
179         cmpl    $-1, dep_mutex(%ebx)
180         setne   %cl
181         subl    $1, %ecx
182         andl    $(LLL_SHARED-LLL_PRIVATE), %ecx
183 #if LLL_PRIVATE != 0
184         addl    $LLL_PRIVATE, %ecx
185 #endif
186         call    __lll_lock_wait
187         jmp     2b
189         /* Unlock in loop requires waekup.  */
190 5:      leal    cond_lock-cond_futex(%ebx), %eax
191 #if (LLL_SHARED-LLL_PRIVATE) > 255
192         xorl    %ecx, %ecx
193 #endif
194         cmpl    $-1, dep_mutex-cond_futex(%ebx)
195         setne   %cl
196         subl    $1, %ecx
197         andl    $(LLL_SHARED-LLL_PRIVATE), %ecx
198 #if LLL_PRIVATE != 0
199         addl    $LLL_PRIVATE, %ecx
200 #endif
201         call    __lll_unlock_wake
202         jmp     6b
204         /* Unlock in loop requires waekup.  */
205 7:      leal    cond_lock-cond_futex(%ebx), %eax
206 #if (LLL_SHARED-LLL_PRIVATE) > 255
207         xorl    %ecx, %ecx
208 #endif
209         cmpl    $-1, dep_mutex-cond_futex(%ebx)
210         setne   %cl
211         subl    $1, %ecx
212         andl    $(LLL_SHARED-LLL_PRIVATE), %ecx
213 #if LLL_PRIVATE != 0
214         addl    $LLL_PRIVATE, %ecx
215 #endif
216         call    __lll_unlock_wake
217         jmp     8b
219 9:      /* The futex requeue functionality is not available.  */
220         movl    $0x7fffffff, %edx
221 #if FUTEX_PRIVATE_FLAG > 255
222         xorl    %ecx, %ecx
223 #endif
224         cmpl    $-1, dep_mutex-cond_futex(%ebx)
225         sete    %cl
226         subl    $1, %ecx
227 #ifdef __ASSUME_PRIVATE_FUTEX
228         andl    $FUTEX_PRIVATE_FLAG, %ecx
229 #else
230         andl    %gs:PRIVATE_FUTEX, %ecx
231 #endif
232         addl    $FUTEX_WAKE, %ecx
233         movl    $SYS_futex, %eax
234         ENTER_KERNEL
235         jmp     10b
236         cfi_endproc
237         .size   __pthread_cond_broadcast, .-__pthread_cond_broadcast
238 versioned_symbol (libpthread, __pthread_cond_broadcast, pthread_cond_broadcast,
239                   GLIBC_2_3_2)