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