Updated to fedora-glibc-20041006T0900
[kopensolaris-gnu/glibc.git] / nptl / sysdeps / unix / sysv / linux / x86_64 / sem_timedwait.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 <shlib-compat.h>
22 #include <pthread-errnos.h>
23
24 #ifndef UP
25 # define LOCK lock
26 #else
27 # define
28 #endif
29
30 #define SYS_futex               202
31
32 /* For the calculation see asm/vsyscall.h.  */
33 #define VSYSCALL_ADDR_vgettimeofday     0xffffffffff600000
34
35
36         .text
37
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
48
49         movl    (%rdi), %eax
50 2:      testl   %eax, %eax
51         je      1f
52
53         leaq    -1(%rax), %rdx
54         LOCK
55         cmpxchgl %edx, (%rdi)
56         jne     2b
57
58         xorl    %eax, %eax
59         retq
60
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)
70
71         movq    %rdi, %r12
72         cfi_offset(12, -16)             /* %r12 */
73         movq    %rsi, %r13
74         cfi_offset(13, -24)             /* %r13 */
75
76         /* Check for invalid nanosecond field.  */
77         cmpq    $1000000000, 8(%r13)
78         movl    $EINVAL, %r14d
79         cfi_offset(14, -24)             /* %r14 */
80         jae     6f
81
82 7:      call    __pthread_enable_asynccancel
83         movl    %eax, 16(%rsp)
84
85         xorq    %rsi, %rsi
86         movq    %rsp, %rdi
87         movq    $VSYSCALL_ADDR_vgettimeofday, %rax
88         callq   *%rax
89
90         /* Compute relative timeout.  */
91         movq    8(%rsp), %rax
92         movq    $1000, %rdi
93         mul     %rdi            /* Milli seconds to nano seconds.  */
94         movq    (%r13), %rdi
95         movq    8(%r13), %rsi
96         subq    (%rsp), %rdi
97         subq    %rax, %rsi
98         jns     5f
99         addq    $1000000000, %rsi
100         decq    %rdi
101 5:      testq   %rdi, %rdi
102         movl    $ETIMEDOUT, %r14d
103         js      6f              /* Time is already up.  */
104
105         movq    %rdi, (%rsp)    /* Store relative timeout.  */
106         movq    %rsi, 8(%rsp)
107
108         movq    %rsp, %r10
109         movq    %r12, %rdi
110         xorq    %rsi, %rsi
111         movq    $SYS_futex, %rax
112         xorl    %edx, %edx
113         syscall
114         movq    %rax, %r14
115
116         movl    16(%rsp), %edi
117         call    __pthread_disable_asynccancel
118
119         testq   %r14, %r14
120         je      9f
121         cmpq    $-EWOULDBLOCK, %r14
122         jne     3f
123
124 9:      movl    (%r12), %eax
125 8:      testl   %eax, %eax
126         je      7b
127
128         leaq    -1(%rax), %rcx
129         LOCK
130         cmpxchgl %ecx, (%r12)
131         jne     8b
132
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
146
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
152 6:
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
160
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)
167
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