fdwalk should return 0 on an empty directory
[kopensolaris-gnu/glibc.git] / nptl / sysdeps / unix / sysv / linux / i386 / i486 / pthread_cond_wait.S
1 /* Copyright (C) 2002, 2003, 2004, 2006, 2007 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 <lowlevellock.h>
23 #include <lowlevelcond.h>
24 #include <tcb-offsets.h>
25 #include <kernel-features.h>
26
27
28         .text
29
30 /* int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)  */
31         .globl  __pthread_cond_wait
32         .type   __pthread_cond_wait, @function
33         .align  16
34 __pthread_cond_wait:
35 .LSTARTCODE:
36
37         pushl   %edi
38 .Lpush_edi:
39         pushl   %esi
40 .Lpush_esi:
41         pushl   %ebx
42 .Lpush_ebx:
43
44         xorl    %esi, %esi
45         movl    16(%esp), %ebx
46
47         /* Get internal lock.  */
48         movl    $1, %edx
49         xorl    %eax, %eax
50         LOCK
51 #if cond_lock == 0
52         cmpxchgl %edx, (%ebx)
53 #else
54         cmpxchgl %edx, cond_lock(%ebx)
55 #endif
56         jnz     1f
57
58         /* Store the reference to the mutex.  If there is already a
59            different value in there this is a bad user bug.  */
60 2:      cmpl    $-1, dep_mutex(%ebx)
61         movl    20(%esp), %eax
62         je      15f
63         movl    %eax, dep_mutex(%ebx)
64
65         /* Unlock the mutex.  */
66 15:     xorl    %edx, %edx
67         call    __pthread_mutex_unlock_usercnt
68
69         testl   %eax, %eax
70         jne     12f
71
72         addl    $1, total_seq(%ebx)
73         adcl    $0, total_seq+4(%ebx)
74         addl    $1, cond_futex(%ebx)
75         addl    $(1 << nwaiters_shift), cond_nwaiters(%ebx)
76
77 #define FRAME_SIZE 16
78         subl    $FRAME_SIZE, %esp
79 .Lsubl:
80
81         /* Get and store current wakeup_seq value.  */
82         movl    wakeup_seq(%ebx), %edi
83         movl    wakeup_seq+4(%ebx), %edx
84         movl    broadcast_seq(%ebx), %eax
85         movl    %edi, 4(%esp)
86         movl    %edx, 8(%esp)
87         movl    %eax, 12(%esp)
88
89 8:      movl    cond_futex(%ebx), %edi
90
91         /* Unlock.  */
92         LOCK
93 #if cond_lock == 0
94         subl    $1, (%ebx)
95 #else
96         subl    $1, cond_lock(%ebx)
97 #endif
98         jne     3f
99
100 .LcleanupSTART:
101 4:      call    __pthread_enable_asynccancel
102         movl    %eax, (%esp)
103
104 #if FUTEX_PRIVATE_FLAG > 255
105         xorl    %ecx, %ecx
106 #endif
107         cmpl    $-1, dep_mutex(%ebx)
108         sete    %cl
109         subl    $1, %ecx
110 #ifdef __ASSUME_PRIVATE_FUTEX
111         andl    $FUTEX_PRIVATE_FLAG, %ecx
112 #else
113         andl    %gs:PRIVATE_FUTEX, %ecx
114 #endif
115 #if FUTEX_WAIT != 0
116         addl    $FUTEX_WAIT, %ecx
117 #endif
118         movl    %edi, %edx
119         addl    $cond_futex, %ebx
120 .Ladd_cond_futex:
121         movl    $SYS_futex, %eax
122         ENTER_KERNEL
123         subl    $cond_futex, %ebx
124 .Lsub_cond_futex:
125
126         movl    (%esp), %eax
127         call    __pthread_disable_asynccancel
128 .LcleanupEND:
129
130         /* Lock.  */
131         movl    $1, %edx
132         xorl    %eax, %eax
133         LOCK
134 #if cond_lock == 0
135         cmpxchgl %edx, (%ebx)
136 #else
137         cmpxchgl %edx, cond_lock(%ebx)
138 #endif
139         jnz     5f
140
141 6:      movl    broadcast_seq(%ebx), %eax
142         cmpl    12(%esp), %eax
143         jne     16f
144
145         movl    woken_seq(%ebx), %eax
146         movl    woken_seq+4(%ebx), %ecx
147
148         movl    wakeup_seq(%ebx), %edi
149         movl    wakeup_seq+4(%ebx), %edx
150
151         cmpl    8(%esp), %edx
152         jne     7f
153         cmpl    4(%esp), %edi
154         je      8b
155
156 7:      cmpl    %ecx, %edx
157         jne     9f
158         cmp     %eax, %edi
159         je      8b
160
161 9:      addl    $1, woken_seq(%ebx)
162         adcl    $0, woken_seq+4(%ebx)
163
164         /* Unlock */
165 16:     subl    $(1 << nwaiters_shift), cond_nwaiters(%ebx)
166
167         /* Wake up a thread which wants to destroy the condvar object.  */
168         movl    total_seq(%ebx), %eax
169         andl    total_seq+4(%ebx), %eax
170         cmpl    $0xffffffff, %eax
171         jne     17f
172         movl    cond_nwaiters(%ebx), %eax
173         andl    $~((1 << nwaiters_shift) - 1), %eax
174         jne     17f
175
176         addl    $cond_nwaiters, %ebx
177         movl    $SYS_futex, %eax
178 #if FUTEX_PRIVATE_FLAG > 255
179         xorl    %ecx, %ecx
180 #endif
181         cmpl    $-1, dep_mutex-cond_nwaiters(%ebx)
182         sete    %cl
183         subl    $1, %ecx
184 #ifdef __ASSUME_PRIVATE_FUTEX
185         andl    $FUTEX_PRIVATE_FLAG, %ecx
186 #else
187         andl    %gs:PRIVATE_FUTEX, %ecx
188 #endif
189         addl    $FUTEX_WAKE, %ecx
190         movl    $1, %edx
191         ENTER_KERNEL
192         subl    $cond_nwaiters, %ebx
193
194 17:     LOCK
195 #if cond_lock == 0
196         subl    $1, (%ebx)
197 #else
198         subl    $1, cond_lock(%ebx)
199 #endif
200         jne     10f
201
202 11:     movl    20+FRAME_SIZE(%esp), %eax
203         call    __pthread_mutex_cond_lock
204         addl    $FRAME_SIZE, %esp
205 .Laddl:
206
207 14:     popl    %ebx
208 .Lpop_ebx:
209         popl    %esi
210 .Lpop_esi:
211         popl    %edi
212 .Lpop_edi:
213
214         /* We return the result of the mutex_lock operation.  */
215         ret
216
217         /* Initial locking failed.  */
218 1:
219 .LSbl1:
220 #if cond_lock == 0
221         movl    %ebx, %edx
222 #else
223         leal    cond_lock(%ebx), %edx
224 #endif
225 #if (LLL_SHARED-LLL_PRIVATE) > 255
226         xorl    %ecx, %ecx
227 #endif
228         cmpl    $-1, dep_mutex(%ebx)
229         setne   %cl
230         subl    $1, %ecx
231         andl    $(LLL_SHARED-LLL_PRIVATE), %ecx
232 #if LLL_PRIVATE != 0
233         addl    $LLL_PRIVATE, %ecx
234 #endif
235         call    __lll_lock_wait
236         jmp     2b
237
238         /* Unlock in loop requires waekup.  */
239 3:
240 .LSbl2:
241 #if cond_lock == 0
242         movl    %ebx, %eax
243 #else
244         leal    cond_lock(%ebx), %eax
245 #endif
246 #if (LLL_SHARED-LLL_PRIVATE) > 255
247         xorl    %ecx, %ecx
248 #endif
249         cmpl    $-1, dep_mutex(%ebx)
250         setne   %cl
251         subl    $1, %ecx
252         andl    $(LLL_SHARED-LLL_PRIVATE), %ecx
253 #if LLL_PRIVATE != 0
254         addl    $LLL_PRIVATE, %ecx
255 #endif
256         call    __lll_unlock_wake
257         jmp     4b
258
259         /* Locking in loop failed.  */
260 5:
261 #if cond_lock == 0
262         movl    %ebx, %edx
263 #else
264         leal    cond_lock(%ebx), %edx
265 #endif
266 #if (LLL_SHARED-LLL_PRIVATE) > 255
267         xorl    %ecx, %ecx
268 #endif
269         cmpl    $-1, dep_mutex(%ebx)
270         setne   %cl
271         subl    $1, %ecx
272         andl    $(LLL_SHARED-LLL_PRIVATE), %ecx
273 #if LLL_PRIVATE != 0
274         addl    $LLL_PRIVATE, %ecx
275 #endif
276         call    __lll_lock_wait
277         jmp     6b
278
279         /* Unlock after loop requires wakeup.  */
280 10:
281 #if cond_lock == 0
282         movl    %ebx, %eax
283 #else
284         leal    cond_lock(%ebx), %eax
285 #endif
286 #if (LLL_SHARED-LLL_PRIVATE) > 255
287         xorl    %ecx, %ecx
288 #endif
289         cmpl    $-1, dep_mutex(%ebx)
290         setne   %cl
291         subl    $1, %ecx
292         andl    $(LLL_SHARED-LLL_PRIVATE), %ecx
293 #if LLL_PRIVATE != 0
294         addl    $LLL_PRIVATE, %ecx
295 #endif
296         call    __lll_unlock_wake
297         jmp     11b
298
299         /* The initial unlocking of the mutex failed.  */
300 12:
301 .LSbl3:
302         LOCK
303 #if cond_lock == 0
304         subl    $1, (%ebx)
305 #else
306         subl    $1, cond_lock(%ebx)
307 #endif
308         jne     14b
309
310         movl    %eax, %esi
311 #if cond_lock == 0
312         movl    %ebx, %eax
313 #else
314         leal    cond_lock(%ebx), %eax
315 #endif
316 #if (LLL_SHARED-LLL_PRIVATE) > 255
317         xorl    %ecx, %ecx
318 #endif
319         cmpl    $-1, dep_mutex(%ebx)
320         setne   %cl
321         subl    $1, %ecx
322         andl    $(LLL_SHARED-LLL_PRIVATE), %ecx
323 #if LLL_PRIVATE != 0
324         addl    $LLL_PRIVATE, %ecx
325 #endif
326         call    __lll_unlock_wake
327
328         movl    %esi, %eax
329         jmp     14b
330         .size   __pthread_cond_wait, .-__pthread_cond_wait
331 versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
332                   GLIBC_2_3_2)
333
334
335         .type   __condvar_w_cleanup2, @function
336 __condvar_w_cleanup2:
337         subl    $cond_futex, %ebx
338         .size   __condvar_w_cleanup2, .-__condvar_w_cleanup2
339 .LSbl4:
340         .type   __condvar_w_cleanup, @function
341 __condvar_w_cleanup:
342         movl    %eax, %esi
343
344         /* Get internal lock.  */
345         movl    $1, %edx
346         xorl    %eax, %eax
347         LOCK
348 #if cond_lock == 0
349         cmpxchgl %edx, (%ebx)
350 #else
351         cmpxchgl %edx, cond_lock(%ebx)
352 #endif
353         jz      1f
354
355 #if cond_lock == 0
356         movl    %ebx, %edx
357 #else
358         leal    cond_lock(%ebx), %edx
359 #endif
360 #if (LLL_SHARED-LLL_PRIVATE) > 255
361         xorl    %ecx, %ecx
362 #endif
363         cmpl    $-1, dep_mutex(%ebx)
364         setne   %cl
365         subl    $1, %ecx
366         andl    $(LLL_SHARED-LLL_PRIVATE), %ecx
367 #if LLL_PRIVATE != 0
368         addl    $LLL_PRIVATE, %ecx
369 #endif
370         call    __lll_lock_wait
371
372 1:      movl    broadcast_seq(%ebx), %eax
373         cmpl    12(%esp), %eax
374         jne     3f
375
376         /* We increment the wakeup_seq counter only if it is lower than
377            total_seq.  If this is not the case the thread was woken and
378            then canceled.  In this case we ignore the signal.  */
379         movl    total_seq(%ebx), %eax
380         movl    total_seq+4(%ebx), %edi
381         cmpl    wakeup_seq+4(%ebx), %edi
382         jb      6f
383         ja      7f
384         cmpl    wakeup_seq(%ebx), %eax
385         jbe     7f
386
387 6:      addl    $1, wakeup_seq(%ebx)
388         adcl    $0, wakeup_seq+4(%ebx)
389         addl    $1, cond_futex(%ebx)
390
391 7:      addl    $1, woken_seq(%ebx)
392         adcl    $0, woken_seq+4(%ebx)
393
394 3:      subl    $(1 << nwaiters_shift), cond_nwaiters(%ebx)
395
396         /* Wake up a thread which wants to destroy the condvar object.  */
397         xorl    %edi, %edi
398         movl    total_seq(%ebx), %eax
399         andl    total_seq+4(%ebx), %eax
400         cmpl    $0xffffffff, %eax
401         jne     4f
402         movl    cond_nwaiters(%ebx), %eax
403         andl    $~((1 << nwaiters_shift) - 1), %eax
404         jne     4f
405
406         addl    $cond_nwaiters, %ebx
407         movl    $SYS_futex, %eax
408 #if FUTEX_PRIVATE_FLAG > 255
409         xorl    %ecx, %ecx
410 #endif
411         cmpl    $-1, dep_mutex-cond_nwaiters(%ebx)
412         sete    %cl
413         subl    $1, %ecx
414 #ifdef __ASSUME_PRIVATE_FUTEX
415         andl    $FUTEX_PRIVATE_FLAG, %ecx
416 #else
417         andl    %gs:PRIVATE_FUTEX, %ecx
418 #endif
419         addl    $FUTEX_WAKE, %ecx
420         movl    $1, %edx
421         ENTER_KERNEL
422         subl    $cond_nwaiters, %ebx
423         movl    $1, %edi
424
425 4:      LOCK
426 #if cond_lock == 0
427         subl    $1, (%ebx)
428 #else
429         subl    $1, cond_lock(%ebx)
430 #endif
431         je      2f
432
433 #if cond_lock == 0
434         movl    %ebx, %eax
435 #else
436         leal    cond_lock(%ebx), %eax
437 #endif
438 #if (LLL_SHARED-LLL_PRIVATE) > 255
439         xorl    %ecx, %ecx
440 #endif
441         cmpl    $-1, dep_mutex(%ebx)
442         setne   %cl
443         subl    $1, %ecx
444         andl    $(LLL_SHARED-LLL_PRIVATE), %ecx
445 #if LLL_PRIVATE != 0
446         addl    $LLL_PRIVATE, %ecx
447 #endif
448         call    __lll_unlock_wake
449
450         /* Wake up all waiters to make sure no signal gets lost.  */
451 2:      testl   %edi, %edi
452         jnz     5f
453         addl    $cond_futex, %ebx
454 #if FUTEX_PRIVATE_FLAG > 255
455         xorl    %ecx, %ecx
456 #endif
457         cmpl    $-1, dep_mutex-cond_futex(%ebx)
458         sete    %cl
459         subl    $1, %ecx
460 #ifdef __ASSUME_PRIVATE_FUTEX
461         andl    $FUTEX_PRIVATE_FLAG, %ecx
462 #else
463         andl    %gs:PRIVATE_FUTEX, %ecx
464 #endif
465         addl    $FUTEX_WAKE, %ecx
466         movl    $SYS_futex, %eax
467         movl    $0x7fffffff, %edx
468         ENTER_KERNEL
469
470 5:      movl    20+FRAME_SIZE(%esp), %eax
471         call    __pthread_mutex_cond_lock
472
473         movl    %esi, (%esp)
474 .LcallUR:
475         call    _Unwind_Resume
476         hlt
477 .LENDCODE:
478         .size   __condvar_w_cleanup, .-__condvar_w_cleanup
479
480
481         .section .gcc_except_table,"a",@progbits
482 .LexceptSTART:
483         .byte   0xff                            # @LPStart format (omit)
484         .byte   0xff                            # @TType format (omit)
485         .byte   0x0b                            # call-site format
486                                                 # DW_EH_PE_sdata4
487         .uleb128 .Lcstend-.Lcstbegin
488 .Lcstbegin:
489         .long   .LcleanupSTART-.LSTARTCODE
490         .long   .Ladd_cond_futex-.LcleanupSTART
491         .long   __condvar_w_cleanup-.LSTARTCODE
492         .uleb128  0
493         .long   .Ladd_cond_futex-.LSTARTCODE
494         .long   .Lsub_cond_futex-.Ladd_cond_futex
495         .long   __condvar_w_cleanup2-.LSTARTCODE
496         .uleb128  0
497         .long   .Lsub_cond_futex-.LSTARTCODE
498         .long   .LcleanupEND-.Lsub_cond_futex
499         .long   __condvar_w_cleanup-.LSTARTCODE
500         .uleb128  0
501         .long   .LcallUR-.LSTARTCODE
502         .long   .LENDCODE-.LcallUR
503         .long   0
504         .uleb128  0
505 .Lcstend:
506
507         .section .eh_frame,"a",@progbits
508 .LSTARTFRAME:
509         .long   L(ENDCIE)-L(STARTCIE)           # Length of the CIE.
510 .LSTARTCIE:
511         .long   0                               # CIE ID.
512         .byte   1                               # Version number.
513 #ifdef SHARED
514         .string "zPLR"                          # NUL-terminated augmentation
515                                                 # string.
516 #else
517         .string "zPL"                           # NUL-terminated augmentation
518                                                 # string.
519 #endif
520         .uleb128 1                              # Code alignment factor.
521         .sleb128 -4                             # Data alignment factor.
522         .byte   8                               # Return address register
523                                                 # column.
524 #ifdef SHARED
525         .uleb128 7                              # Augmentation value length.
526         .byte   0x9b                            # Personality: DW_EH_PE_pcrel
527                                                 # + DW_EH_PE_sdata4
528                                                 # + DW_EH_PE_indirect
529         .long   DW.ref.__gcc_personality_v0-.
530         .byte   0x1b                            # LSDA Encoding: DW_EH_PE_pcrel
531                                                 # + DW_EH_PE_sdata4.
532         .byte   0x1b                            # FDE Encoding: DW_EH_PE_pcrel
533                                                 # + DW_EH_PE_sdata4.
534 #else
535         .uleb128 6                              # Augmentation value length.
536         .byte   0x0                             # Personality: absolute
537         .long   __gcc_personality_v0
538         .byte   0x0                             # LSDA Encoding: absolute
539 #endif
540         .byte 0x0c                              # DW_CFA_def_cfa
541         .uleb128 4
542         .uleb128 4
543         .byte   0x88                            # DW_CFA_offset, column 0x8
544         .uleb128 1
545         .align 4
546 .LENDCIE:
547
548         .long   .LENDFDE-.LSTARTFDE             # Length of the FDE.
549 .LSTARTFDE:
550         .long   .LSTARTFDE-.LSTARTFRAME         # CIE pointer.
551 #ifdef SHARED
552         .long   .LSTARTCODE-.                   # PC-relative start address
553                                                 # of the code.
554 #else
555         .long   .LSTARTCODE                     # Start address of the code.
556 #endif
557         .long   .LENDCODE-.LSTARTCODE           # Length of the code.
558         .uleb128 4                              # Augmentation size
559 #ifdef SHARED
560         .long   .LexceptSTART-.
561 #else
562         .long   .LexceptSTART
563 #endif
564         .byte   0x40+.Lpush_edi-.LSTARTCODE     # DW_CFA_advance_loc+N
565         .byte   14                              # DW_CFA_def_cfa_offset
566         .uleb128 8
567         .byte   0x87                            # DW_CFA_offset %edi
568         .uleb128 2
569         .byte   0x40+.Lpush_esi-.Lpush_edi      # DW_CFA_advance_loc+N
570         .byte   14                              # DW_CFA_def_cfa_offset
571         .uleb128 12
572         .byte   0x86                            # DW_CFA_offset %esi
573         .uleb128 3
574         .byte   0x40+.Lpush_ebx-.Lpush_esi      # DW_CFA_advance_loc+N
575         .byte   14                              # DW_CFA_def_cfa_offset
576         .uleb128 16
577         .byte   0x83                            # DW_CFA_offset %ebx
578         .uleb128 4
579         .byte   4                               # DW_CFA_advance_loc4
580         .4byte  .Lsubl-.Lpush_ebx
581         .byte   14                              # DW_CFA_def_cfa_offset
582         .uleb128 16+FRAME_SIZE
583         .byte   4                               # DW_CFA_advance_loc4
584         .4byte  .Laddl-.Lsubl
585         .byte   14                              # DW_CFA_def_cfa_offset
586         .uleb128 16
587         .byte   0x40+ .Lpop_ebx-.Laddl          # DW_CFA_advance_loc+N
588         .byte   14                              # DW_CFA_def_cfa_offset
589         .uleb128 12
590         .byte   0xc3                            # DW_CFA_restore %ebx
591         .byte   0x40+.Lpop_esi-.Lpop_ebx        # DW_CFA_advance_loc+N
592         .byte   14                              # DW_CFA_def_cfa_offset
593         .uleb128 8
594         .byte   0xc6                            # DW_CFA_restore %esi
595         .byte   0x40+.Lpop_edi-.Lpop_esi        # DW_CFA_advance_loc+N
596         .byte   14                              # DW_CFA_def_cfa_offset
597         .uleb128 4
598         .byte   0xc7                            # DW_CFA_restore %edi
599         .byte   0x40+.LSbl1-.Lpop_edi           # DW_CFA_advance_loc+N
600         .byte   14                              # DW_CFA_def_cfa_offset
601         .uleb128 16
602         .byte   0x87                            # DW_CFA_offset %edi
603         .uleb128 2
604         .byte   0x86                            # DW_CFA_offset %esi
605         .uleb128 3
606         .byte   0x83                            # DW_CFA_offset %ebx
607         .uleb128 4
608         .byte   4                               # DW_CFA_advance_loc4
609         .4byte  .LSbl2-.LSbl1
610         .byte   14                              # DW_CFA_def_cfa_offset
611         .uleb128 16+FRAME_SIZE
612         .byte   4                               # DW_CFA_advance_loc4
613         .4byte  .LSbl3-.LSbl2
614         .byte   14                              # DW_CFA_def_cfa_offset
615         .uleb128 16
616         .byte   4                               # DW_CFA_advance_loc4
617         .4byte  .LSbl4-.LSbl3
618         .byte   14                              # DW_CFA_def_cfa_offset
619         .uleb128 16+FRAME_SIZE
620         .align  4
621 .LENDFDE:
622
623
624 #ifdef PIC
625         .section .gnu.linkonce.t.__i686.get_pc_thunk.cx,"ax",@progbits
626         .globl  __i686.get_pc_thunk.cx
627         .hidden __i686.get_pc_thunk.cx
628         .type   __i686.get_pc_thunk.cx,@function
629 __i686.get_pc_thunk.cx:
630         movl (%esp), %ecx;
631         ret
632         .size   __i686.get_pc_thunk.cx,.-__i686.get_pc_thunk.cx
633 #endif
634
635 #ifdef SHARED
636         .hidden DW.ref.__gcc_personality_v0
637         .weak   DW.ref.__gcc_personality_v0
638         .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
639         .align 4
640         .type   DW.ref.__gcc_personality_v0, @object
641         .size   DW.ref.__gcc_personality_v0, 4
642 DW.ref.__gcc_personality_v0:
643         .long   __gcc_personality_v0
644 #endif