fdwalk should return 0 on an empty directory
[kopensolaris-gnu/glibc.git] / nptl / sysdeps / unix / sysv / linux / i386 / i486 / pthread_cond_signal.S
1 /* Copyright (C) 2002, 2003, 2004, 2005, 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 <kernel-features.h>
25 #include <pthread-errnos.h>
26
27
28         .text
29
30         /* int pthread_cond_signal (pthread_cond_t *cond) */
31         .globl  __pthread_cond_signal
32         .type   __pthread_cond_signal, @function
33         .align  16
34 __pthread_cond_signal:
35
36         pushl   %ebx
37         pushl   %edi
38
39         movl    12(%esp), %edi
40
41         /* Get internal lock.  */
42         movl    $1, %edx
43         xorl    %eax, %eax
44         LOCK
45 #if cond_lock == 0
46         cmpxchgl %edx, (%edi)
47 #else
48         cmpxchgl %edx, cond_lock(%edi)
49 #endif
50         jnz     1f
51
52 2:      leal    cond_futex(%edi), %ebx
53         movl    total_seq+4(%edi), %eax
54         movl    total_seq(%edi), %ecx
55         cmpl    wakeup_seq+4(%edi), %eax
56 #if cond_lock != 0
57         /* Must use leal to preserve the flags.  */
58         leal    cond_lock(%edi), %edi
59 #endif
60         ja      3f
61         jb      4f
62         cmpl    wakeup_seq-cond_futex(%ebx), %ecx
63         jbe     4f
64
65         /* Bump the wakeup number.  */
66 3:      addl    $1, wakeup_seq-cond_futex(%ebx)
67         adcl    $0, wakeup_seq-cond_futex+4(%ebx)
68         addl    $1, (%ebx)
69
70         /* Wake up one thread.  */
71         pushl   %esi
72         pushl   %ebp
73 #if FUTEX_PRIVATE_FLAG > 255
74         xorl    %ecx, %ecx
75 #endif
76         cmpl    $-1, dep_mutex-cond_futex(%ebx)
77         sete    %cl
78         subl    $1, %ecx
79 #ifdef __ASSUME_PRIVATE_FUTEX
80         andl    $FUTEX_PRIVATE_FLAG, %ecx
81 #else
82         andl    %gs:PRIVATE_FUTEX, %ecx
83 #endif
84         addl    $FUTEX_WAKE_OP, %ecx
85         movl    $SYS_futex, %eax
86         movl    $1, %edx
87         movl    $1, %esi
88         movl    $FUTEX_OP_CLEAR_WAKE_IF_GT_ONE, %ebp
89         /* FIXME: Until Ingo fixes 4G/4G vDSO, 6 arg syscalls are broken for
90            sysenter.
91         ENTER_KERNEL  */
92         int     $0x80
93         popl    %ebp
94         popl    %esi
95
96         /* For any kind of error, we try again with WAKE.
97            The general test also covers running on old kernels.  */
98         cmpl    $-4095, %eax
99         jae     7f
100
101 6:      xorl    %eax, %eax
102         popl    %edi
103         popl    %ebx
104         ret
105
106 7:      /* %ecx should be either FUTEX_WAKE_OP or
107            FUTEX_WAKE_OP|FUTEX_PRIVATE_FLAG from the previous syscall.  */
108         xorl    $(FUTEX_WAKE ^ FUTEX_WAKE_OP), %ecx
109         movl    $SYS_futex, %eax
110         /* %edx should be 1 already from $FUTEX_WAKE_OP syscall.
111         movl    $1, %edx  */
112         ENTER_KERNEL
113
114         /* Unlock.  Note that at this point %edi always points to
115            cond_lock.  */
116 4:      LOCK
117         subl    $1, (%edi)
118         je      6b
119
120         /* Unlock in loop requires wakeup.  */
121 5:      movl    %edi, %eax
122 #if (LLL_SHARED-LLL_PRIVATE) > 255
123         xorl    %ecx, %ecx
124 #endif
125         cmpl    $-1, dep_mutex-cond_futex(%ebx)
126         setne   %cl
127         subl    $1, %ecx
128         andl    $(LLL_SHARED-LLL_PRIVATE), %ecx
129 #if LLL_PRIVATE != 0
130         addl    $LLL_PRIVATE, %ecx
131 #endif
132         call    __lll_unlock_wake
133         jmp     6b
134
135         /* Initial locking failed.  */
136 1:
137 #if cond_lock == 0
138         movl    %edi, %edx
139 #else
140         leal    cond_lock(%edi), %edx
141 #endif
142 #if (LLL_SHARED-LLL_PRIVATE) > 255
143         xorl    %ecx, %ecx
144 #endif
145         cmpl    $-1, dep_mutex(%edi)
146         setne   %cl
147         subl    $1, %ecx
148         andl    $(LLL_SHARED-LLL_PRIVATE), %ecx
149 #if LLL_PRIVATE != 0
150         addl    $LLL_PRIVATE, %ecx
151 #endif
152         call    __lll_lock_wait
153         jmp     2b
154
155         .size   __pthread_cond_signal, .-__pthread_cond_signal
156 versioned_symbol (libpthread, __pthread_cond_signal, pthread_cond_signal,
157                   GLIBC_2_3_2)