2.9
[glibc/nacl-glibc.git] / nptl / sysdeps / unix / sysv / linux / x86_64 / sem_timedwait.S
blob88e99cf6a1ff389dc0ed31d66de93f5e1dee61e4
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 <lowlevellock.h>
22 #include <shlib-compat.h>
23 #include <pthread-errnos.h>
24 #include <structsem.h>
27 /* For the calculation see asm/vsyscall.h.  */
28 #define VSYSCALL_ADDR_vgettimeofday     0xffffffffff600000
30         .text
32         .globl  sem_timedwait
33         .type   sem_timedwait,@function
34         .align  16
35 sem_timedwait:
36 .LSTARTCODE:
37 #if VALUE == 0
38         movl    (%rdi), %eax
39 #else
40         movl    VALUE(%rdi), %eax
41 #endif
42 2:      testl   %eax, %eax
43         je      1f
45         leaq    -1(%rax), %rdx
46         LOCK
47 #if VALUE == 0
48         cmpxchgl %edx, (%rdi)
49 #else
50         cmpxchgl %edx, VALUE(%rdi)
51 #endif
52         jne     2b
54         xorl    %eax, %eax
55         retq
57         /* Check whether the timeout value is valid.  */
58 1:      pushq   %r12
59 .Lpush_r12:
60         pushq   %r13
61 .Lpush_r13:
62         pushq   %r14
63 .Lpush_r14:
64         subq    $24, %rsp
65 .Lsubq:
67         movq    %rdi, %r12
68         movq    %rsi, %r13
70         /* Check for invalid nanosecond field.  */
71         cmpq    $1000000000, 8(%r13)
72         movl    $EINVAL, %r14d
73         jae     6f
75         LOCK
76         addq    $1, NWAITERS(%r12)
78 7:      xorl    %esi, %esi
79         movq    %rsp, %rdi
80         movq    $VSYSCALL_ADDR_vgettimeofday, %rax
81         callq   *%rax
83         /* Compute relative timeout.  */
84         movq    8(%rsp), %rax
85         movl    $1000, %edi
86         mul     %rdi            /* Milli seconds to nano seconds.  */
87         movq    (%r13), %rdi
88         movq    8(%r13), %rsi
89         subq    (%rsp), %rdi
90         subq    %rax, %rsi
91         jns     5f
92         addq    $1000000000, %rsi
93         decq    %rdi
94 5:      testq   %rdi, %rdi
95         movl    $ETIMEDOUT, %r14d
96         js      6f              /* Time is already up.  */
98         movq    %rdi, (%rsp)    /* Store relative timeout.  */
99         movq    %rsi, 8(%rsp)
101 .LcleanupSTART:
102         call    __pthread_enable_asynccancel
103         movl    %eax, 16(%rsp)
105         movq    %rsp, %r10
106 #if VALUE == 0
107         movq    %r12, %rdi
108 #else
109         leaq    VALUE(%r12), %rdi
110 #endif
111 #if FUTEX_WAIT == 0
112         movl    PRIVATE(%rdi), %esi
113 #else
114         movl    $FUTEX_WAIT, %esi
115         orl     PRIVATE(%rdi), %esi
116 #endif
117         movl    $SYS_futex, %eax
118         xorl    %edx, %edx
119         syscall
120         movq    %rax, %r14
122         movl    16(%rsp), %edi
123         call    __pthread_disable_asynccancel
124 .LcleanupEND:
126         testq   %r14, %r14
127         je      9f
128         cmpq    $-EWOULDBLOCK, %r14
129         jne     3f
132 #if VALUE == 0
133         movl    (%r12), %eax
134 #else
135         movl    VALUE(%r12), %eax
136 #endif
137 8:      testl   %eax, %eax
138         je      7b
140         leaq    -1(%rax), %rcx
141         LOCK
142 #if VALUE == 0
143         cmpxchgl %ecx, (%r12)
144 #else
145         cmpxchgl %ecx, VALUE(%r12)
146 #endif
147         jne     8b
149         xorl    %eax, %eax
151 10:     LOCK
152         subq    $1, NWAITERS(%r12)
154         addq    $24, %rsp
155 .Laddq:
156         popq    %r14
157 .Lpop_r14:
158         popq    %r13
159 .Lpop_r13:
160         popq    %r12
161 .Lpop_r12:
162         retq
164 .Lafter_retq:
165 3:      negq    %r14
167 #if USE___THREAD
168         movq    errno@gottpoff(%rip), %rdx
169         movl    %r14d, %fs:(%rdx)
170 #else
171         callq   __errno_location@plt
172         movl    %r14d, (%rax)
173 #endif
175         orl     $-1, %eax
176         jmp     10b
177         .size   sem_timedwait,.-sem_timedwait
180         .type   sem_timedwait_cleanup,@function
181 sem_timedwait_cleanup:
182         LOCK
183         subq    $1, NWAITERS(%r12)
184         movq    %rax, %rdi
185 .LcallUR:
186         call    _Unwind_Resume@PLT
187         hlt
188 .LENDCODE:
189         .size   sem_timedwait_cleanup,.-sem_timedwait_cleanup
192         .section .gcc_except_table,"a",@progbits
193 .LexceptSTART:
194         .byte   0xff                            # @LPStart format (omit)
195         .byte   0xff                            # @TType format (omit)
196         .byte   0x01                            # call-site format
197                                                 # DW_EH_PE_uleb128
198         .uleb128 .Lcstend-.Lcstbegin
199 .Lcstbegin:
200         .uleb128 .LcleanupSTART-.LSTARTCODE
201         .uleb128 .LcleanupEND-.LcleanupSTART
202         .uleb128 sem_timedwait_cleanup-.LSTARTCODE
203         .uleb128  0
204         .uleb128 .LcallUR-.LSTARTCODE
205         .uleb128 .LENDCODE-.LcallUR
206         .uleb128 0
207         .uleb128  0
208 .Lcstend:
211         .section .eh_frame,"a",@progbits
212 .LSTARTFRAME:
213         .long   .LENDCIE-.LSTARTCIE             # Length of the CIE.
214 .LSTARTCIE:
215         .long   0                               # CIE ID.
216         .byte   1                               # Version number.
217 #ifdef SHARED
218         .string "zPLR"                          # NUL-terminated augmentation
219                                                 # string.
220 #else
221         .string "zPL"                           # NUL-terminated augmentation
222                                                 # string.
223 #endif
224         .uleb128 1                              # Code alignment factor.
225         .sleb128 -8                             # Data alignment factor.
226         .byte   16                              # Return address register
227                                                 # column.
228 #ifdef SHARED
229         .uleb128 7                              # Augmentation value length.
230         .byte   0x9b                            # Personality: DW_EH_PE_pcrel
231                                                 # + DW_EH_PE_sdata4
232                                                 # + DW_EH_PE_indirect
233         .long   DW.ref.__gcc_personality_v0-.
234         .byte   0x1b                            # LSDA Encoding: DW_EH_PE_pcrel
235                                                 # + DW_EH_PE_sdata4.
236         .byte   0x1b                            # FDE Encoding: DW_EH_PE_pcrel
237                                                 # + DW_EH_PE_sdata4.
238 #else
239         .uleb128 10                             # Augmentation value length.
240         .byte   0x0                             # Personality: absolute
241         .quad   __gcc_personality_v0
242         .byte   0x0                             # LSDA Encoding: absolute
243 #endif
244         .byte 0x0c                              # DW_CFA_def_cfa
245         .uleb128 7
246         .uleb128 8
247         .byte   0x90                            # DW_CFA_offset, column 0x10
248         .uleb128 1
249         .align 8
250 .LENDCIE:
252         .long   .LENDFDE-.LSTARTFDE             # Length of the FDE.
253 .LSTARTFDE:
254         .long   .LSTARTFDE-.LSTARTFRAME         # CIE pointer.
255 #ifdef SHARED
256         .long   .LSTARTCODE-.                   # PC-relative start address
257                                                 # of the code.
258         .long   .LENDCODE-.LSTARTCODE           # Length of the code.
259         .uleb128 4                              # Augmentation size
260         .long   .LexceptSTART-.
261 #else
262         .quad   .LSTARTCODE                     # Start address of the code.
263         .quad   .LENDCODE-.LSTARTCODE           # Length of the code.
264         .uleb128 8                              # Augmentation size
265         .quad   .LexceptSTART
266 #endif
268         .byte   4                               # DW_CFA_advance_loc4
269         .long   .Lpush_r12-.LSTARTCODE
270         .byte   14                              # DW_CFA_def_cfa_offset
271         .uleb128 16
272         .byte   0x8c                            # DW_CFA_offset %r12
273         .uleb128 2
274         .byte   4                               # DW_CFA_advance_loc4
275         .long   .Lpush_r13-.Lpush_r12
276         .byte   14                              # DW_CFA_def_cfa_offset
277         .uleb128 24
278         .byte   0x8d                            # DW_CFA_offset %r13
279         .uleb128 3
280         .byte   4                               # DW_CFA_advance_loc4
281         .long   .Lpush_r14-.Lpush_r13
282         .byte   14                              # DW_CFA_def_cfa_offset
283         .uleb128 32
284         .byte   0x8e                            # DW_CFA_offset %r14
285         .uleb128 4
286         .byte   4                               # DW_CFA_advance_loc4
287         .long   .Lsubq-.Lpush_r14
288         .byte   14                              # DW_CFA_def_cfa_offset
289         .uleb128 56
290         .byte   4                               # DW_CFA_advance_loc4
291         .long   .Laddq-.Lsubq
292         .byte   14                              # DW_CFA_def_cfa_offset
293         .uleb128 32
294         .byte   4                               # DW_CFA_advance_loc4
295         .long   .Lpop_r14-.Laddq
296         .byte   14                              # DW_CFA_def_cfa_offset
297         .uleb128 24
298         .byte   0xce                            # DW_CFA_restore %r14
299         .byte   4                               # DW_CFA_advance_loc4
300         .long   .Lpop_r13-.Lpop_r14
301         .byte   14                              # DW_CFA_def_cfa_offset
302         .uleb128 16
303         .byte   0xcd                            # DW_CFA_restore %r13
304         .byte   4                               # DW_CFA_advance_loc4
305         .long   .Lpop_r12-.Lpop_r13
306         .byte   14                              # DW_CFA_def_cfa_offset
307         .uleb128 8
308         .byte   0xcc                            # DW_CFA_restore %r12
309         .byte   4                               # DW_CFA_advance_loc4
310         .long   .Lafter_retq-.Lpop_r12
311         .byte   14                              # DW_CFA_def_cfa_offset
312         .uleb128 56
313         .byte   0x8c                            # DW_CFA_offset %r12
314         .uleb128 2
315         .byte   0x8d                            # DW_CFA_offset %r13
316         .uleb128 3
317         .byte   0x8e                            # DW_CFA_offset %r14
318         .uleb128 4
319         .align  8
320 .LENDFDE:
323 #ifdef SHARED
324         .hidden DW.ref.__gcc_personality_v0
325         .weak   DW.ref.__gcc_personality_v0
326         .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
327         .align  8
328         .type   DW.ref.__gcc_personality_v0, @object
329         .size   DW.ref.__gcc_personality_v0, 8
330 DW.ref.__gcc_personality_v0:
331         .quad   __gcc_personality_v0
332 #endif