Update copyright notices with scripts/update-copyrights
[glibc.git] / nptl / sysdeps / unix / sysv / linux / i386 / i486 / pthread_barrier_wait.S
blobaa755a1737edf0c133da358ce0dd006f03f25f78
1 /* Copyright (C) 2002-2014 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 <lowlevellock.h>
21 #include <lowlevelbarrier.h>
23         .text
25         .globl  pthread_barrier_wait
26         .type   pthread_barrier_wait,@function
27         .align  16
28 pthread_barrier_wait:
29         cfi_startproc
30         pushl   %ebx
31         cfi_adjust_cfa_offset(4)
32         cfi_offset(%ebx, -8)
34         movl    8(%esp), %ebx
36         /* Get the mutex.  */
37         movl    $1, %edx
38         xorl    %eax, %eax
39         LOCK
40         cmpxchgl %edx, MUTEX(%ebx)
41         jnz     1f
43         /* One less waiter.  If this was the last one needed wake
44            everybody.  */
45 2:      subl    $1, LEFT(%ebx)
46         je      3f
48         /* There are more threads to come.  */
49         pushl   %esi
50         cfi_adjust_cfa_offset(4)
51         cfi_offset(%esi, -12)
53 #if CURR_EVENT == 0
54         movl    (%ebx), %edx
55 #else
56         movl    CURR_EVENT(%ebx), %edx
57 #endif
59         /* Release the mutex.  */
60         LOCK
61         subl    $1, MUTEX(%ebx)
62         jne     6f
64         /* Wait for the remaining threads.  The call will return immediately
65            if the CURR_EVENT memory has meanwhile been changed.  */
67 #if FUTEX_WAIT == 0
68         movl    PRIVATE(%ebx), %ecx
69 #else
70         movl    $FUTEX_WAIT, %ecx
71         orl     PRIVATE(%ebx), %ecx
72 #endif
73         xorl    %esi, %esi
74 8:      movl    $SYS_futex, %eax
75         ENTER_KERNEL
77         /* Don't return on spurious wakeups.  The syscall does not change
78            any register except %eax so there is no need to reload any of
79            them.  */
80 #if CURR_EVENT == 0
81         cmpl    %edx, (%ebx)
82 #else
83         cmpl    %edx, CURR_EVENT(%ebx)
84 #endif
85         je      8b
87         /* Increment LEFT.  If this brings the count back to the
88            initial count unlock the object.  */
89         movl    $1, %edx
90         movl    INIT_COUNT(%ebx), %ecx
91         LOCK
92         xaddl   %edx, LEFT(%ebx)
93         subl    $1, %ecx
94         cmpl    %ecx, %edx
95         jne     10f
97         /* Release the mutex.  We cannot release the lock before
98            waking the waiting threads since otherwise a new thread might
99            arrive and gets waken up, too.  */
100         LOCK
101         subl    $1, MUTEX(%ebx)
102         jne     9f
104         /* Note: %esi is still zero.  */
105 10:     movl    %esi, %eax              /* != PTHREAD_BARRIER_SERIAL_THREAD */
107         popl    %esi
108         cfi_adjust_cfa_offset(-4)
109         cfi_restore(%esi)
110         popl    %ebx
111         cfi_adjust_cfa_offset(-4)
112         cfi_restore(%ebx)
113         ret
115         cfi_adjust_cfa_offset(4)
116         cfi_offset(%ebx, -8)
118         /* The necessary number of threads arrived.  */
120 #if CURR_EVENT == 0
121         addl    $1, (%ebx)
122 #else
123         addl    $1, CURR_EVENT(%ebx)
124 #endif
126         /* Wake up all waiters.  The count is a signed number in the kernel
127            so 0x7fffffff is the highest value.  */
128         movl    $0x7fffffff, %edx
129         movl    $FUTEX_WAKE, %ecx
130         orl     PRIVATE(%ebx), %ecx
131         movl    $SYS_futex, %eax
132         ENTER_KERNEL
134         /* Increment LEFT.  If this brings the count back to the
135            initial count unlock the object.  */
136         movl    $1, %edx
137         movl    INIT_COUNT(%ebx), %ecx
138         LOCK
139         xaddl   %edx, LEFT(%ebx)
140         subl    $1, %ecx
141         cmpl    %ecx, %edx
142         jne     5f
144         /* Release the mutex.  We cannot release the lock before
145            waking the waiting threads since otherwise a new thread might
146            arrive and gets waken up, too.  */
147         LOCK
148         subl    $1, MUTEX(%ebx)
149         jne     4f
151 5:      orl     $-1, %eax               /* == PTHREAD_BARRIER_SERIAL_THREAD */
153         popl    %ebx
154         cfi_adjust_cfa_offset(-4)
155         cfi_restore(%ebx)
156         ret
158         cfi_adjust_cfa_offset(4)
159         cfi_offset(%ebx, -8)
160 1:      movl    PRIVATE(%ebx), %ecx
161         leal    MUTEX(%ebx), %edx
162         xorl    $LLL_SHARED, %ecx
163         call    __lll_lock_wait
164         jmp     2b
166 4:      movl    PRIVATE(%ebx), %ecx
167         leal    MUTEX(%ebx), %eax
168         xorl    $LLL_SHARED, %ecx
169         call    __lll_unlock_wake
170         jmp     5b
172         cfi_adjust_cfa_offset(4)
173         cfi_offset(%esi, -12)
174 6:      movl    PRIVATE(%ebx), %ecx
175         leal    MUTEX(%ebx), %eax
176         xorl    $LLL_SHARED, %ecx
177         call    __lll_unlock_wake
178         jmp     7b
180 9:      movl    PRIVATE(%ebx), %ecx
181         leal    MUTEX(%ebx), %eax
182         xorl    $LLL_SHARED, %ecx
183         call    __lll_unlock_wake
184         jmp     10b
185         cfi_endproc
186         .size   pthread_barrier_wait,.-pthread_barrier_wait