(CFLAGS-tst-align.c): Add -mpreferred-stack-boundary=4.
[glibc.git] / nptl / sysdeps / unix / sysv / linux / i386 / i486 / pthread_cond_wait.S
blobd282785151679352bcc28f992c545a577e8d43a8
1 /* Copyright (C) 2002, 2003, 2004 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, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
20 #include <sysdep.h>
21 #include <shlib-compat.h>
22 #include <lowlevelcond.h>
23 #include <tcb-offsets.h>
25 #ifdef UP
26 # define LOCK
27 #else
28 # define LOCK lock
29 #endif
31 #define SYS_futex               240
32 #define FUTEX_WAIT              0
33 #define FUTEX_WAKE              1
36         .text
38 /* int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)  */
39         .globl  __pthread_cond_wait
40         .type   __pthread_cond_wait, @function
41         .align  16
42 __pthread_cond_wait:
43 .LSTARTCODE:
45         pushl   %edi
46 .Lpush_edi:
47         pushl   %esi
48 .Lpush_esi:
49         pushl   %ebx
50 .Lpush_ebx:
52         xorl    %esi, %esi
53         movl    16(%esp), %ebx
55         /* Get internal lock.  */
56         movl    $1, %edx
57         xorl    %eax, %eax
58         LOCK
59 #if cond_lock == 0
60         cmpxchgl %edx, (%ebx)
61 #else
62         cmpxchgl %edx, cond_lock(%ebx)
63 #endif
64         jnz     1f
66         /* Store the reference to the mutex.  If there is already a
67            different value in there this is a bad user bug.  */
68 2:      cmpl    $-1, dep_mutex(%ebx)
69         movl    20(%esp), %eax
70         je      15f
71         movl    %eax, dep_mutex(%ebx)
73         /* Unlock the mutex.  */
74 15:     xorl    %edx, %edx
75         call    __pthread_mutex_unlock_usercnt
77         testl   %eax, %eax
78         jne     12f
80         addl    $1, total_seq(%ebx)
81         adcl    $0, total_seq+4(%ebx)
82         addl    $1, cond_futex(%ebx)
83         addl    $(1 << clock_bits), cond_nwaiters(%ebx)
85 #define FRAME_SIZE 16
86         subl    $FRAME_SIZE, %esp
87 .Lsubl:
89         /* Get and store current wakeup_seq value.  */
90         movl    wakeup_seq(%ebx), %edi
91         movl    wakeup_seq+4(%ebx), %edx
92         movl    broadcast_seq(%ebx), %eax
93         movl    %edi, 4(%esp)
94         movl    %edx, 8(%esp)
95         movl    %eax, 12(%esp)
97 8:      movl    cond_futex(%ebx), %edi
99         /* Unlock.  */
100         LOCK
101 #if cond_lock == 0
102         subl    $1, (%ebx)
103 #else
104         subl    $1, cond_lock(%ebx)
105 #endif
106         jne     3f
108 .LcleanupSTART:
109 4:      call    __pthread_enable_asynccancel
110         movl    %eax, (%esp)
112         movl    %esi, %ecx      /* movl $FUTEX_WAIT, %ecx */
113         movl    %edi, %edx
114         addl    $cond_futex, %ebx
115 .Ladd_cond_futex:
116         movl    $SYS_futex, %eax
117         ENTER_KERNEL
118         subl    $cond_futex, %ebx
119 .Lsub_cond_futex:
121         movl    (%esp), %eax
122         call    __pthread_disable_asynccancel
123 .LcleanupEND:
125         /* Lock.  */
126         movl    $1, %edx
127         xorl    %eax, %eax
128         LOCK
129 #if cond_lock == 0
130         cmpxchgl %edx, (%ebx)
131 #else
132         cmpxchgl %edx, cond_lock(%ebx)
133 #endif
134         jnz     5f
136 6:      movl    broadcast_seq(%ebx), %eax
137         cmpl    12(%esp), %eax
138         jne     16f
140         movl    woken_seq(%ebx), %eax
141         movl    woken_seq+4(%ebx), %ecx
143         movl    wakeup_seq(%ebx), %edi
144         movl    wakeup_seq+4(%ebx), %edx
146         cmpl    8(%esp), %edx
147         jne     7f
148         cmpl    4(%esp), %edi
149         je      8b
151 7:      cmpl    %ecx, %edx
152         jne     9f
153         cmp     %eax, %edi
154         je      8b
156 9:      addl    $1, woken_seq(%ebx)
157         adcl    $0, woken_seq+4(%ebx)
159         /* Unlock */
160 16:     subl    $(1 << clock_bits), cond_nwaiters(%ebx)
162         /* Wake up a thread which wants to destroy the condvar object.  */
163         movl    total_seq(%ebx), %eax
164         andl    total_seq+4(%ebx), %eax
165         cmpl    $0xffffffff, %eax
166         jne     17f
167         movl    cond_nwaiters(%ebx), %eax
168         andl    $~((1 << clock_bits) - 1), %eax
169         jne     17f
171         addl    $cond_nwaiters, %ebx
172         movl    $SYS_futex, %eax
173         movl    $FUTEX_WAKE, %ecx
174         movl    $1, %edx
175         ENTER_KERNEL
176         subl    $cond_nwaiters, %ebx
178 17:     LOCK
179 #if cond_lock == 0
180         subl    $1, (%ebx)
181 #else
182         subl    $1, cond_lock(%ebx)
183 #endif
184         jne     10f
186 11:     movl    20+FRAME_SIZE(%esp), %eax
187         call    __pthread_mutex_cond_lock
188         addl    $FRAME_SIZE, %esp
189 .Laddl:
191 14:     popl    %ebx
192 .Lpop_ebx:
193         popl    %esi
194 .Lpop_esi:
195         popl    %edi
196 .Lpop_edi:
198         /* We return the result of the mutex_lock operation.  */
199         ret
201         /* Initial locking failed.  */
203 .LSbl1:
204 #if cond_lock == 0
205         movl    %ebx, %ecx
206 #else
207         leal    cond_lock(%ebx), %ecx
208 #endif
209         call    __lll_mutex_lock_wait
210         jmp     2b
212         /* Unlock in loop requires waekup.  */
214 .LSbl2:
215 #if cond_lock == 0
216         movl    %ebx, %eax
217 #else
218         leal    cond_lock(%ebx), %eax
219 #endif
220         call    __lll_mutex_unlock_wake
221         jmp     4b
223         /* Locking in loop failed.  */
225 #if cond_lock == 0
226         movl    %ebx, %ecx
227 #else
228         leal    cond_lock(%ebx), %ecx
229 #endif
230         call    __lll_mutex_lock_wait
231         jmp     6b
233         /* Unlock after loop requires wakeup.  */
235 #if cond_lock == 0
236         movl    %ebx, %eax
237 #else
238         leal    cond_lock(%ebx), %eax
239 #endif
240         call    __lll_mutex_unlock_wake
241         jmp     11b
243         /* The initial unlocking of the mutex failed.  */
245 .LSbl3:
246         LOCK
247 #if cond_lock == 0
248         subl    $1, (%ebx)
249 #else
250         subl    $1, cond_lock(%ebx)
251 #endif
252         jne     14b
254         movl    %eax, %esi
255 #if cond_lock == 0
256         movl    %ebx, %eax
257 #else
258         leal    cond_lock(%ebx), %eax
259 #endif
260         call    __lll_mutex_unlock_wake
262         movl    %esi, %eax
263         jmp     14b
264         .size   __pthread_cond_wait, .-__pthread_cond_wait
265 versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
266                   GLIBC_2_3_2)
269         .type   __condvar_w_cleanup2, @function
270 __condvar_w_cleanup2:
271         subl    $cond_futex, %ebx
272         .size   __condvar_w_cleanup2, .-__condvar_w_cleanup2
273 .LSbl4:
274         .type   __condvar_w_cleanup, @function
275 __condvar_w_cleanup:
276         movl    %eax, %esi
278         /* Get internal lock.  */
279         movl    $1, %edx
280         xorl    %eax, %eax
281         LOCK
282 #if cond_lock == 0
283         cmpxchgl %edx, (%ebx)
284 #else
285         cmpxchgl %edx, cond_lock(%ebx)
286 #endif
287         jz      1f
289 #if cond_lock == 0
290         movl    %ebx, %ecx
291 #else
292         leal    cond_lock(%ebx), %ecx
293 #endif
294         call    __lll_mutex_lock_wait
296 1:      movl    broadcast_seq(%ebx), %eax
297         cmpl    12(%esp), %eax
298         jne     3f
300         addl    $1, wakeup_seq(%ebx)
301         adcl    $0, wakeup_seq+4(%ebx)
303         addl    $1, cond_futex(%ebx)
305         addl    $1, woken_seq(%ebx)
306         adcl    $0, woken_seq+4(%ebx)
308 3:      subl    $(1 << clock_bits), cond_nwaiters(%ebx)
310         /* Wake up a thread which wants to destroy the condvar object.  */
311         xorl    %edi, %edi
312         movl    total_seq(%ebx), %eax
313         andl    total_seq+4(%ebx), %eax
314         cmpl    $0xffffffff, %eax
315         jne     4f
316         movl    cond_nwaiters(%ebx), %eax
317         andl    $~((1 << clock_bits) - 1), %eax
318         jne     4f
320         addl    $cond_nwaiters, %ebx
321         movl    $SYS_futex, %eax
322         movl    $FUTEX_WAKE, %ecx
323         movl    $1, %edx
324         ENTER_KERNEL
325         subl    $cond_nwaiters, %ebx
326         movl    $1, %edi
328 4:      LOCK
329 #if cond_lock == 0
330         subl    $1, (%ebx)
331 #else
332         subl    $1, cond_lock(%ebx)
333 #endif
334         je      2f
336 #if cond_lock == 0
337         movl    %ebx, %eax
338 #else
339         leal    cond_lock(%ebx), %eax
340 #endif
341         call    __lll_mutex_unlock_wake
343         /* Wake up all waiters to make sure no signal gets lost.  */
344 2:      testl   %edi, %edi
345         jnz     5f
346         addl    $cond_futex, %ebx
347         movl    $FUTEX_WAKE, %ecx
348         movl    $SYS_futex, %eax
349         movl    $0x7fffffff, %edx
350         ENTER_KERNEL
352 5:      movl    20+FRAME_SIZE(%esp), %eax
353         call    __pthread_mutex_cond_lock
355         movl    %esi, (%esp)
356 .LcallUR:
357         call    _Unwind_Resume
358         hlt
359 .LENDCODE:
360         .size   __condvar_w_cleanup, .-__condvar_w_cleanup
363         .section .gcc_except_table,"a",@progbits
364 .LexceptSTART:
365         .byte   0xff                            # @LPStart format (omit)
366         .byte   0xff                            # @TType format (omit)
367         .byte   0x0b                            # call-site format
368                                                 # DW_EH_PE_sdata4
369         .uleb128 .Lcstend-.Lcstbegin
370 .Lcstbegin:
371         .long   .LcleanupSTART-.LSTARTCODE
372         .long   .Ladd_cond_futex-.LcleanupSTART
373         .long   __condvar_w_cleanup-.LSTARTCODE
374         .uleb128  0
375         .long   .Ladd_cond_futex-.LSTARTCODE
376         .long   .Lsub_cond_futex-.Ladd_cond_futex
377         .long   __condvar_w_cleanup2-.LSTARTCODE
378         .uleb128  0
379         .long   .Lsub_cond_futex-.LSTARTCODE
380         .long   .LcleanupEND-.Lsub_cond_futex
381         .long   __condvar_w_cleanup-.LSTARTCODE
382         .uleb128  0
383         .long   .LcallUR-.LSTARTCODE
384         .long   .LENDCODE-.LcallUR
385         .long   0
386         .uleb128  0
387 .Lcstend:
389         .section .eh_frame,"a",@progbits
390 .LSTARTFRAME:
391         .long   L(ENDCIE)-L(STARTCIE)           # Length of the CIE.
392 .LSTARTCIE:
393         .long   0                               # CIE ID.
394         .byte   1                               # Version number.
395 #ifdef SHARED
396         .string "zPLR"                          # NUL-terminated augmentation
397                                                 # string.
398 #else
399         .string "zPL"                           # NUL-terminated augmentation
400                                                 # string.
401 #endif
402         .uleb128 1                              # Code alignment factor.
403         .sleb128 -4                             # Data alignment factor.
404         .byte   8                               # Return address register
405                                                 # column.
406 #ifdef SHARED
407         .uleb128 7                              # Augmentation value length.
408         .byte   0x9b                            # Personality: DW_EH_PE_pcrel
409                                                 # + DW_EH_PE_sdata4
410                                                 # + DW_EH_PE_indirect
411         .long   DW.ref.__gcc_personality_v0-.
412         .byte   0x1b                            # LSDA Encoding: DW_EH_PE_pcrel
413                                                 # + DW_EH_PE_sdata4.
414         .byte   0x1b                            # FDE Encoding: DW_EH_PE_pcrel
415                                                 # + DW_EH_PE_sdata4.
416 #else
417         .uleb128 6                              # Augmentation value length.
418         .byte   0x0                             # Personality: absolute
419         .long   __gcc_personality_v0
420         .byte   0x0                             # LSDA Encoding: absolute
421 #endif
422         .byte 0x0c                              # DW_CFA_def_cfa
423         .uleb128 4
424         .uleb128 4
425         .byte   0x88                            # DW_CFA_offset, column 0x8
426         .uleb128 1
427         .align 4
428 .LENDCIE:
430         .long   .LENDFDE-.LSTARTFDE             # Length of the FDE.
431 .LSTARTFDE:
432         .long   .LSTARTFDE-.LSTARTFRAME         # CIE pointer.
433 #ifdef SHARED
434         .long   .LSTARTCODE-.                   # PC-relative start address
435                                                 # of the code.
436 #else
437         .long   .LSTARTCODE                     # Start address of the code.
438 #endif
439         .long   .LENDCODE-.LSTARTCODE           # Length of the code.
440         .uleb128 4                              # Augmentation size
441 #ifdef SHARED
442         .long   .LexceptSTART-.
443 #else
444         .long   .LexceptSTART
445 #endif
446         .byte   0x40+.Lpush_edi-.LSTARTCODE     # DW_CFA_advance_loc+N
447         .byte   14                              # DW_CFA_def_cfa_offset
448         .uleb128 8
449         .byte   0x87                            # DW_CFA_offset %edi
450         .uleb128 2
451         .byte   0x40+.Lpush_esi-.Lpush_edi      # DW_CFA_advance_loc+N
452         .byte   14                              # DW_CFA_def_cfa_offset
453         .uleb128 12
454         .byte   0x86                            # DW_CFA_offset %esi
455         .uleb128 3
456         .byte   0x40+.Lpush_ebx-.Lpush_esi      # DW_CFA_advance_loc+N
457         .byte   14                              # DW_CFA_def_cfa_offset
458         .uleb128 16
459         .byte   0x83                            # DW_CFA_offset %ebx
460         .uleb128 4
461         .byte   2                               # DW_CFA_advance_loc1
462         .byte   .Lsubl-.Lpush_ebx
463         .byte   14                              # DW_CFA_def_cfa_offset
464         .uleb128 16+FRAME_SIZE
465         .byte   2                               # DW_CFA_advance_loc1
466         .byte   .Laddl-.Lsubl
467         .byte   14                              # DW_CFA_def_cfa_offset
468         .uleb128 16
469         .byte   0x40+ .Lpop_ebx-.Laddl          # DW_CFA_advance_loc+N
470         .byte   14                              # DW_CFA_def_cfa_offset
471         .uleb128 12
472         .byte   0xc3                            # DW_CFA_restore %ebx
473         .byte   0x40+.Lpop_esi-.Lpop_ebx        # DW_CFA_advance_loc+N
474         .byte   14                              # DW_CFA_def_cfa_offset
475         .uleb128 8
476         .byte   0xc6                            # DW_CFA_restore %esi
477         .byte   0x40+.Lpop_edi-.Lpop_esi        # DW_CFA_advance_loc+N
478         .byte   14                              # DW_CFA_def_cfa_offset
479         .uleb128 4
480         .byte   0xc7                            # DW_CFA_restore %edi
481         .byte   0x40+.LSbl1-.Lpop_edi           # DW_CFA_advance_loc+N
482         .byte   14                              # DW_CFA_def_cfa_offset
483         .uleb128 16
484         .byte   0x87                            # DW_CFA_offset %edi
485         .uleb128 2
486         .byte   0x86                            # DW_CFA_offset %esi
487         .uleb128 3
488         .byte   0x83                            # DW_CFA_offset %ebx
489         .uleb128 4
490         .byte   0x40+.LSbl2-.LSbl1              # DW_CFA_advance_loc+N
491         .byte   14                              # DW_CFA_def_cfa_offset
492         .uleb128 16+FRAME_SIZE
493         .byte   0x40+.LSbl3-.LSbl2              # DW_CFA_advance_loc+N
494         .byte   14                              # DW_CFA_def_cfa_offset
495         .uleb128 16
496         .byte   0x40+.LSbl4-.LSbl3              # DW_CFA_advance_loc+N
497         .byte   14                              # DW_CFA_def_cfa_offset
498         .uleb128 16+FRAME_SIZE
499         .align  4
500 .LENDFDE:
503 #ifdef PIC
504         .section .gnu.linkonce.t.__i686.get_pc_thunk.cx,"ax",@progbits
505         .globl  __i686.get_pc_thunk.cx
506         .hidden __i686.get_pc_thunk.cx
507         .type   __i686.get_pc_thunk.cx,@function
508 __i686.get_pc_thunk.cx:
509         movl (%esp), %ecx;
510         ret
511         .size   __i686.get_pc_thunk.cx,.-__i686.get_pc_thunk.cx
512 #endif
514 #ifdef SHARED
515         .hidden DW.ref.__gcc_personality_v0
516         .weak   DW.ref.__gcc_personality_v0
517         .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
518         .align 4
519         .type   DW.ref.__gcc_personality_v0, @object
520         .size   DW.ref.__gcc_personality_v0, 4
521 DW.ref.__gcc_personality_v0:
522         .long   __gcc_personality_v0
523 #endif