2.5-18.1
[glibc.git] / nptl / sysdeps / unix / sysv / linux / x86_64 / sem_timedwait.S
blob51136cf2dc4bc1affad23295a5c33120a9ab8b5b
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         /* First check for cancellation.  */
44         movl    %fs:CANCELHANDLING, %eax
45         andl    $0xfffffff9, %eax
46         cmpl    $8, %eax
47         je      11f
49         movl    (%rdi), %eax
50 2:      testl   %eax, %eax
51         je      1f
53         leaq    -1(%rax), %rdx
54         LOCK
55         cmpxchgl %edx, (%rdi)
56         jne     2b
58         xorl    %eax, %eax
59         retq
61         /* Check whether the timeout value is valid.  */
62 1:      pushq   %r12
63         cfi_adjust_cfa_offset(8)
64         pushq   %r13
65         cfi_adjust_cfa_offset(8)
66         pushq   %r14
67         cfi_adjust_cfa_offset(8)
68         subq    $24, %rsp
69         cfi_adjust_cfa_offset(24)
71         movq    %rdi, %r12
72         cfi_offset(12, -16)             /* %r12 */
73         movq    %rsi, %r13
74         cfi_offset(13, -24)             /* %r13 */
76         /* Check for invalid nanosecond field.  */
77         cmpq    $1000000000, 8(%r13)
78         movl    $EINVAL, %r14d
79         cfi_offset(14, -24)             /* %r14 */
80         jae     6f
82 7:      xorl    %esi, %esi
83         movq    %rsp, %rdi
84         movq    $VSYSCALL_ADDR_vgettimeofday, %rax
85         callq   *%rax
87         /* Compute relative timeout.  */
88         movq    8(%rsp), %rax
89         movl    $1000, %edi
90         mul     %rdi            /* Milli seconds to nano seconds.  */
91         movq    (%r13), %rdi
92         movq    8(%r13), %rsi
93         subq    (%rsp), %rdi
94         subq    %rax, %rsi
95         jns     5f
96         addq    $1000000000, %rsi
97         decq    %rdi
98 5:      testq   %rdi, %rdi
99         movl    $ETIMEDOUT, %r14d
100         js      6f              /* Time is already up.  */
102         movq    %rdi, (%rsp)    /* Store relative timeout.  */
103         movq    %rsi, 8(%rsp)
105         call    __pthread_enable_asynccancel
106         movl    %eax, 16(%rsp)
108         movq    %rsp, %r10
109         movq    %r12, %rdi
110         xorl    %esi, %esi
111         movl    $SYS_futex, %eax
112         xorl    %edx, %edx
113         syscall
114         movq    %rax, %r14
116         movl    16(%rsp), %edi
117         call    __pthread_disable_asynccancel
119         testq   %r14, %r14
120         je      9f
121         cmpq    $-EWOULDBLOCK, %r14
122         jne     3f
124 9:      movl    (%r12), %eax
125 8:      testl   %eax, %eax
126         je      7b
128         leaq    -1(%rax), %rcx
129         LOCK
130         cmpxchgl %ecx, (%r12)
131         jne     8b
133         xorl    %eax, %eax
134 10:     addq    $24, %rsp
135         cfi_adjust_cfa_offset(-24)
136         popq    %r14
137         cfi_adjust_cfa_offset(-8)
138         cfi_restore(14)
139         popq    %r13
140         cfi_adjust_cfa_offset(-8)
141         cfi_restore(13)
142         popq    %r12
143         cfi_adjust_cfa_offset(-8)
144         cfi_restore(12)
145         retq
147         cfi_adjust_cfa_offset(48)
148         cfi_offset(12, -16)             /* %r12 */
149         cfi_offset(13, -24)             /* %r13 */
150         cfi_offset(14, -32)             /* %r14 */
151 3:      negq    %r14
153 #if USE___THREAD
154         movq    errno@gottpoff(%rip), %rdx
155         movl    %r14d, %fs:(%rdx)
156 #else
157         callq   __errno_location@plt
158         movl    %r14d, (%rax)
159 #endif
161         orl     $-1, %eax
162         jmp     10b
163         cfi_adjust_cfa_offset(-48)
164         cfi_restore(14)
165         cfi_restore(13)
166         cfi_restore(12)
168 11:     /* Canceled.  */
169         movq    $0xffffffffffffffff, %fs:RESULT
170         LOCK
171         orl     $0x10, %fs:CANCELHANDLING
172         movq    %fs:CLEANUP_JMP_BUF, %rdi
173         jmp     HIDDEN_JUMPTARGET (__pthread_unwind)
174         cfi_endproc
175         .size   sem_timedwait,.-sem_timedwait