(pthread_barrier_wait): Don't save, load, and restore %esi for last thread.
[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
22 #define SYS_futex       240
23 #define FUTEX_WAIT      0
24 #define FUTEX_WAKE      1
25
26 #ifndef UP
27 # define LOCK lock
28 #else
29 # define LOCK
30 #endif
31
32 #define CURR_EVENT      0
33 #define MUTEX           4
34 #define LEFT            8
35 #define INIT_COUNT      12
36
37
38         .text
39
40         .globl  pthread_barrier_wait
41         .type   pthread_barrier_wait,@function
42         .align  16
43 pthread_barrier_wait:
44         pushl   %ebx
45
46         movl    8(%esp), %ebx
47
48         /* Get the mutex.  */
49         orl     $-1, %eax
50         LOCK
51         xaddl   %eax, MUTEX(%ebx)
52         jne     1f
53
54         /* One less waiter.  If this was the last one needed wake
55            everybody.  */
56 2:      decl    LEFT(%ebx)
57         je      3f
58
59         /* There are more threads to come.  */
60         pushl   %esi
61
62 #if CURR_EVENT == 0
63         movl    (%ebx), %edx
64 #else
65         movl    CURR_EVENT(%ebx), %edx
66 #endif
67
68         /* Release the mutex.  */
69         LOCK
70         incl    MUTEX(%ebx)
71         jng     6f
72
73         /* Wait for the remaining threads.  The call will return immediately
74            if the CURR_EVENT memory has meanwhile been changed.  */
75 7:      xorl    %ecx, %ecx              /* movl $FUTEX_WAIT, %ecx */
76         xorl    %esi, %esi
77 8:      movl    $SYS_futex, %eax
78         ENTER_KERNEL
79
80         /* Don't return on spurious wakeups.  The syscall does not change
81            any register except %eax so there is no need to reload any of
82            them.  */
83 #if CURR_EVENT == 0
84         cmpl    %edx, (%ebx)
85 #else
86         cmpl    %edx, CURR_EVENT(%ebx)
87 #endif
88         je,pn   8b
89
90         /* Note: %esi is still zero.  */
91         movl    %esi, %eax              /* != PTHREAD_BARRIER_SERIAL_THREAD */
92
93         popl    %esi
94         popl    %ebx
95         ret
96
97         /* The necessary number of threads arrived.  */
98 3:      movl    INIT_COUNT(%ebx), %eax
99         movl    %eax, LEFT(%ebx)
100 #if CURR_EVENT == 0
101         incl    (%ebx)
102 #else
103         incl    CURR_EVENT(%ebx)
104 #endif
105
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, %ecx
110         movl    $SYS_futex, %eax
111         ENTER_KERNEL
112
113         /* Release the mutex.  We cannot release the lock before
114            waking the waiting threads since otherwise a new thread might
115            arrive and gets waken up, too.  */
116         LOCK
117         incl    MUTEX(%ebx)
118         jng     4f
119
120 5:      orl     $-1, %eax               /* == PTHREAD_BARRIER_SERIAL_THREAD */
121
122         popl    %ebx
123         ret
124
125 1:      leal    MUTEX(%ebx), %ecx
126         call    __lll_lock_wait
127         jmp     2b
128
129 4:      leal    MUTEX(%ebx), %eax
130         call    __lll_unlock_wake
131         jmp     5b
132
133 6:      leal    MUTEX(%ebx), %eax
134         call    __lll_unlock_wake
135         jmp     7b
136         .size   pthread_barrier_wait,.-pthread_barrier_wait