* sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S (sem_timedwait):
[glibc.git] / nptl / sysdeps / unix / sysv / linux / x86_64 / sem_timedwait.S
blob8c5c2a69741533c1835e66b0ca6b54139141ea22
1 /* Copyright (C) 2002, 2003, 2005, 2007 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 <shlib-compat.h>
22 #include <pthread-errnos.h>
24 #ifndef UP
25 # define LOCK lock
26 #else
27 # define
28 #endif
30 #define SYS_futex               202
32 /* For the calculation see asm/vsyscall.h.  */
33 #define VSYSCALL_ADDR_vgettimeofday     0xffffffffff600000
36         .text
38         .globl  sem_timedwait
39         .type   sem_timedwait,@function
40         .align  16
41         cfi_startproc
42 sem_timedwait:
43         movl    (%rdi), %eax
44 2:      testl   %eax, %eax
45         je      1f
47         leaq    -1(%rax), %rdx
48         LOCK
49         cmpxchgl %edx, (%rdi)
50         jne     2b
52         xorl    %eax, %eax
53         retq
55         /* Check whether the timeout value is valid.  */
56 1:      pushq   %r12
57         cfi_adjust_cfa_offset(8)
58         pushq   %r13
59         cfi_adjust_cfa_offset(8)
60         pushq   %r14
61         cfi_adjust_cfa_offset(8)
62         subq    $24, %rsp
63         cfi_adjust_cfa_offset(24)
65         movq    %rdi, %r12
66         cfi_offset(12, -16)             /* %r12 */
67         movq    %rsi, %r13
68         cfi_offset(13, -24)             /* %r13 */
70         /* Check for invalid nanosecond field.  */
71         cmpq    $1000000000, 8(%r13)
72         movl    $EINVAL, %r14d
73         cfi_offset(14, -24)             /* %r14 */
74         jae     6f
76 7:      xorl    %esi, %esi
77         movq    %rsp, %rdi
78         movq    $VSYSCALL_ADDR_vgettimeofday, %rax
79         callq   *%rax
81         /* Compute relative timeout.  */
82         movq    8(%rsp), %rax
83         movl    $1000, %edi
84         mul     %rdi            /* Milli seconds to nano seconds.  */
85         movq    (%r13), %rdi
86         movq    8(%r13), %rsi
87         subq    (%rsp), %rdi
88         subq    %rax, %rsi
89         jns     5f
90         addq    $1000000000, %rsi
91         decq    %rdi
92 5:      testq   %rdi, %rdi
93         movl    $ETIMEDOUT, %r14d
94         js      6f              /* Time is already up.  */
96         movq    %rdi, (%rsp)    /* Store relative timeout.  */
97         movq    %rsi, 8(%rsp)
99         call    __pthread_enable_asynccancel
100         movl    %eax, 16(%rsp)
102         movq    %rsp, %r10
103         movq    %r12, %rdi
104         xorl    %esi, %esi
105         movl    $SYS_futex, %eax
106         xorl    %edx, %edx
107         syscall
108         movq    %rax, %r14
110         movl    16(%rsp), %edi
111         call    __pthread_disable_asynccancel
113         testq   %r14, %r14
114         je      9f
115         cmpq    $-EWOULDBLOCK, %r14
116         jne     3f
118 9:      movl    (%r12), %eax
119 8:      testl   %eax, %eax
120         je      7b
122         leaq    -1(%rax), %rcx
123         LOCK
124         cmpxchgl %ecx, (%r12)
125         jne     8b
127         xorl    %eax, %eax
128 10:     addq    $24, %rsp
129         cfi_adjust_cfa_offset(-24)
130         popq    %r14
131         cfi_adjust_cfa_offset(-8)
132         cfi_restore(14)
133         popq    %r13
134         cfi_adjust_cfa_offset(-8)
135         cfi_restore(13)
136         popq    %r12
137         cfi_adjust_cfa_offset(-8)
138         cfi_restore(12)
139         retq
141         cfi_adjust_cfa_offset(48)
142         cfi_offset(12, -16)             /* %r12 */
143         cfi_offset(13, -24)             /* %r13 */
144         cfi_offset(14, -32)             /* %r14 */
145 3:      negq    %r14
147 #if USE___THREAD
148         movq    errno@gottpoff(%rip), %rdx
149         movl    %r14d, %fs:(%rdx)
150 #else
151         callq   __errno_location@plt
152         movl    %r14d, (%rax)
153 #endif
155         orl     $-1, %eax
156         jmp     10b
157         cfi_endproc
158         .size   sem_timedwait,.-sem_timedwait