]> git.ipfire.org Git - thirdparty/glibc.git/blob - nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S
Update.
[thirdparty/glibc.git] / nptl / sysdeps / unix / sysv / linux / i386 / i486 / lowlevellock.S
1 /* Copyright (C) 2002, 2003 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
23 .text
24
25 #ifndef LOCK
26 # ifdef UP
27 # define LOCK
28 # else
29 # define LOCK lock
30 # endif
31 #endif
32
33 #define SYS_gettimeofday __NR_gettimeofday
34 #define SYS_futex 240
35 #define FUTEX_WAIT 0
36 #define FUTEX_WAKE 1
37
38
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
47
48 movl $2, %edx
49 movl %ecx, %ebx
50 xorl %esi, %esi /* No timeout. */
51 xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */
52
53 1: cmpl %edx, %eax /* NB: %edx == 2 */
54 je 3f
55
56 movl $1, %eax
57 LOCK
58 cmpxchgl %edx, (%ebx)
59
60 testl %eax, %eax
61 je 2f
62
63 3: movl $SYS_futex, %eax
64 ENTER_KERNEL
65
66 xorl %eax, %eax
67 2: LOCK
68 cmpxchgl %edx, (%ebx)
69
70 jnz,pn 1b
71
72 popl %esi
73 popl %ebx
74 popl %edx
75 ret
76 .size __lll_mutex_lock_wait,.-__lll_mutex_lock_wait
77
78
79 #ifdef NOT_IN_libc
80 .globl __lll_mutex_timedlock_wait
81 .type __lll_mutex_timedlock_wait,@function
82 .hidden __lll_mutex_timedlock_wait
83 .align 16
84 __lll_mutex_timedlock_wait:
85 /* Check for a valid timeout value. */
86 cmpl $1000000000, 4(%edx)
87 jae 3f
88
89 pushl %edi
90 pushl %esi
91 pushl %ebx
92 pushl %ebp
93
94 /* Stack frame for the timespec and timeval structs. */
95 subl $8, %esp
96
97 movl %ecx, %ebp
98 movl %edx, %edi
99
100 1:
101 /* Get current time. */
102 movl %esp, %ebx
103 xorl %ecx, %ecx
104 movl $SYS_gettimeofday, %eax
105 ENTER_KERNEL
106
107 /* Compute relative timeout. */
108 movl 4(%esp), %eax
109 movl $1000, %edx
110 mul %edx /* Milli seconds to nano seconds. */
111 movl (%edi), %ecx
112 movl 4(%edi), %edx
113 subl (%esp), %ecx
114 subl %eax, %edx
115 jns 4f
116 addl $1000000000, %edx
117 subl $1, %ecx
118 4: testl %ecx, %ecx
119 js 5f /* Time is already up. */
120
121 /* Store relative timeout. */
122 movl %ecx, (%esp)
123 movl %edx, 4(%esp)
124
125 movl %ebp, %ebx
126
127 movl $1, %eax
128 movl $2, %edx
129 LOCK
130 cmpxchgl %edx, (%ebx)
131
132 testl %eax, %eax
133 je 8f
134
135 /* Futex call. */
136 movl %esp, %esi
137 xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */
138 movl $SYS_futex, %eax
139 ENTER_KERNEL
140 movl %eax, %ecx
141
142 8:
143 xorl %eax, %eax
144 movl $2, %edx
145 LOCK
146 cmpxchgl %edx, (%ebx)
147
148 jnz 7f
149
150 6: addl $8, %esp
151 popl %ebp
152 popl %ebx
153 popl %esi
154 popl %edi
155 ret
156
157 /* Check whether the time expired. */
158 7: cmpl $-ETIMEDOUT, %ecx
159 je 5f
160 jmp 1b
161
162 3: movl $EINVAL, %eax
163 ret
164
165 5: movl $ETIMEDOUT, %eax
166 jmp 6b
167 .size __lll_mutex_timedlock_wait,.-__lll_mutex_timedlock_wait
168 #endif
169
170
171 #ifdef NOT_IN_libc
172 .globl lll_unlock_wake_cb
173 .type lll_unlock_wake_cb,@function
174 .hidden lll_unlock_wake_cb
175 .align 16
176 lll_unlock_wake_cb:
177 pushl %ebx
178 pushl %ecx
179 pushl %edx
180
181 movl 20(%esp), %ebx
182 LOCK
183 subl $1, (%ebx)
184 je 1f
185
186 movl $FUTEX_WAKE, %ecx
187 movl $1, %edx /* Wake one thread. */
188 movl $SYS_futex, %eax
189 movl $0, (%ebx)
190 ENTER_KERNEL
191
192 1: popl %edx
193 popl %ecx
194 popl %ebx
195 ret
196 .size lll_unlock_wake_cb,.-lll_unlock_wake_cb
197 #endif
198
199
200 .globl __lll_mutex_unlock_wake
201 .type __lll_mutex_unlock_wake,@function
202 .hidden __lll_mutex_unlock_wake
203 .align 16
204 __lll_mutex_unlock_wake:
205 pushl %ebx
206 pushl %ecx
207 pushl %edx
208
209 movl %eax, %ebx
210 movl $0, (%eax)
211 movl $FUTEX_WAKE, %ecx
212 movl $1, %edx /* Wake one thread. */
213 movl $SYS_futex, %eax
214 ENTER_KERNEL
215
216 popl %edx
217 popl %ecx
218 popl %ebx
219 ret
220 .size __lll_mutex_unlock_wake,.-__lll_mutex_unlock_wake
221
222
223 #ifdef NOT_IN_libc
224 .globl __lll_timedwait_tid
225 .type __lll_timedwait_tid,@function
226 .hidden __lll_timedwait_tid
227 .align 16
228 __lll_timedwait_tid:
229 pushl %edi
230 pushl %esi
231 pushl %ebx
232 pushl %ebp
233
234 movl %eax, %ebp
235 movl %edx, %edi
236 subl $8, %esp
237
238 /* Get current time. */
239 2: movl %esp, %ebx
240 xorl %ecx, %ecx
241 movl $SYS_gettimeofday, %eax
242 ENTER_KERNEL
243
244 /* Compute relative timeout. */
245 movl 4(%esp), %eax
246 movl $1000, %edx
247 mul %edx /* Milli seconds to nano seconds. */
248 movl (%edi), %ecx
249 movl 4(%edi), %edx
250 subl (%esp), %ecx
251 subl %eax, %edx
252 jns 5f
253 addl $1000000000, %edx
254 subl $1, %ecx
255 5: testl %ecx, %ecx
256 js 6f /* Time is already up. */
257
258 movl %ecx, (%esp) /* Store relative timeout. */
259 movl %edx, 4(%esp)
260
261 movl (%ebp), %edx
262 testl %edx, %edx
263 jz 4f
264
265 movl %esp, %esi
266 xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */
267 movl %ebp, %ebx
268 movl $SYS_futex, %eax
269 ENTER_KERNEL
270
271 cmpl $0, (%ebx)
272 jne 1f
273 4: xorl %eax, %eax
274
275 3: addl $8, %esp
276 popl %ebp
277 popl %ebx
278 popl %esi
279 popl %edi
280 ret
281
282 1: cmpl $-ETIMEDOUT, %eax
283 jne 2b
284 6: movl $ETIMEDOUT, %eax
285 jmp 3b
286 .size __lll_timedwait_tid,.-__lll_timedwait_tid
287 #endif