(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_cond_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 <shlib-compat.h>
22 #include <lowlevelcond.h>
23 #include <tcb-offsets.h>
24
25 #ifdef UP
26 # define LOCK
27 #else
28 # define LOCK lock
29 #endif
30
31 #define SYS_futex               240
32 #define FUTEX_WAIT              0
33 #define FUTEX_WAKE              1
34
35
36         .text
37
38         .align  16
39         .type   __condvar_cleanup, @function
40         .globl  __condvar_cleanup
41         .hidden __condvar_cleanup
42 __condvar_cleanup:
43         pushl   %ebx
44         pushl   %esi
45         movl    12(%esp), %esi
46
47         /* Get internal lock.  */
48         movl    4(%esi), %ebx
49         movl    $1, %eax
50         LOCK
51 #if cond_lock == 0
52         xaddl   %eax, (%ebx)
53 #else
54         xaddl   %eax, cond_lock(%ebx)
55 #endif
56         testl   %eax, %eax
57         je      1f
58
59 #if cond_lock == 0
60         movl    %ebx, %ecx
61 #else
62         leal    cond_lock(%ebx), %ecx
63 #endif
64         call    __lll_mutex_lock_wait
65
66 1:      addl    $1, wakeup_seq(%ebx)
67         adcl    $0, wakeup_seq+4(%ebx)
68
69         addl    $1, woken_seq(%ebx)
70         adcl    $0, woken_seq+4(%ebx)
71
72         LOCK
73 #if cond_lock == 0
74         decl    (%ebx)
75 #else
76         decl    cond_lock(%ebx)
77 #endif
78         je      2f
79 #if cond_lock == 0
80         movl    %ebx, %eax
81 #else
82         leal    cond_lock(%ebx), %eax
83 #endif
84         call    __lll_mutex_unlock_wake
85
86         /* Lock the mutex unless asnychronous cancellation is in effect.  */
87 2:      testl   $2, (%esi)
88         jne     3f
89
90         pushl   8(%esi)
91         call    __pthread_mutex_lock_internal
92         popl    %eax
93
94 3:      popl    %esi
95         popl    %ebx
96         ret
97         .size   __condvar_cleanup, .-__condvar_cleanup
98
99
100 /* int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)  */
101         .globl  __pthread_cond_wait
102         .type   __pthread_cond_wait, @function
103         .align  16
104 __pthread_cond_wait:
105
106         pushl   %edi
107         pushl   %esi
108         pushl   %ebx
109
110         xorl    %esi, %esi
111         movl    16(%esp), %ebx
112
113         /* Get internal lock.  */
114         movl    $1, %eax
115         LOCK
116 #if cond_lock == 0
117         xaddl   %eax, (%ebx)
118 #else
119         xaddl   %eax, cond_lock(%ebx)
120 #endif
121         testl   %eax, %eax
122         jne     1f
123
124         /* Unlock the mutex.  */
125 2:      pushl   20(%esp)
126         call    __pthread_mutex_unlock_internal
127
128         testl   %eax, %eax
129         jne     12f
130
131         addl    $1, total_seq(%ebx)
132         adcl    $0, total_seq+4(%ebx)
133
134         /* Install cancellation handler.  */
135 #ifdef PIC
136         call    __i686.get_pc_thunk.cx
137         addl    $_GLOBAL_OFFSET_TABLE_, %ecx
138         leal    __condvar_cleanup@GOTOFF(%ecx), %eax
139 #else
140         leal    __condvar_cleanup, %eax
141 #endif
142         subl    $32, %esp
143         leal    20(%esp), %edx
144         movl    %esp, 8(%esp)
145         movl    %eax, 4(%esp)
146         movl    %edx, (%esp)
147         call    __pthread_cleanup_push
148
149         /* Get and store current wakeup_seq value.  */
150         movl    56(%esp), %ecx
151         movl    wakeup_seq(%ebx), %edi
152         movl    wakeup_seq+4(%ebx), %edx
153         movl    %edi, 12(%esp)
154         movl    %edx, 16(%esp)
155         /* Prepare structure passed to cancellation handler.  */
156         movl    %ebx, 4(%esp)
157         movl    %ecx, 8(%esp)
158
159         /* Unlock.  */
160 8:      LOCK
161 #if cond_lock == 0
162         decl    (%ebx)
163 #else
164         decl    cond_lock(%ebx)
165 #endif
166         jne     3f
167
168 4:      call    __pthread_enable_asynccancel
169         movl    %eax, (%esp)
170
171         movl    %esi, %ecx      /* movl $FUTEX_WAIT, %ecx */
172         movl    %edi, %edx
173         addl    $wakeup_seq, %ebx
174         movl    $SYS_futex, %eax
175         ENTER_KERNEL
176         subl    $wakeup_seq, %ebx
177
178         call    __pthread_disable_asynccancel
179
180         /* Lock.  */
181         movl    $1, %eax
182         LOCK
183 #if cond_lock == 0
184         xaddl   %eax, (%ebx)
185 #else
186         xaddl   %eax, cond_lock(%ebx)
187 #endif
188         testl   %eax, %eax
189         jne     5f
190
191 6:      movl    woken_seq(%ebx), %eax
192         movl    woken_seq+4(%ebx), %ecx
193
194         movl    wakeup_seq(%ebx), %edi
195         movl    wakeup_seq+4(%ebx), %edx
196
197         cmpl    16(%esp), %ecx
198         ja      7f
199         jb      8b
200         cmpl    12(%esp), %eax
201         jb      8b
202
203 7:      cmpl    %ecx, %edx
204         ja      9f
205         jb      8b
206         cmp     %eax, %edi
207         jna     8b
208
209 9:      addl    $1, woken_seq(%ebx)
210         adcl    $0, woken_seq+4(%ebx)
211
212         LOCK
213 #if cond_lock == 0
214         decl    (%ebx)
215 #else
216         decl    cond_lock(%ebx)
217 #endif
218         jne     10f
219
220         /* Remove cancellation handler.  */
221 11:     leal    20(%esp), %edx
222         movl    $0, 4(%esp)
223         movl    %edx, (%esp)
224         call    __pthread_cleanup_pop
225
226         /* Trick ahead:  8(%esp) contains the address of the mutex.  */
227         addl    $8, %esp
228         call    __pthread_mutex_lock_internal
229         addl    $28, %esp
230
231 14:     popl    %ebx
232         popl    %esi
233         popl    %edi
234
235         /* We return the result of the mutex_lock operation.  */
236         ret
237
238         /* Initial locking failed.  */
239 1:
240 #if cond_lock == 0
241         movl    %ebx, %ecx
242 #else
243         leal    cond_lock(%ebx), %ecx
244 #endif
245         call    __lll_mutex_lock_wait
246         jmp     2b
247
248         /* Unlock in loop requires waekup.  */
249 3:
250 #if cond_lock == 0
251         movl    %ebx, %eax
252 #else
253         leal    cond_lock(%ebx), %eax
254 #endif
255         call    __lll_mutex_unlock_wake
256         jmp     4b
257
258         /* Locking in loop failed.  */
259 5:
260 #if cond_lock == 0
261         movl    %ebx, %ecx
262 #else
263         leal    cond_lock(%ebx), %ecx
264 #endif
265         call    __lll_mutex_lock_wait
266         jmp     6b
267
268         /* Unlock after loop requires wakeup.  */
269 10:
270 #if cond_lock == 0
271         movl    %ebx, %eax
272 #else
273         leal    cond_lock(%ebx), %eax
274 #endif
275         call    __lll_mutex_unlock_wake
276         jmp     11b
277
278         /* The initial unlocking of the mutex failed.  */
279 12:     movl    %eax, (%esp)
280         LOCK
281 #if cond_lock == 0
282         decl    (%ebx)
283 #else
284         decl    cond_lock(%ebx)
285 #endif
286         jne     13f
287
288 #if cond_lock == 0
289         movl    %ebx, %eax
290 #else
291         leal    cond_lock(%ebx), %eax
292 #endif
293         call    __lll_mutex_unlock_wake
294
295 13:     popl    %eax
296         jmp     14b
297         .size   __pthread_cond_wait, .-__pthread_cond_wait
298 versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
299                   GLIBC_2_3_2)
300
301
302 #ifdef PIC
303         .section .gnu.linkonce.t.__i686.get_pc_thunk.cx,"ax",@progbits
304         .globl  __i686.get_pc_thunk.cx
305         .hidden __i686.get_pc_thunk.cx
306         .type   __i686.get_pc_thunk.cx,@function
307 __i686.get_pc_thunk.cx:
308         movl (%esp), %ecx;
309         ret
310         .size   __i686.get_pc_thunk.cx,.-__i686.get_pc_thunk.cx
311 #endif