]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/l4re-core/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S
Update
[l4.git] / l4 / pkg / l4re-core / uclibc / lib / contrib / uclibc / libpthread / nptl / sysdeps / unix / sysv / linux / i386 / i486 / lowlevellock.S
1 /* Copyright (C) 2002-2004, 2006, 2007, 2009 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, see
17    <http://www.gnu.org/licenses/>.  */
18
19 #include <sysdep.h>
20 #include <pthread-errnos.h>
21 #include <bits/kernel-features.h>
22 #include <lowlevellock.h>
23 #include <tcb-offsets.h>
24
25         .text
26
27 #ifdef __ASSUME_PRIVATE_FUTEX
28 # define LOAD_PRIVATE_FUTEX_WAIT(reg) \
29         movl    $(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg
30 # define LOAD_PRIVATE_FUTEX_WAKE(reg) \
31         movl    $(FUTEX_WAKE | FUTEX_PRIVATE_FLAG), reg
32 # define LOAD_FUTEX_WAIT(reg) \
33         xorl    $(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg
34 # define LOAD_FUTEX_WAIT_ABS(reg) \
35         xorl    $(FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME), reg
36 # define LOAD_FUTEX_WAKE(reg) \
37         xorl    $(FUTEX_WAKE | FUTEX_PRIVATE_FLAG), reg
38 #else
39 # if FUTEX_WAIT == 0
40 #  define LOAD_PRIVATE_FUTEX_WAIT(reg) \
41         movl    %gs:PRIVATE_FUTEX, reg
42 # else
43 #  define LOAD_PRIVATE_FUTEX_WAIT(reg) \
44         movl    %gs:PRIVATE_FUTEX, reg ; \
45         orl     $FUTEX_WAIT, reg
46 # endif
47 # define LOAD_PRIVATE_FUTEX_WAKE(reg) \
48         movl    %gs:PRIVATE_FUTEX, reg ; \
49         orl     $FUTEX_WAKE, reg
50 # if FUTEX_WAIT == 0
51 #  define LOAD_FUTEX_WAIT(reg) \
52         xorl    $FUTEX_PRIVATE_FLAG, reg ; \
53         andl    %gs:PRIVATE_FUTEX, reg
54 # else
55 #  define LOAD_FUTEX_WAIT(reg) \
56         xorl    $FUTEX_PRIVATE_FLAG, reg ; \
57         andl    %gs:PRIVATE_FUTEX, reg ; \
58         orl     $FUTEX_WAIT, reg
59 # endif
60 # define LOAD_FUTEX_WAIT_ABS(reg) \
61         xorl    $FUTEX_PRIVATE_FLAG, reg ; \
62         andl    %gs:PRIVATE_FUTEX, reg ; \
63         orl     $FUTEX_WAIT_BITSET | FUTEX_CLOCK_REALTIME, reg
64 # define LOAD_FUTEX_WAKE(reg) \
65         xorl    $FUTEX_PRIVATE_FLAG, reg ; \
66         andl    %gs:PRIVATE_FUTEX, reg ; \
67         orl     $FUTEX_WAKE, reg
68 #endif
69
70         .globl  __lll_lock_wait_private
71         .type   __lll_lock_wait_private,@function
72         .hidden __lll_lock_wait_private
73         .align  16
74 __lll_lock_wait_private:
75         cfi_startproc
76         pushl   %edx
77         cfi_adjust_cfa_offset(4)
78         pushl   %ebx
79         cfi_adjust_cfa_offset(4)
80         pushl   %esi
81         cfi_adjust_cfa_offset(4)
82         cfi_offset(%edx, -8)
83         cfi_offset(%ebx, -12)
84         cfi_offset(%esi, -16)
85
86         movl    $2, %edx
87         movl    %ecx, %ebx
88         xorl    %esi, %esi      /* No timeout.  */
89         LOAD_PRIVATE_FUTEX_WAIT (%ecx)
90
91         cmpl    %edx, %eax      /* NB:   %edx == 2 */
92         jne 2f
93
94 1:      movl    $SYS_futex, %eax
95         ENTER_KERNEL
96
97 2:      movl    %edx, %eax
98         xchgl   %eax, (%ebx)    /* NB:   lock is implied */
99
100         testl   %eax, %eax
101         jnz     1b
102
103         popl    %esi
104         cfi_adjust_cfa_offset(-4)
105         cfi_restore(%esi)
106         popl    %ebx
107         cfi_adjust_cfa_offset(-4)
108         cfi_restore(%ebx)
109         popl    %edx
110         cfi_adjust_cfa_offset(-4)
111         cfi_restore(%edx)
112         ret
113         cfi_endproc
114         .size   __lll_lock_wait_private,.-__lll_lock_wait_private
115
116 #ifdef NOT_IN_libc
117         .globl  __lll_lock_wait
118         .type   __lll_lock_wait,@function
119         .hidden __lll_lock_wait
120         .align  16
121 __lll_lock_wait:
122         cfi_startproc
123         pushl   %edx
124         cfi_adjust_cfa_offset(4)
125         pushl   %ebx
126         cfi_adjust_cfa_offset(4)
127         pushl   %esi
128         cfi_adjust_cfa_offset(4)
129         cfi_offset(%edx, -8)
130         cfi_offset(%ebx, -12)
131         cfi_offset(%esi, -16)
132
133         movl    %edx, %ebx
134         movl    $2, %edx
135         xorl    %esi, %esi      /* No timeout.  */
136         LOAD_FUTEX_WAIT (%ecx)
137
138         cmpl    %edx, %eax      /* NB:   %edx == 2 */
139         jne 2f
140
141 1:      movl    $SYS_futex, %eax
142         ENTER_KERNEL
143
144 2:      movl    %edx, %eax
145         xchgl   %eax, (%ebx)    /* NB:   lock is implied */
146
147         testl   %eax, %eax
148         jnz     1b
149
150         popl    %esi
151         cfi_adjust_cfa_offset(-4)
152         cfi_restore(%esi)
153         popl    %ebx
154         cfi_adjust_cfa_offset(-4)
155         cfi_restore(%ebx)
156         popl    %edx
157         cfi_adjust_cfa_offset(-4)
158         cfi_restore(%edx)
159         ret
160         cfi_endproc
161         .size   __lll_lock_wait,.-__lll_lock_wait
162
163         /*      %ecx: futex
164                 %esi: flags
165                 %edx: timeout
166                 %eax: futex value
167         */
168         .globl  __lll_timedlock_wait
169         .type   __lll_timedlock_wait,@function
170         .hidden __lll_timedlock_wait
171         .align  16
172 __lll_timedlock_wait:
173         cfi_startproc
174         pushl   %ebp
175         cfi_adjust_cfa_offset(4)
176         cfi_rel_offset(%ebp, 0)
177         pushl   %ebx
178         cfi_adjust_cfa_offset(4)
179         cfi_rel_offset(%ebx, 0)
180
181 # ifndef __ASSUME_FUTEX_CLOCK_REALTIME
182 #  ifdef __PIC__
183         LOAD_PIC_REG (bx)
184         cmpl    $0, __have_futex_clock_realtime@GOTOFF(%ebx)
185 #  else
186         cmpl    $0, __have_futex_clock_realtime
187 #  endif
188         je      .Lreltmo
189 # endif
190
191         movl    %ecx, %ebx
192         movl    %esi, %ecx
193         movl    %edx, %esi
194         movl    $0xffffffff, %ebp
195         LOAD_FUTEX_WAIT_ABS (%ecx)
196
197         movl    $2, %edx
198         cmpl    %edx, %eax
199         jne     2f
200
201 1:      movl    $SYS_futex, %eax
202         movl    $2, %edx
203         ENTER_KERNEL
204
205 2:      xchgl   %edx, (%ebx)    /* NB:   lock is implied */
206
207         testl   %edx, %edx
208         jz      3f
209
210         cmpl    $-ETIMEDOUT, %eax
211         je      4f
212         cmpl    $-EINVAL, %eax
213         jne     1b
214 4:      movl    %eax, %edx
215         negl    %edx
216
217 3:      movl    %edx, %eax
218 7:      popl    %ebx
219         cfi_adjust_cfa_offset(-4)
220         cfi_restore(%ebx)
221         popl    %ebp
222         cfi_adjust_cfa_offset(-4)
223         cfi_restore(%ebp)
224         ret
225
226 # ifndef __ASSUME_FUTEX_CLOCK_REALTIME
227 .Lreltmo:
228         /* Check for a valid timeout value.  */
229         cmpl    $1000000000, 4(%edx)
230         jae     3f
231
232         pushl   %esi
233         cfi_adjust_cfa_offset(4)
234         cfi_rel_offset(%esi, 0)
235         pushl   %edi
236         cfi_adjust_cfa_offset(4)
237         cfi_rel_offset(%edi, 0)
238
239         /* Stack frame for the timespec and timeval structs.  */
240         subl    $8, %esp
241         cfi_adjust_cfa_offset(8)
242
243         movl    %ecx, %ebp
244         movl    %edx, %edi
245
246         movl    $2, %edx
247         xchgl   %edx, (%ebp)
248
249         test    %edx, %edx
250         je      6f
251
252 1:
253         /* Get current time.  */
254         movl    %esp, %ebx
255         xorl    %ecx, %ecx
256         movl    $__NR_gettimeofday, %eax
257         ENTER_KERNEL
258
259         /* Compute relative timeout.  */
260         movl    4(%esp), %eax
261         movl    $1000, %edx
262         mul     %edx            /* Milli seconds to nano seconds.  */
263         movl    (%edi), %ecx
264         movl    4(%edi), %edx
265         subl    (%esp), %ecx
266         subl    %eax, %edx
267         jns     4f
268         addl    $1000000000, %edx
269         subl    $1, %ecx
270 4:      testl   %ecx, %ecx
271         js      2f              /* Time is already up.  */
272
273         /* Store relative timeout.  */
274         movl    %ecx, (%esp)
275         movl    %edx, 4(%esp)
276
277         /* Futex call.  */
278         movl    %ebp, %ebx
279         movl    $2, %edx
280         movl    %esp, %esi
281         movl    16(%esp), %ecx
282         LOAD_FUTEX_WAIT (%ecx)
283         movl    $SYS_futex, %eax
284         ENTER_KERNEL
285
286         /* NB: %edx == 2 */
287         xchgl   %edx, (%ebp)
288
289         testl   %edx, %edx
290         je      6f
291
292         cmpl    $-ETIMEDOUT, %eax
293         jne     1b
294 2:      movl    $ETIMEDOUT, %edx
295
296 6:      addl    $8, %esp
297         cfi_adjust_cfa_offset(-8)
298         popl    %edi
299         cfi_adjust_cfa_offset(-4)
300         cfi_restore(%edi)
301         popl    %esi
302         cfi_adjust_cfa_offset(-4)
303         cfi_restore(%esi)
304 7:      popl    %ebx
305         cfi_adjust_cfa_offset(-4)
306         cfi_restore(%ebx)
307         popl    %ebp
308         cfi_adjust_cfa_offset(-4)
309         cfi_restore(%ebp)
310         movl    %edx, %eax
311         ret
312
313 3:      movl    $EINVAL, %edx
314         jmp     7b
315 # endif
316         cfi_endproc
317         .size   __lll_timedlock_wait,.-__lll_timedlock_wait
318 #endif
319
320         .globl  __lll_unlock_wake_private
321         .type   __lll_unlock_wake_private,@function
322         .hidden __lll_unlock_wake_private
323         .align  16
324 __lll_unlock_wake_private:
325         cfi_startproc
326         pushl   %ebx
327         cfi_adjust_cfa_offset(4)
328         pushl   %ecx
329         cfi_adjust_cfa_offset(4)
330         pushl   %edx
331         cfi_adjust_cfa_offset(4)
332         cfi_offset(%ebx, -8)
333         cfi_offset(%ecx, -12)
334         cfi_offset(%edx, -16)
335
336         movl    %eax, %ebx
337         movl    $0, (%eax)
338         LOAD_PRIVATE_FUTEX_WAKE (%ecx)
339         movl    $1, %edx        /* Wake one thread.  */
340         movl    $SYS_futex, %eax
341         ENTER_KERNEL
342
343         popl    %edx
344         cfi_adjust_cfa_offset(-4)
345         cfi_restore(%edx)
346         popl    %ecx
347         cfi_adjust_cfa_offset(-4)
348         cfi_restore(%ecx)
349         popl    %ebx
350         cfi_adjust_cfa_offset(-4)
351         cfi_restore(%ebx)
352         ret
353         cfi_endproc
354         .size   __lll_unlock_wake_private,.-__lll_unlock_wake_private
355
356 #ifdef NOT_IN_libc
357         .globl  __lll_unlock_wake
358         .type   __lll_unlock_wake,@function
359         .hidden __lll_unlock_wake
360         .align  16
361 __lll_unlock_wake:
362         cfi_startproc
363         pushl   %ebx
364         cfi_adjust_cfa_offset(4)
365         pushl   %ecx
366         cfi_adjust_cfa_offset(4)
367         pushl   %edx
368         cfi_adjust_cfa_offset(4)
369         cfi_offset(%ebx, -8)
370         cfi_offset(%ecx, -12)
371         cfi_offset(%edx, -16)
372
373         movl    %eax, %ebx
374         movl    $0, (%eax)
375         LOAD_FUTEX_WAKE (%ecx)
376         movl    $1, %edx        /* Wake one thread.  */
377         movl    $SYS_futex, %eax
378         ENTER_KERNEL
379
380         popl    %edx
381         cfi_adjust_cfa_offset(-4)
382         cfi_restore(%edx)
383         popl    %ecx
384         cfi_adjust_cfa_offset(-4)
385         cfi_restore(%ecx)
386         popl    %ebx
387         cfi_adjust_cfa_offset(-4)
388         cfi_restore(%ebx)
389         ret
390         cfi_endproc
391         .size   __lll_unlock_wake,.-__lll_unlock_wake
392
393         .globl  __lll_timedwait_tid
394         .type   __lll_timedwait_tid,@function
395         .hidden __lll_timedwait_tid
396         .align  16
397 __lll_timedwait_tid:
398         pushl   %edi
399         pushl   %esi
400         pushl   %ebx
401         pushl   %ebp
402
403         movl    %eax, %ebp
404         movl    %edx, %edi
405         subl    $8, %esp
406
407         /* Get current time.  */
408 2:      movl    %esp, %ebx
409         xorl    %ecx, %ecx
410         movl    $__NR_gettimeofday, %eax
411         ENTER_KERNEL
412
413         /* Compute relative timeout.  */
414         movl    4(%esp), %eax
415         movl    $1000, %edx
416         mul     %edx            /* Milli seconds to nano seconds.  */
417         movl    (%edi), %ecx
418         movl    4(%edi), %edx
419         subl    (%esp), %ecx
420         subl    %eax, %edx
421         jns     5f
422         addl    $1000000000, %edx
423         subl    $1, %ecx
424 5:      testl   %ecx, %ecx
425         js      6f              /* Time is already up.  */
426
427         movl    %ecx, (%esp)    /* Store relative timeout.  */
428         movl    %edx, 4(%esp)
429
430         movl    (%ebp), %edx
431         testl   %edx, %edx
432         jz      4f
433
434         movl    %esp, %esi
435         /* XXX The kernel so far uses global futex for the wakeup at
436            all times.  */
437         xorl    %ecx, %ecx      /* movl $FUTEX_WAIT, %ecx */
438         movl    %ebp, %ebx
439         movl    $SYS_futex, %eax
440         ENTER_KERNEL
441
442         cmpl    $0, (%ebx)
443         jne     1f
444 4:      xorl    %eax, %eax
445
446 3:      addl    $8, %esp
447         popl    %ebp
448         popl    %ebx
449         popl    %esi
450         popl    %edi
451         ret
452
453 1:      cmpl    $-ETIMEDOUT, %eax
454         jne     2b
455 6:      movl    $ETIMEDOUT, %eax
456         jmp     3b
457         .size   __lll_timedwait_tid,.-__lll_timedwait_tid
458 #endif