Update copyright dates with scripts/update-copyrights.
[glibc.git] / sysdeps / unix / sysv / linux / x86_64 / pthread_barrier_wait.S
blob69ecc1816aae6b08798d83461d3f33d0a46584e6
1 /* Copyright (C) 2002-2015 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>
24         .text
26         .globl  pthread_barrier_wait
27         .type   pthread_barrier_wait,@function
28         .align  16
29 pthread_barrier_wait:
30         /* Get the mutex.  */
31         xorl    %eax, %eax
32         movl    $1, %esi
33         LOCK
34         cmpxchgl %esi, MUTEX(%rdi)
35         jnz     1f
37         /* One less waiter.  If this was the last one needed wake
38            everybody.  */
39 2:      decl    LEFT(%rdi)
40         je      3f
42         /* There are more threads to come.  */
43 #if CURR_EVENT == 0
44         movl    (%rdi), %edx
45 #else
46         movl    CURR_EVENT(%rdi), %edx
47 #endif
49         /* Release the mutex.  */
50         LOCK
51         decl    MUTEX(%rdi)
52         jne     6f
54         /* Wait for the remaining threads.  The call will return immediately
55            if the CURR_EVENT memory has meanwhile been changed.  */
57 #if FUTEX_WAIT == 0
58         movl    PRIVATE(%rdi), %esi
59 #else
60         movl    $FUTEX_WAIT, %esi
61         orl     PRIVATE(%rdi), %esi
62 #endif
63         xorq    %r10, %r10
64 8:      movl    $SYS_futex, %eax
65         syscall
67         /* Don't return on spurious wakeups.  The syscall does not change
68            any register except %eax so there is no need to reload any of
69            them.  */
70 #if CURR_EVENT == 0
71         cmpl    %edx, (%rdi)
72 #else
73         cmpl    %edx, CURR_EVENT(%rdi)
74 #endif
75         je      8b
77         /* Increment LEFT.  If this brings the count back to the
78            initial count unlock the object.  */
79         movl    $1, %edx
80         movl    INIT_COUNT(%rdi), %eax
81         LOCK
82         xaddl   %edx, LEFT(%rdi)
83         subl    $1, %eax
84         cmpl    %eax, %edx
85         jne,pt  10f
87         /* Release the mutex.  We cannot release the lock before
88            waking the waiting threads since otherwise a new thread might
89            arrive and gets waken up, too.  */
90         LOCK
91         decl    MUTEX(%rdi)
92         jne     9f
94 10:     xorl    %eax, %eax              /* != PTHREAD_BARRIER_SERIAL_THREAD */
96         retq
98         /* The necessary number of threads arrived.  */
100 #if CURR_EVENT == 0
101         incl    (%rdi)
102 #else
103         incl    CURR_EVENT(%rdi)
104 #endif
106         /* Wake up all waiters.  The count is a signed number in the kernel
107            so 0x7fffffff is the highest value.  */
108         movl    $0x7fffffff, %edx
109         movl    $FUTEX_WAKE, %esi
110         orl     PRIVATE(%rdi), %esi
111         movl    $SYS_futex, %eax
112         syscall
114         /* Increment LEFT.  If this brings the count back to the
115            initial count unlock the object.  */
116         movl    $1, %edx
117         movl    INIT_COUNT(%rdi), %eax
118         LOCK
119         xaddl   %edx, LEFT(%rdi)
120         subl    $1, %eax
121         cmpl    %eax, %edx
122         jne,pt  5f
124         /* Release the mutex.  We cannot release the lock before
125            waking the waiting threads since otherwise a new thread might
126            arrive and gets waken up, too.  */
127         LOCK
128         decl    MUTEX(%rdi)
129         jne     4f
131 5:      orl     $-1, %eax               /* == PTHREAD_BARRIER_SERIAL_THREAD */
133         retq
135 1:      movl    PRIVATE(%rdi), %esi
136         addq    $MUTEX, %rdi
137         xorl    $LLL_SHARED, %esi
138         callq   __lll_lock_wait
139         subq    $MUTEX, %rdi
140         jmp     2b
142 4:      movl    PRIVATE(%rdi), %esi
143         addq    $MUTEX, %rdi
144         xorl    $LLL_SHARED, %esi
145         callq   __lll_unlock_wake
146         jmp     5b
148 6:      movl    PRIVATE(%rdi), %esi
149         addq    $MUTEX, %rdi
150         xorl    $LLL_SHARED, %esi
151         callq   __lll_unlock_wake
152         subq    $MUTEX, %rdi
153         jmp     7b
155 9:      movl    PRIVATE(%rdi), %esi
156         addq    $MUTEX, %rdi
157         xorl    $LLL_SHARED, %esi
158         callq   __lll_unlock_wake
159         jmp     10b
160         .size   pthread_barrier_wait,.-pthread_barrier_wait