]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S
update
[l4.git] / l4 / pkg / uclibc / lib / contrib / uclibc / libpthread / nptl / sysdeps / unix / sysv / linux / i386 / i486 / pthread_cond_broadcast.S
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.
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
16    License along with the GNU C Library; if not, see
17    <http://www.gnu.org/licenses/>.  */
18
19 #include <sysdep.h>
20 #include <lowlevellock.h>
21 #include <lowlevelcond.h>
22 #include <bits/kernel-features.h>
23 #include <pthread-pi-defines.h>
24 #include <pthread-errnos.h>
25 #include <tls.h>
26
27         .text
28
29         /* int pthread_cond_broadcast (pthread_cond_t *cond) */
30         .globl  __pthread_cond_broadcast
31         .type   __pthread_cond_broadcast, @function
32         .protected      __pthread_cond_broadcast
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
49
50         movl    20(%esp), %ebx
51
52         /* Get internal lock.  */
53         movl    $1, %edx
54         xorl    %eax, %eax
55         LOCK
56 #if cond_lock == 0
57         cmpxchgl %edx, (%ebx)
58 #else
59         cmpxchgl %edx, cond_lock(%ebx)
60 #endif
61         jnz     1f
62
63 2:      addl    $cond_futex, %ebx
64         movl    total_seq+4-cond_futex(%ebx), %eax
65         movl    total_seq-cond_futex(%ebx), %ebp
66         cmpl    wakeup_seq+4-cond_futex(%ebx), %eax
67         ja      3f
68         jb      4f
69         cmpl    wakeup_seq-cond_futex(%ebx), %ebp
70         jna     4f
71
72         /* Cause all currently waiting threads to recognize they are
73            woken up.  */
74 3:      movl    %ebp, wakeup_seq-cond_futex(%ebx)
75         movl    %eax, wakeup_seq-cond_futex+4(%ebx)
76         movl    %ebp, woken_seq-cond_futex(%ebx)
77         movl    %eax, woken_seq-cond_futex+4(%ebx)
78         addl    %ebp, %ebp
79         addl    $1, broadcast_seq-cond_futex(%ebx)
80         movl    %ebp, (%ebx)
81
82         /* Get the address of the mutex used.  */
83         movl    dep_mutex-cond_futex(%ebx), %edi
84
85         /* Unlock.  */
86         LOCK
87         subl    $1, cond_lock-cond_futex(%ebx)
88         jne     7f
89
90         /* Don't use requeue for pshared condvars.  */
91 8:      cmpl    $-1, %edi
92         je      9f
93
94         /* Do not use requeue for pshared condvars.  */
95         testl   $PS_BIT, MUTEX_KIND(%edi)
96         jne     9f
97
98         /* Requeue to a non-robust PI mutex if the PI bit is set and
99            the robust bit is not set.  */
100         movl    MUTEX_KIND(%edi), %eax
101         andl    $(ROBUST_BIT|PI_BIT), %eax
102         cmpl    $PI_BIT, %eax
103         je      81f
104
105         /* Wake up all threads.  */
106 #ifdef __ASSUME_PRIVATE_FUTEX
107         movl    $(FUTEX_CMP_REQUEUE|FUTEX_PRIVATE_FLAG), %ecx
108 #else
109         movl    %gs:PRIVATE_FUTEX, %ecx
110         orl     $FUTEX_CMP_REQUEUE, %ecx
111 #endif
112         movl    $SYS_futex, %eax
113         movl    $0x7fffffff, %esi
114         movl    $1, %edx
115         /* Get the address of the futex involved.  */
116 # if MUTEX_FUTEX != 0
117         addl    $MUTEX_FUTEX, %edi
118 # endif
119 /* FIXME: Until Ingo fixes 4G/4G vDSO, 6 arg syscalls are broken for sysenter.
120         ENTER_KERNEL  */
121         int     $0x80
122
123         /* For any kind of error, which mainly is EAGAIN, we try again
124            with WAKE.  The general test also covers running on old
125            kernels.  */
126         cmpl    $0xfffff001, %eax
127         jae     9f
128
129 6:      xorl    %eax, %eax
130         popl    %ebp
131         cfi_adjust_cfa_offset(-4)
132         cfi_restore(%ebp)
133         popl    %edi
134         cfi_adjust_cfa_offset(-4)
135         cfi_restore(%edi)
136         popl    %esi
137         cfi_adjust_cfa_offset(-4)
138         cfi_restore(%esi)
139         popl    %ebx
140         cfi_adjust_cfa_offset(-4)
141         cfi_restore(%ebx)
142         ret
143
144         cfi_restore_state
145
146 81:     movl    $(FUTEX_CMP_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %ecx
147         movl    $SYS_futex, %eax
148         movl    $0x7fffffff, %esi
149         movl    $1, %edx
150         /* Get the address of the futex involved.  */
151 # if MUTEX_FUTEX != 0
152         addl    $MUTEX_FUTEX, %edi
153 # endif
154         int     $0x80
155
156         /* For any kind of error, which mainly is EAGAIN, we try again
157         with WAKE.  The general test also covers running on old
158         kernels.  */
159         cmpl    $0xfffff001, %eax
160         jb      6b
161         jmp     9f
162
163         /* Initial locking failed.  */
164 1:
165 #if cond_lock == 0
166         movl    %ebx, %edx
167 #else
168         leal    cond_lock(%ebx), %edx
169 #endif
170 #if (LLL_SHARED-LLL_PRIVATE) > 255
171         xorl    %ecx, %ecx
172 #endif
173         cmpl    $-1, dep_mutex(%ebx)
174         setne   %cl
175         subl    $1, %ecx
176         andl    $(LLL_SHARED-LLL_PRIVATE), %ecx
177 #if LLL_PRIVATE != 0
178         addl    $LLL_PRIVATE, %ecx
179 #endif
180         call    __lll_lock_wait
181         jmp     2b
182
183         .align  16
184         /* Unlock.  */
185 4:      LOCK
186         subl    $1, cond_lock-cond_futex(%ebx)
187         je      6b
188
189         /* Unlock in loop requires wakeup.  */
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
203
204         /* Unlock in loop requires wakeup.  */
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
218
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     6b
236         cfi_endproc
237         .size   __pthread_cond_broadcast, .-__pthread_cond_broadcast
238 weak_alias(__pthread_cond_broadcast, pthread_cond_broadcast)