c9b3d8b7bc4c1692b65eb1cc58a0b4ceb9322dff
[kopensolaris-gnu/glibc.git] / nptl / sysdeps / unix / sysv / linux / i386 / i486 / pthread_barrier_wait.S
1 /* Copyright (C) 2002, 2003 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, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 #include <sysdep.h>
21 #include <lowlevelbarrier.h>
22
23 #define SYS_futex       240
24 #define FUTEX_WAIT      0
25 #define FUTEX_WAKE      1
26
27 #ifndef UP
28 # define LOCK lock
29 #else
30 # define LOCK
31 #endif
32
33
34         .text
35
36         .globl  pthread_barrier_wait
37         .type   pthread_barrier_wait,@function
38         .align  16
39 pthread_barrier_wait:
40         pushl   %ebx
41
42         movl    8(%esp), %ebx
43
44         /* Get the mutex.  */
45         orl     $-1, %eax
46         LOCK
47         xaddl   %eax, MUTEX(%ebx)
48         jne     1f
49
50         /* One less waiter.  If this was the last one needed wake
51            everybody.  */
52 2:      subl    $1, LEFT(%ebx)
53         je      3f
54
55         /* There are more threads to come.  */
56         pushl   %esi
57
58 #if CURR_EVENT == 0
59         movl    (%ebx), %edx
60 #else
61         movl    CURR_EVENT(%ebx), %edx
62 #endif
63
64         /* Release the mutex.  */
65         LOCK
66         addl    $1, MUTEX(%ebx)
67         jng     6f
68
69         /* Wait for the remaining threads.  The call will return immediately
70            if the CURR_EVENT memory has meanwhile been changed.  */
71 7:      xorl    %ecx, %ecx              /* movl $FUTEX_WAIT, %ecx */
72         xorl    %esi, %esi
73 8:      movl    $SYS_futex, %eax
74         ENTER_KERNEL
75
76         /* Don't return on spurious wakeups.  The syscall does not change
77            any register except %eax so there is no need to reload any of
78            them.  */
79 #if CURR_EVENT == 0
80         cmpl    %edx, (%ebx)
81 #else
82         cmpl    %edx, CURR_EVENT(%ebx)
83 #endif
84         je,pn   8b
85
86         /* Note: %esi is still zero.  */
87         movl    %esi, %eax              /* != PTHREAD_BARRIER_SERIAL_THREAD */
88
89         popl    %esi
90         popl    %ebx
91         ret
92
93         /* The necessary number of threads arrived.  */
94 3:      movl    INIT_COUNT(%ebx), %eax
95         movl    %eax, LEFT(%ebx)
96 #if CURR_EVENT == 0
97         addl    $1, (%ebx)
98 #else
99         addl    $1, CURR_EVENT(%ebx)
100 #endif
101
102         /* Wake up all waiters.  The count is a signed number in the kernel
103            so 0x7fffffff is the highest value.  */
104         movl    $0x7fffffff, %edx
105         movl    $FUTEX_WAKE, %ecx
106         movl    $SYS_futex, %eax
107         ENTER_KERNEL
108
109         /* Release the mutex.  We cannot release the lock before
110            waking the waiting threads since otherwise a new thread might
111            arrive and gets waken up, too.  */
112         LOCK
113         addl    $1, MUTEX(%ebx)
114         jng     4f
115
116 5:      orl     $-1, %eax               /* == PTHREAD_BARRIER_SERIAL_THREAD */
117
118         popl    %ebx
119         ret
120
121 1:      leal    MUTEX(%ebx), %ecx
122         call    __lll_lock_wait
123         jmp     2b
124
125 4:      leal    MUTEX(%ebx), %eax
126         call    __lll_unlock_wake
127         jmp     5b
128
129 6:      leal    MUTEX(%ebx), %eax
130         call    __lll_unlock_wake
131         jmp     7b
132         .size   pthread_barrier_wait,.-pthread_barrier_wait