2006-03-04 Jakub Jelinek <jakub@redhat.com>
[glibc.git] / nptl / sysdeps / unix / sysv / linux / i386 / i486 / lowlevellock.S
blobe2da5b04cf01f80b8a9d679a37db47de3b23b354
1 /* Copyright (C) 2002, 2003, 2004, 2006 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 <pthread-errnos.h>
23         .text
25 #ifndef LOCK
26 # ifdef UP
27 #  define LOCK
28 # else
29 #  define LOCK lock
30 # endif
31 #endif
33 #define SYS_gettimeofday        __NR_gettimeofday
34 #define SYS_futex               240
35 #define FUTEX_WAIT              0
36 #define FUTEX_WAKE              1
39         .globl  __lll_mutex_lock_wait
40         .type   __lll_mutex_lock_wait,@function
41         .hidden __lll_mutex_lock_wait
42         .align  16
43 __lll_mutex_lock_wait:
44         cfi_startproc
45         pushl   %edx
46         cfi_adjust_cfa_offset(4)
47         pushl   %ebx
48         cfi_adjust_cfa_offset(4)
49         pushl   %esi
50         cfi_adjust_cfa_offset(4)
51         cfi_offset(%edx, -8)
52         cfi_offset(%ebx, -12)
53         cfi_offset(%esi, -16)
55         movl    $2, %edx
56         movl    %ecx, %ebx
57         xorl    %esi, %esi      /* No timeout.  */
58         xorl    %ecx, %ecx      /* movl $FUTEX_WAIT, %ecx */
60         cmpl    %edx, %eax      /* NB:   %edx == 2 */
61         jne 2f
63 1:      movl    $SYS_futex, %eax
64         ENTER_KERNEL
66 2:      movl    %edx, %eax
67         xchgl   %eax, (%ebx)    /* NB:   lock is implied */
69         testl   %eax, %eax
70         jnz     1b
72         popl    %esi
73         cfi_adjust_cfa_offset(-4)
74         cfi_restore(%esi)
75         popl    %ebx
76         cfi_adjust_cfa_offset(-4)
77         cfi_restore(%ebx)
78         popl    %edx
79         cfi_adjust_cfa_offset(-4)
80         cfi_restore(%edx)
81         ret
82         cfi_endproc
83         .size   __lll_mutex_lock_wait,.-__lll_mutex_lock_wait
86 #ifdef NOT_IN_libc
87         .globl  __lll_mutex_timedlock_wait
88         .type   __lll_mutex_timedlock_wait,@function
89         .hidden __lll_mutex_timedlock_wait
90         .align  16
91 __lll_mutex_timedlock_wait:
92         cfi_startproc
93         /* Check for a valid timeout value.  */
94         cmpl    $1000000000, 4(%edx)
95         jae     3f
97         pushl   %edi
98         cfi_adjust_cfa_offset(4)
99         pushl   %esi
100         cfi_adjust_cfa_offset(4)
101         pushl   %ebx
102         cfi_adjust_cfa_offset(4)
103         pushl   %ebp
104         cfi_adjust_cfa_offset(4)
105         cfi_offset(%edi, -8)
106         cfi_offset(%esi, -12)
107         cfi_offset(%ebx, -16)
108         cfi_offset(%ebp, -20)
110         /* Stack frame for the timespec and timeval structs.  */
111         subl    $8, %esp
112         cfi_adjust_cfa_offset(8)
114         movl    %ecx, %ebp
115         movl    %edx, %edi
118         /* Get current time.  */
119         movl    %esp, %ebx
120         xorl    %ecx, %ecx
121         movl    $SYS_gettimeofday, %eax
122         ENTER_KERNEL
124         /* Compute relative timeout.  */
125         movl    4(%esp), %eax
126         movl    $1000, %edx
127         mul     %edx            /* Milli seconds to nano seconds.  */
128         movl    (%edi), %ecx
129         movl    4(%edi), %edx
130         subl    (%esp), %ecx
131         subl    %eax, %edx
132         jns     4f
133         addl    $1000000000, %edx
134         subl    $1, %ecx
135 4:      testl   %ecx, %ecx
136         js      5f              /* Time is already up.  */
138         /* Store relative timeout.  */
139         movl    %ecx, (%esp)
140         movl    %edx, 4(%esp)
142         movl    %ebp, %ebx
144         movl    $1, %eax
145         movl    $2, %edx
146         LOCK
147         cmpxchgl %edx, (%ebx)
149         testl   %eax, %eax
150         je      8f
152         /* Futex call.  */
153         movl    %esp, %esi
154         xorl    %ecx, %ecx      /* movl $FUTEX_WAIT, %ecx */
155         movl    $SYS_futex, %eax
156         ENTER_KERNEL
157         movl    %eax, %ecx
159 8:                              /* NB: %edx == 2 */
160         xorl    %eax, %eax
161         LOCK
162         cmpxchgl %edx, (%ebx)
164         jnz     7f
166 6:      addl    $8, %esp
167         cfi_adjust_cfa_offset(-8)
168         popl    %ebp
169         cfi_adjust_cfa_offset(-4)
170         cfi_restore(%ebp)
171         popl    %ebx
172         cfi_adjust_cfa_offset(-4)
173         cfi_restore(%ebx)
174         popl    %esi
175         cfi_adjust_cfa_offset(-4)
176         cfi_restore(%esi)
177         popl    %edi
178         cfi_adjust_cfa_offset(-4)
179         cfi_restore(%edi)
180         ret
182 3:      movl    $EINVAL, %eax
183         ret
185         cfi_adjust_cfa_offset(24)
186         cfi_offset(%edi, -8)
187         cfi_offset(%esi, -12)
188         cfi_offset(%ebx, -16)
189         cfi_offset(%ebp, -20)
190         /* Check whether the time expired.  */
191 7:      cmpl    $-ETIMEDOUT, %ecx
192         je      5f
194         /* Make sure the current holder knows we are going to sleep.  */
195         movl    %edx, %eax
196         xchgl   %eax, (%ebx)
197         testl   %eax, %eax
198         jz      6b
199         jmp     1b
201 5:      movl    $ETIMEDOUT, %eax
202         jmp     6b
203         cfi_endproc
204         .size   __lll_mutex_timedlock_wait,.-__lll_mutex_timedlock_wait
205 #endif
208 #ifdef NOT_IN_libc
209         .globl  lll_unlock_wake_cb
210         .type   lll_unlock_wake_cb,@function
211         .hidden lll_unlock_wake_cb
212         .align  16
213 lll_unlock_wake_cb:
214         pushl   %ebx
215         pushl   %ecx
216         pushl   %edx
218         movl    20(%esp), %ebx
219         LOCK
220         subl    $1, (%ebx)
221         je      1f
223         movl    $FUTEX_WAKE, %ecx
224         movl    $1, %edx        /* Wake one thread.  */
225         movl    $SYS_futex, %eax
226         movl    $0, (%ebx)
227         ENTER_KERNEL
229 1:      popl    %edx
230         popl    %ecx
231         popl    %ebx
232         ret
233         .size   lll_unlock_wake_cb,.-lll_unlock_wake_cb
234 #endif
237         .globl  __lll_mutex_unlock_wake
238         .type   __lll_mutex_unlock_wake,@function
239         .hidden __lll_mutex_unlock_wake
240         .align  16
241 __lll_mutex_unlock_wake:
242         cfi_startproc
243         pushl   %ebx
244         cfi_adjust_cfa_offset(4)
245         pushl   %ecx
246         cfi_adjust_cfa_offset(4)
247         pushl   %edx
248         cfi_adjust_cfa_offset(4)
249         cfi_offset(%ebx, -8)
250         cfi_offset(%ecx, -12)
251         cfi_offset(%edx, -16)
253         movl    %eax, %ebx
254         movl    $0, (%eax)
255         movl    $FUTEX_WAKE, %ecx
256         movl    $1, %edx        /* Wake one thread.  */
257         movl    $SYS_futex, %eax
258         ENTER_KERNEL
260         popl    %edx
261         cfi_adjust_cfa_offset(-4)
262         cfi_restore(%edx)
263         popl    %ecx
264         cfi_adjust_cfa_offset(-4)
265         cfi_restore(%ecx)
266         popl    %ebx
267         cfi_adjust_cfa_offset(-4)
268         cfi_restore(%ebx)
269         ret
270         cfi_endproc
271         .size   __lll_mutex_unlock_wake,.-__lll_mutex_unlock_wake
274 #ifdef NOT_IN_libc
275         .globl  __lll_timedwait_tid
276         .type   __lll_timedwait_tid,@function
277         .hidden __lll_timedwait_tid
278         .align  16
279 __lll_timedwait_tid:
280         pushl   %edi
281         pushl   %esi
282         pushl   %ebx
283         pushl   %ebp
285         movl    %eax, %ebp
286         movl    %edx, %edi
287         subl    $8, %esp
289         /* Get current time.  */
290 2:      movl    %esp, %ebx
291         xorl    %ecx, %ecx
292         movl    $SYS_gettimeofday, %eax
293         ENTER_KERNEL
295         /* Compute relative timeout.  */
296         movl    4(%esp), %eax
297         movl    $1000, %edx
298         mul     %edx            /* Milli seconds to nano seconds.  */
299         movl    (%edi), %ecx
300         movl    4(%edi), %edx
301         subl    (%esp), %ecx
302         subl    %eax, %edx
303         jns     5f
304         addl    $1000000000, %edx
305         subl    $1, %ecx
306 5:      testl   %ecx, %ecx
307         js      6f              /* Time is already up.  */
309         movl    %ecx, (%esp)    /* Store relative timeout.  */
310         movl    %edx, 4(%esp)
312         movl    (%ebp), %edx
313         testl   %edx, %edx
314         jz      4f
316         movl    %esp, %esi
317         xorl    %ecx, %ecx      /* movl $FUTEX_WAIT, %ecx */
318         movl    %ebp, %ebx
319         movl    $SYS_futex, %eax
320         ENTER_KERNEL
322         cmpl    $0, (%ebx)
323         jne     1f
324 4:      xorl    %eax, %eax
326 3:      addl    $8, %esp
327         popl    %ebp
328         popl    %ebx
329         popl    %esi
330         popl    %edi
331         ret
333 1:      cmpl    $-ETIMEDOUT, %eax
334         jne     2b
335 6:      movl    $ETIMEDOUT, %eax
336         jmp     3b
337         .size   __lll_timedwait_tid,.-__lll_timedwait_tid
338 #endif