(CFLAGS-tst-align.c): Add -mpreferred-stack-boundary=4.
[glibc.git] / nptl / sysdeps / unix / sysv / linux / i386 / i486 / pthread_cond_broadcast.S
blob5471c1c9275403dc20811e82a0e594e5f49f5136
1 /* Copyright (C) 2002, 2003, 2004 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 <lowlevelcond.h>
23 #include <kernel-features.h>
25 #ifdef UP
26 # define LOCK
27 #else
28 # define LOCK lock
29 #endif
31 #define SYS_futex               240
32 #define FUTEX_WAIT              0
33 #define FUTEX_WAKE              1
34 #define FUTEX_REQUEUE           3
35 #define FUTEX_CMP_REQUEUE       4
37 #define EINVAL                  22
40         .text
42         /* int pthread_cond_broadcast (pthread_cond_t *cond) */
43         .globl  __pthread_cond_broadcast
44         .type   __pthread_cond_broadcast, @function
45         .align  16
46 __pthread_cond_broadcast:
48         pushl   %ebx
49         pushl   %esi
50         pushl   %edi
51         pushl   %ebp
53         movl    20(%esp), %ebx
55         /* Get internal lock.  */
56         movl    $1, %edx
57         xorl    %eax, %eax
58         LOCK
59 #if cond_lock == 0
60         cmpxchgl %edx, (%ebx)
61 #else
62         cmpxchgl %edx, cond_lock(%ebx)
63 #endif
64         jnz     1f
66 2:      addl    $cond_futex, %ebx
67         movl    total_seq+4-cond_futex(%ebx), %eax
68         movl    total_seq-cond_futex(%ebx), %ebp
69         cmpl    wakeup_seq+4-cond_futex(%ebx), %eax
70         ja      3f
71         jb      4f
72         cmpl    wakeup_seq-cond_futex(%ebx), %ebp
73         jna     4f
75         /* Cause all currently waiting threads to recognize they are
76            woken up.  */
77 3:      movl    %ebp, wakeup_seq-cond_futex(%ebx)
78         movl    %eax, wakeup_seq-cond_futex+4(%ebx)
79         movl    %ebp, woken_seq-cond_futex(%ebx)
80         movl    %eax, woken_seq-cond_futex+4(%ebx)
81         addl    %ebp, %ebp
82         addl    $1, broadcast_seq-cond_futex(%ebx)
83         movl    %ebp, (%ebx)
85         /* Get the address of the mutex used.  */
86         movl    dep_mutex-cond_futex(%ebx), %edi
88         /* Unlock.  */
89         LOCK
90         subl    $1, cond_lock-cond_futex(%ebx)
91         jne     7f
93         /* Don't use requeue for pshared condvars.  */
94 8:      cmpl    $-1, %edi
95         je      9f
97         /* Wake up all threads.  */
98         movl    $FUTEX_CMP_REQUEUE, %ecx
99         movl    $SYS_futex, %eax
100         movl    $0x7fffffff, %esi
101         movl    $1, %edx
102         /* Get the address of the futex involved.  */
103 # if MUTEX_FUTEX != 0
104         addl    $MUTEX_FUTEX, %edi
105 # endif
106 /* FIXME: Until Ingo fixes 4G/4G vDSO, 6 arg syscalls are broken for sysenter.
107         ENTER_KERNEL  */
108         int     $0x80
110         /* For any kind of error, which mainly is EAGAIN, we try again
111            with WAKE.  The general test also covers running on old
112            kernels.  */
113         cmpl    $0xfffff001, %eax
114         jae     9f
116 10:     xorl    %eax, %eax
117         popl    %ebp
118         popl    %edi
119         popl    %esi
120         popl    %ebx
121         ret
123         .align  16
124         /* Unlock.  */
125 4:      LOCK
126         subl    $1, cond_lock-cond_futex(%ebx)
127         jne     5f
129 6:      xorl    %eax, %eax
130         popl    %ebp
131         popl    %edi
132         popl    %esi
133         popl    %ebx
134         ret
136         /* Initial locking failed.  */
138 #if cond_lock == 0
139         movl    %ebx, %ecx
140 #else
141         leal    cond_lock(%ebx), %ecx
142 #endif
143         call    __lll_mutex_lock_wait
144         jmp     2b
146         /* Unlock in loop requires waekup.  */
147 5:      leal    cond_lock-cond_futex(%ebx), %eax
148         call    __lll_mutex_unlock_wake
149         jmp     6b
151         /* Unlock in loop requires waekup.  */
152 7:      leal    cond_lock-cond_futex(%ebx), %eax
153         call    __lll_mutex_unlock_wake
154         jmp     8b
156 9:      /* The futex requeue functionality is not available.  */
157         movl    $0x7fffffff, %edx
158         movl    $FUTEX_WAKE, %ecx
159         movl    $SYS_futex, %eax
160         ENTER_KERNEL
161         jmp     10b
162         .size   __pthread_cond_broadcast, .-__pthread_cond_broadcast
163 versioned_symbol (libpthread, __pthread_cond_broadcast, pthread_cond_broadcast,
164                   GLIBC_2_3_2)