(CFLAGS-tst-align.c): Add -mpreferred-stack-boundary=4.
[glibc.git] / nptl / sysdeps / unix / sysv / linux / i386 / i486 / lowlevellock.S
blobdc65b709a1a1194a1c41994efa2cdb030b81340e
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 <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         pushl   %edx
45         pushl   %ebx
46         pushl   %esi
48         movl    $2, %edx
49         movl    %ecx, %ebx
50         xorl    %esi, %esi      /* No timeout.  */
51         xorl    %ecx, %ecx      /* movl $FUTEX_WAIT, %ecx */
53         cmpl    %edx, %eax      /* NB:   %edx == 2 */
54         jne 2f
56 1:      movl    $SYS_futex, %eax
57         ENTER_KERNEL
59 2:      movl    %edx, %eax
60         xchgl   %eax, (%ebx)    /* NB:   lock is implied */
62         testl   %eax, %eax
63         jnz,pn  1b
65         popl    %esi
66         popl    %ebx
67         popl    %edx
68         ret
69         .size   __lll_mutex_lock_wait,.-__lll_mutex_lock_wait
72 #ifdef NOT_IN_libc
73         .globl  __lll_mutex_timedlock_wait
74         .type   __lll_mutex_timedlock_wait,@function
75         .hidden __lll_mutex_timedlock_wait
76         .align  16
77 __lll_mutex_timedlock_wait:
78         /* Check for a valid timeout value.  */
79         cmpl    $1000000000, 4(%edx)
80         jae     3f
82         pushl   %edi
83         pushl   %esi
84         pushl   %ebx
85         pushl   %ebp
87         /* Stack frame for the timespec and timeval structs.  */
88         subl    $8, %esp
90         movl    %ecx, %ebp
91         movl    %edx, %edi
94         /* Get current time.  */
95         movl    %esp, %ebx
96         xorl    %ecx, %ecx
97         movl    $SYS_gettimeofday, %eax
98         ENTER_KERNEL
100         /* Compute relative timeout.  */
101         movl    4(%esp), %eax
102         movl    $1000, %edx
103         mul     %edx            /* Milli seconds to nano seconds.  */
104         movl    (%edi), %ecx
105         movl    4(%edi), %edx
106         subl    (%esp), %ecx
107         subl    %eax, %edx
108         jns     4f
109         addl    $1000000000, %edx
110         subl    $1, %ecx
111 4:      testl   %ecx, %ecx
112         js      5f              /* Time is already up.  */
114         /* Store relative timeout.  */
115         movl    %ecx, (%esp)
116         movl    %edx, 4(%esp)
118         movl    %ebp, %ebx
120         movl    $1, %eax
121         movl    $2, %edx
122         LOCK
123         cmpxchgl %edx, (%ebx)
125         testl   %eax, %eax
126         je      8f
128         /* Futex call.  */
129         movl    %esp, %esi
130         xorl    %ecx, %ecx      /* movl $FUTEX_WAIT, %ecx */
131         movl    $SYS_futex, %eax
132         ENTER_KERNEL
133         movl    %eax, %ecx
135 8:                              /* NB: %edx == 2 */
136         xorl    %eax, %eax
137         LOCK
138         cmpxchgl %edx, (%ebx)
140         jnz     7f
142 6:      addl    $8, %esp
143         popl    %ebp
144         popl    %ebx
145         popl    %esi
146         popl    %edi
147         ret
149         /* Check whether the time expired.  */
150 7:      cmpl    $-ETIMEDOUT, %ecx
151         je      5f
153         /* Make sure the current holder knows we are going to sleep.  */
154         movl    %edx, %eax
155         xchgl   %eax, (%ebx)
156         testl   %eax, %eax
157         jz      6b
158         jmp     1b
160 3:      movl    $EINVAL, %eax
161         ret
163 5:      movl    $ETIMEDOUT, %eax
164         jmp     6b
165         .size   __lll_mutex_timedlock_wait,.-__lll_mutex_timedlock_wait
166 #endif
169 #ifdef NOT_IN_libc
170         .globl  lll_unlock_wake_cb
171         .type   lll_unlock_wake_cb,@function
172         .hidden lll_unlock_wake_cb
173         .align  16
174 lll_unlock_wake_cb:
175         pushl   %ebx
176         pushl   %ecx
177         pushl   %edx
179         movl    20(%esp), %ebx
180         LOCK
181         subl    $1, (%ebx)
182         je      1f
184         movl    $FUTEX_WAKE, %ecx
185         movl    $1, %edx        /* Wake one thread.  */
186         movl    $SYS_futex, %eax
187         movl    $0, (%ebx)
188         ENTER_KERNEL
190 1:      popl    %edx
191         popl    %ecx
192         popl    %ebx
193         ret
194         .size   lll_unlock_wake_cb,.-lll_unlock_wake_cb
195 #endif
198         .globl  __lll_mutex_unlock_wake
199         .type   __lll_mutex_unlock_wake,@function
200         .hidden __lll_mutex_unlock_wake
201         .align  16
202 __lll_mutex_unlock_wake:
203         pushl   %ebx
204         pushl   %ecx
205         pushl   %edx
207         movl    %eax, %ebx
208         movl    $0, (%eax)
209         movl    $FUTEX_WAKE, %ecx
210         movl    $1, %edx        /* Wake one thread.  */
211         movl    $SYS_futex, %eax
212         ENTER_KERNEL
214         popl    %edx
215         popl    %ecx
216         popl    %ebx
217         ret
218         .size   __lll_mutex_unlock_wake,.-__lll_mutex_unlock_wake
221 #ifdef NOT_IN_libc
222         .globl  __lll_timedwait_tid
223         .type   __lll_timedwait_tid,@function
224         .hidden __lll_timedwait_tid
225         .align  16
226 __lll_timedwait_tid:
227         pushl   %edi
228         pushl   %esi
229         pushl   %ebx
230         pushl   %ebp
232         movl    %eax, %ebp
233         movl    %edx, %edi
234         subl    $8, %esp
236         /* Get current time.  */
237 2:      movl    %esp, %ebx
238         xorl    %ecx, %ecx
239         movl    $SYS_gettimeofday, %eax
240         ENTER_KERNEL
242         /* Compute relative timeout.  */
243         movl    4(%esp), %eax
244         movl    $1000, %edx
245         mul     %edx            /* Milli seconds to nano seconds.  */
246         movl    (%edi), %ecx
247         movl    4(%edi), %edx
248         subl    (%esp), %ecx
249         subl    %eax, %edx
250         jns     5f
251         addl    $1000000000, %edx
252         subl    $1, %ecx
253 5:      testl   %ecx, %ecx
254         js      6f              /* Time is already up.  */
256         movl    %ecx, (%esp)    /* Store relative timeout.  */
257         movl    %edx, 4(%esp)
259         movl    (%ebp), %edx
260         testl   %edx, %edx
261         jz      4f
263         movl    %esp, %esi
264         xorl    %ecx, %ecx      /* movl $FUTEX_WAIT, %ecx */
265         movl    %ebp, %ebx
266         movl    $SYS_futex, %eax
267         ENTER_KERNEL
269         cmpl    $0, (%ebx)
270         jne     1f
271 4:      xorl    %eax, %eax
273 3:      addl    $8, %esp
274         popl    %ebp
275         popl    %ebx
276         popl    %esi
277         popl    %edi
278         ret
280 1:      cmpl    $-ETIMEDOUT, %eax
281         jne     2b
282 6:      movl    $ETIMEDOUT, %eax
283         jmp     3b
284         .size   __lll_timedwait_tid,.-__lll_timedwait_tid
285 #endif