fdwalk should return 0 on an empty directory
[kopensolaris-gnu/glibc.git] / nptl / sysdeps / unix / sysv / linux / i386 / i486 / lowlevelrobustlock.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 <pthread-errnos.h>
22 #include <lowlevellock.h>
23 #include <lowlevelrobustlock.h>
24 #include <kernel-features.h>
25
26         .text
27
28 #define FUTEX_WAITERS           0x80000000
29 #define FUTEX_OWNER_DIED        0x40000000
30
31 #ifdef __ASSUME_PRIVATE_FUTEX
32 # define LOAD_FUTEX_WAIT(reg) \
33         xorl    $(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg
34 #else
35 # if FUTEX_WAIT == 0
36 #  define LOAD_FUTEX_WAIT(reg) \
37         xorl    $FUTEX_PRIVATE_FLAG, reg ; \
38         andl    %gs:PRIVATE_FUTEX, reg
39 # else
40 #  define LOAD_FUTEX_WAIT(reg) \
41         xorl    $FUTEX_PRIVATE_FLAG, reg ; \
42         andl    %gs:PRIVATE_FUTEX, reg ; \
43         orl     $FUTEX_WAIT, reg
44 # endif
45 #endif
46
47         .globl  __lll_robust_lock_wait
48         .type   __lll_robust_lock_wait,@function
49         .hidden __lll_robust_lock_wait
50         .align  16
51 __lll_robust_lock_wait:
52         cfi_startproc
53         pushl   %edx
54         cfi_adjust_cfa_offset(4)
55         pushl   %ebx
56         cfi_adjust_cfa_offset(4)
57         pushl   %esi
58         cfi_adjust_cfa_offset(4)
59         cfi_offset(%edx, -8)
60         cfi_offset(%ebx, -12)
61         cfi_offset(%esi, -16)
62
63         movl    %edx, %ebx
64         xorl    %esi, %esi      /* No timeout.  */
65         LOAD_FUTEX_WAIT (%ecx)
66
67 4:      movl    %eax, %edx
68         orl     $FUTEX_WAITERS, %edx
69
70         testl   $FUTEX_OWNER_DIED, %eax
71         jnz     3f
72
73         cmpl    %edx, %eax      /* NB:   %edx == 2 */
74         je      1f
75
76         LOCK
77         cmpxchgl %edx, (%ebx)
78         jnz     2f
79
80 1:      movl    $SYS_futex, %eax
81         ENTER_KERNEL
82
83         movl    (%ebx), %eax
84
85 2:      test    %eax, %eax
86         jne     4b
87
88         movl    %gs:TID, %edx
89         orl     $FUTEX_WAITERS, %edx
90         LOCK
91         cmpxchgl %edx, (%ebx)
92         jnz     4b
93         /* NB:   %eax == 0 */
94
95 3:      popl    %esi
96         cfi_adjust_cfa_offset(-4)
97         cfi_restore(%esi)
98         popl    %ebx
99         cfi_adjust_cfa_offset(-4)
100         cfi_restore(%ebx)
101         popl    %edx
102         cfi_adjust_cfa_offset(-4)
103         cfi_restore(%edx)
104         ret
105         cfi_endproc
106         .size   __lll_robust_lock_wait,.-__lll_robust_lock_wait
107
108
109         .globl  __lll_robust_timedlock_wait
110         .type   __lll_robust_timedlock_wait,@function
111         .hidden __lll_robust_timedlock_wait
112         .align  16
113 __lll_robust_timedlock_wait:
114         cfi_startproc
115         /* Check for a valid timeout value.  */
116         cmpl    $1000000000, 4(%edx)
117         jae     3f
118
119         pushl   %edi
120         cfi_adjust_cfa_offset(4)
121         pushl   %esi
122         cfi_adjust_cfa_offset(4)
123         pushl   %ebx
124         cfi_adjust_cfa_offset(4)
125         pushl   %ebp
126         cfi_adjust_cfa_offset(4)
127         cfi_offset(%edi, -8)
128         cfi_offset(%esi, -12)
129         cfi_offset(%ebx, -16)
130         cfi_offset(%ebp, -20)
131
132         /* Stack frame for the timespec and timeval structs.  */
133         subl    $12, %esp
134         cfi_adjust_cfa_offset(12)
135
136         movl    %ecx, %ebp
137         movl    %edx, %edi
138
139 1:      movl    %eax, 8(%esp)
140
141         /* Get current time.  */
142         movl    %esp, %ebx
143         xorl    %ecx, %ecx
144         movl    $__NR_gettimeofday, %eax
145         ENTER_KERNEL
146
147         /* Compute relative timeout.  */
148         movl    4(%esp), %eax
149         movl    $1000, %edx
150         mul     %edx            /* Milli seconds to nano seconds.  */
151         movl    (%edi), %ecx
152         movl    4(%edi), %edx
153         subl    (%esp), %ecx
154         subl    %eax, %edx
155         jns     4f
156         addl    $1000000000, %edx
157         subl    $1, %ecx
158 4:      testl   %ecx, %ecx
159         js      8f              /* Time is already up.  */
160
161         /* Store relative timeout.  */
162         movl    %ecx, (%esp)
163         movl    %edx, 4(%esp)
164
165         movl    %ebp, %ebx
166
167         movl    8(%esp), %edx
168         movl    %edx, %eax
169         orl     $FUTEX_WAITERS, %edx
170
171         testl   $FUTEX_OWNER_DIED, %eax
172         jnz     6f
173
174         cmpl    %eax, %edx
175         je      2f
176
177         LOCK
178         cmpxchgl %edx, (%ebx)
179         movl    $0, %ecx        /* Must use mov to avoid changing cc.  */
180         jnz     5f
181
182 2:
183         /* Futex call.  */
184         movl    %esp, %esi
185         movl    20(%esp), %ecx
186         LOAD_FUTEX_WAIT (%ecx)
187         movl    $SYS_futex, %eax
188         ENTER_KERNEL
189         movl    %eax, %ecx
190
191         movl    (%ebx), %eax
192
193 5:      testl   %eax, %eax
194         jne     7f
195
196         movl    %gs:TID, %edx
197         orl     $FUTEX_WAITERS, %edx
198         LOCK
199         cmpxchgl %edx, (%ebx)
200         jnz     7f
201
202 6:      addl    $12, %esp
203         cfi_adjust_cfa_offset(-12)
204         popl    %ebp
205         cfi_adjust_cfa_offset(-4)
206         cfi_restore(%ebp)
207         popl    %ebx
208         cfi_adjust_cfa_offset(-4)
209         cfi_restore(%ebx)
210         popl    %esi
211         cfi_adjust_cfa_offset(-4)
212         cfi_restore(%esi)
213         popl    %edi
214         cfi_adjust_cfa_offset(-4)
215         cfi_restore(%edi)
216         ret
217
218 3:      movl    $EINVAL, %eax
219         ret
220
221         cfi_adjust_cfa_offset(28)
222         cfi_offset(%edi, -8)
223         cfi_offset(%esi, -12)
224         cfi_offset(%ebx, -16)
225         cfi_offset(%ebp, -20)
226         /* Check whether the time expired.  */
227 7:      cmpl    $-ETIMEDOUT, %ecx
228         jne     1b
229
230 8:      movl    $ETIMEDOUT, %eax
231         jmp     6b
232         cfi_endproc
233         .size   __lll_robust_timedlock_wait,.-__lll_robust_timedlock_wait