]>
Commit | Line | Data |
---|---|---|
37c054c7 | 1 | /* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. |
76a50749 UD |
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> | |
6a4263e3 | 21 | #include <lowlevelbarrier.h> |
76a50749 UD |
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 | ||
76a50749 UD |
33 | |
34 | .text | |
35 | ||
36 | .globl pthread_barrier_wait | |
37 | .type pthread_barrier_wait,@function | |
38 | .align 16 | |
39 | pthread_barrier_wait: | |
76a50749 UD |
40 | pushl %ebx |
41 | ||
bd8bb78b | 42 | movl 8(%esp), %ebx |
76a50749 UD |
43 | |
44 | /* Get the mutex. */ | |
71451de2 UD |
45 | movl $1, %edx |
46 | xorl %eax, %eax | |
76a50749 | 47 | LOCK |
71451de2 | 48 | cmpxchgl %edx, MUTEX(%ebx) |
3a226d33 | 49 | jnz 1f |
76a50749 UD |
50 | |
51 | /* One less waiter. If this was the last one needed wake | |
52 | everybody. */ | |
ccf1d573 | 53 | 2: subl $1, LEFT(%ebx) |
76a50749 UD |
54 | je 3f |
55 | ||
56 | /* There are more threads to come. */ | |
bd8bb78b UD |
57 | pushl %esi |
58 | ||
b1b8e747 UD |
59 | #if CURR_EVENT == 0 |
60 | movl (%ebx), %edx | |
61 | #else | |
76a50749 | 62 | movl CURR_EVENT(%ebx), %edx |
b1b8e747 | 63 | #endif |
76a50749 UD |
64 | |
65 | /* Release the mutex. */ | |
66 | LOCK | |
71451de2 UD |
67 | subl $1, MUTEX(%ebx) |
68 | jne 6f | |
76a50749 UD |
69 | |
70 | /* Wait for the remaining threads. The call will return immediately | |
71 | if the CURR_EVENT memory has meanwhile been changed. */ | |
bd8bb78b UD |
72 | 7: xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */ |
73 | xorl %esi, %esi | |
76a50749 | 74 | 8: movl $SYS_futex, %eax |
097eca29 | 75 | ENTER_KERNEL |
76a50749 UD |
76 | |
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. */ | |
b1b8e747 UD |
80 | #if CURR_EVENT == 0 |
81 | cmpl %edx, (%ebx) | |
82 | #else | |
76a50749 | 83 | cmpl %edx, CURR_EVENT(%ebx) |
b1b8e747 | 84 | #endif |
a334319f | 85 | je,pn 8b |
76a50749 | 86 | |
37c054c7 UD |
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 | |
a334319f | 95 | jne,pt 10f |
37c054c7 UD |
96 | |
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 | |
103 | ||
76a50749 | 104 | /* Note: %esi is still zero. */ |
37c054c7 | 105 | 10: movl %esi, %eax /* != PTHREAD_BARRIER_SERIAL_THREAD */ |
76a50749 | 106 | |
76a50749 | 107 | popl %esi |
bd8bb78b | 108 | popl %ebx |
76a50749 UD |
109 | ret |
110 | ||
111 | /* The necessary number of threads arrived. */ | |
37c054c7 | 112 | 3: |
b1b8e747 | 113 | #if CURR_EVENT == 0 |
ccf1d573 | 114 | addl $1, (%ebx) |
b1b8e747 | 115 | #else |
ccf1d573 | 116 | addl $1, CURR_EVENT(%ebx) |
b1b8e747 | 117 | #endif |
76a50749 UD |
118 | |
119 | /* Wake up all waiters. The count is a signed number in the kernel | |
120 | so 0x7fffffff is the highest value. */ | |
121 | movl $0x7fffffff, %edx | |
122 | movl $FUTEX_WAKE, %ecx | |
123 | movl $SYS_futex, %eax | |
097eca29 | 124 | ENTER_KERNEL |
76a50749 | 125 | |
37c054c7 UD |
126 | /* Increment LEFT. If this brings the count back to the |
127 | initial count unlock the object. */ | |
128 | movl $1, %edx | |
129 | movl INIT_COUNT(%ebx), %ecx | |
130 | LOCK | |
131 | xaddl %edx, LEFT(%ebx) | |
132 | subl $1, %ecx | |
133 | cmpl %ecx, %edx | |
a334319f | 134 | jne,pt 5f |
37c054c7 | 135 | |
206a5cde UD |
136 | /* Release the mutex. We cannot release the lock before |
137 | waking the waiting threads since otherwise a new thread might | |
138 | arrive and gets waken up, too. */ | |
76a50749 | 139 | LOCK |
71451de2 UD |
140 | subl $1, MUTEX(%ebx) |
141 | jne 4f | |
76a50749 UD |
142 | |
143 | 5: orl $-1, %eax /* == PTHREAD_BARRIER_SERIAL_THREAD */ | |
144 | ||
145 | popl %ebx | |
76a50749 UD |
146 | ret |
147 | ||
148 | 1: leal MUTEX(%ebx), %ecx | |
71451de2 | 149 | call __lll_mutex_lock_wait |
76a50749 UD |
150 | jmp 2b |
151 | ||
152 | 4: leal MUTEX(%ebx), %eax | |
71451de2 | 153 | call __lll_mutex_unlock_wake |
76a50749 UD |
154 | jmp 5b |
155 | ||
156 | 6: leal MUTEX(%ebx), %eax | |
71451de2 | 157 | call __lll_mutex_unlock_wake |
76a50749 | 158 | jmp 7b |
37c054c7 UD |
159 | |
160 | 9: leal MUTEX(%ebx), %eax | |
161 | call __lll_mutex_unlock_wake | |
162 | jmp 10b | |
76a50749 | 163 | .size pthread_barrier_wait,.-pthread_barrier_wait |