Update copyright dates with scripts/update-copyrights.
[glibc.git] / sysdeps / unix / sysv / linux / x86_64 / sem_timedwait.S
blob091b2411b44f4c3f80688c15907dd601d537d316
1 /* Copyright (C) 2002-2015 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, see
17    <http://www.gnu.org/licenses/>.  */
19 #include <sysdep.h>
20 #include <kernel-features.h>
21 #include <lowlevellock.h>
22 #include <shlib-compat.h>
23 #include <pthread-errnos.h>
24 #include <structsem.h>
26         .text
28         .globl  sem_timedwait
29         .type   sem_timedwait,@function
30         .align  16
31 sem_timedwait:
32 .LSTARTCODE:
33         cfi_startproc
34 #ifdef SHARED
35         cfi_personality(DW_EH_PE_pcrel | DW_EH_PE_sdata4 | DW_EH_PE_indirect,
36                         DW.ref.__gcc_personality_v0)
37         cfi_lsda(DW_EH_PE_pcrel | DW_EH_PE_sdata4, .LexceptSTART)
38 #else
39         cfi_personality(DW_EH_PE_udata4, __gcc_personality_v0)
40         cfi_lsda(DW_EH_PE_udata4, .LexceptSTART)
41 #endif
42 #if VALUE == 0
43         movl    (%rdi), %eax
44 #else
45         movl    VALUE(%rdi), %eax
46 #endif
47 2:      testl   %eax, %eax
48         je      1f
50         leaq    -1(%rax), %rdx
51         LOCK
52 #if VALUE == 0
53         cmpxchgl %edx, (%rdi)
54 #else
55         cmpxchgl %edx, VALUE(%rdi)
56 #endif
57         jne     2b
59         xorl    %eax, %eax
60         retq
62         /* Check whether the timeout value is valid.  */
63 1:      cmpq    $1000000000, 8(%rsi)
64         jae     6f
66 #ifndef __ASSUME_FUTEX_CLOCK_REALTIME
67 #  ifdef PIC
68         cmpl    $0, __have_futex_clock_realtime(%rip)
69 #  else
70         cmpl    $0, __have_futex_clock_realtime
71 #  endif
72         je      .Lreltmo
73 #endif
75         cmpq    $0, (%rsi)
76         js      16f
78         /* This push is only needed to store the sem_t pointer for the
79            exception handler.  */
80         pushq   %rdi
81         cfi_adjust_cfa_offset(8)
83         movq    %rsi, %r10
85         LOCK
86         LP_OP(add) $1, NWAITERS(%rdi)
88 .LcleanupSTART:
89 13:     call    __pthread_enable_asynccancel
90         movl    %eax, %r8d
92 #if VALUE != 0
93         leaq    VALUE(%rdi), %rdi
94 #endif
95         movl    $0xffffffff, %r9d
96         movl    $FUTEX_WAIT_BITSET|FUTEX_CLOCK_REALTIME, %esi
97         orl     PRIVATE(%rdi), %esi
98         movl    $SYS_futex, %eax
99         xorl    %edx, %edx
100         syscall
101         movq    %rax, %r9
102 #if VALUE != 0
103         leaq    -VALUE(%rdi), %rdi
104 #endif
106         xchgq   %r8, %rdi
107         call    __pthread_disable_asynccancel
108 .LcleanupEND:
109         movq    %r8, %rdi
111         testq   %r9, %r9
112         je      11f
113         cmpq    $-EWOULDBLOCK, %r9
114         jne     3f
117 #if VALUE == 0
118         movl    (%rdi), %eax
119 #else
120         movl    VALUE(%rdi), %eax
121 #endif
122 14:     testl   %eax, %eax
123         je      13b
125         leaq    -1(%rax), %rcx
126         LOCK
127 #if VALUE == 0
128         cmpxchgl %ecx, (%rdi)
129 #else
130         cmpxchgl %ecx, VALUE(%rdi)
131 #endif
132         jne     14b
134         xorl    %eax, %eax
136 15:     LOCK
137         LP_OP(sub) $1, NWAITERS(%rdi)
139         leaq    8(%rsp), %rsp
140         cfi_adjust_cfa_offset(-8)
141         retq
143         cfi_adjust_cfa_offset(8)
144 3:      negq    %r9
145         movq    errno@gottpoff(%rip), %rdx
146         movl    %r9d, %fs:(%rdx)
148         orl     $-1, %eax
149         jmp     15b
151         cfi_adjust_cfa_offset(-8)
153         movq    errno@gottpoff(%rip), %rdx
154         movl    $EINVAL, %fs:(%rdx)
156         orl     $-1, %eax
158         retq
161         movq    errno@gottpoff(%rip), %rdx
162         movl    $ETIMEDOUT, %fs:(%rdx)
164         orl     $-1, %eax
166         retq
168 #ifndef __ASSUME_FUTEX_CLOCK_REALTIME
169 .Lreltmo:
170         pushq   %r12
171         cfi_adjust_cfa_offset(8)
172         cfi_rel_offset(%r12, 0)
173         pushq   %r13
174         cfi_adjust_cfa_offset(8)
175         cfi_rel_offset(%r13, 0)
176         pushq   %r14
177         cfi_adjust_cfa_offset(8)
178         cfi_rel_offset(%r14, 0)
180 #ifdef __ASSUME_FUTEX_CLOCK_REALTIME
181 # define STACKFRAME 8
182 #else
183 # define STACKFRAME 24
184 #endif
185         subq    $STACKFRAME, %rsp
186         cfi_adjust_cfa_offset(STACKFRAME)
188         movq    %rdi, %r12
189         movq    %rsi, %r13
191         LOCK
192         LP_OP(add) $1, NWAITERS(%r12)
194 7:      xorl    %esi, %esi
195         movq    %rsp,%rdi
196         /* This call works because we directly jump to a system call entry
197            which preserves all the registers.  */
198         call    JUMPTARGET(__gettimeofday)
200         /* Compute relative timeout.  */
201         movq    8(%rsp), %rax
202         movl    $1000, %edi
203         mul     %rdi            /* Milli seconds to nano seconds.  */
204         movq    (%r13), %rdi
205         movq    8(%r13), %rsi
206         subq    (%rsp), %rdi
207         subq    %rax, %rsi
208         jns     5f
209         addq    $1000000000, %rsi
210         decq    %rdi
211 5:      testq   %rdi, %rdi
212         movl    $ETIMEDOUT, %r14d
213         js      36f             /* Time is already up.  */
215         movq    %rdi, (%rsp)    /* Store relative timeout.  */
216         movq    %rsi, 8(%rsp)
218 .LcleanupSTART2:
219         call    __pthread_enable_asynccancel
220         movl    %eax, 16(%rsp)
222         movq    %rsp, %r10
223 # if VALUE == 0
224         movq    %r12, %rdi
225 # else
226         leaq    VALUE(%r12), %rdi
227 # endif
228 # if FUTEX_WAIT == 0
229         movl    PRIVATE(%rdi), %esi
230 # else
231         movl    $FUTEX_WAIT, %esi
232         orl     PRIVATE(%rdi), %esi
233 # endif
234         movl    $SYS_futex, %eax
235         xorl    %edx, %edx
236         syscall
237         movq    %rax, %r14
239         movl    16(%rsp), %edi
240         call    __pthread_disable_asynccancel
241 .LcleanupEND2:
243         testq   %r14, %r14
244         je      9f
245         cmpq    $-EWOULDBLOCK, %r14
246         jne     33f
249 # if VALUE == 0
250         movl    (%r12), %eax
251 # else
252         movl    VALUE(%r12), %eax
253 # endif
254 8:      testl   %eax, %eax
255         je      7b
257         leaq    -1(%rax), %rcx
258         LOCK
259 # if VALUE == 0
260         cmpxchgl %ecx, (%r12)
261 # else
262         cmpxchgl %ecx, VALUE(%r12)
263 # endif
264         jne     8b
266         xorl    %eax, %eax
268 45:     LOCK
269         LP_OP(sub) $1, NWAITERS(%r12)
271         addq    $STACKFRAME, %rsp
272         cfi_adjust_cfa_offset(-STACKFRAME)
273         popq    %r14
274         cfi_adjust_cfa_offset(-8)
275         cfi_restore(%r14)
276         popq    %r13
277         cfi_adjust_cfa_offset(-8)
278         cfi_restore(%r13)
279         popq    %r12
280         cfi_adjust_cfa_offset(-8)
281         cfi_restore(%r12)
282         retq
284         cfi_adjust_cfa_offset(STACKFRAME + 3 * 8)
285         cfi_rel_offset(%r12, STACKFRAME + 2 * 8)
286         cfi_rel_offset(%r13, STACKFRAME + 1 * 8)
287         cfi_rel_offset(%r14, STACKFRAME)
288 33:     negq    %r14
290         movq    errno@gottpoff(%rip), %rdx
291         movl    %r14d, %fs:(%rdx)
293         orl     $-1, %eax
294         jmp     45b
295 #endif
296         cfi_endproc
297         .size   sem_timedwait,.-sem_timedwait
300         .type   sem_timedwait_cleanup,@function
301 sem_timedwait_cleanup:
302         cfi_startproc
303         cfi_adjust_cfa_offset(8)
305         movq    (%rsp), %rdi
306         LOCK
307         LP_OP(sub) $1, NWAITERS(%rdi)
308         movq    %rax, %rdi
309 .LcallUR:
310         call    _Unwind_Resume@PLT
311         hlt
312 .LENDCODE:
313         cfi_endproc
314         .size   sem_timedwait_cleanup,.-sem_timedwait_cleanup
317 #ifndef __ASSUME_FUTEX_CLOCK_REALTIME
318         .type   sem_timedwait_cleanup2,@function
319 sem_timedwait_cleanup2:
320         cfi_startproc
321         cfi_adjust_cfa_offset(STACKFRAME + 3 * 8)
322         cfi_rel_offset(%r12, STACKFRAME + 2 * 8)
323         cfi_rel_offset(%r13, STACKFRAME + 1 * 8)
324         cfi_rel_offset(%r14, STACKFRAME)
326         LOCK
327         LP_OP(sub) $1, NWAITERS(%r12)
328         movq    %rax, %rdi
329         movq    STACKFRAME(%rsp), %r14
330         movq    STACKFRAME+8(%rsp), %r13
331         movq    STACKFRAME+16(%rsp), %r12
332 .LcallUR2:
333         call    _Unwind_Resume@PLT
334         hlt
335 .LENDCODE2:
336         cfi_endproc
337         .size   sem_timedwait_cleanup2,.-sem_timedwait_cleanup2
338 #endif
341         .section .gcc_except_table,"a",@progbits
342 .LexceptSTART:
343         .byte   DW_EH_PE_omit                   # @LPStart format
344         .byte   DW_EH_PE_omit                   # @TType format
345         .byte   DW_EH_PE_uleb128                # call-site format
346         .uleb128 .Lcstend-.Lcstbegin
347 .Lcstbegin:
348         .uleb128 .LcleanupSTART-.LSTARTCODE
349         .uleb128 .LcleanupEND-.LcleanupSTART
350         .uleb128 sem_timedwait_cleanup-.LSTARTCODE
351         .uleb128  0
352 #ifndef __ASSUME_FUTEX_CLOCK_REALTIME
353         .uleb128 .LcleanupSTART2-.LSTARTCODE
354         .uleb128 .LcleanupEND2-.LcleanupSTART2
355         .uleb128 sem_timedwait_cleanup2-.LSTARTCODE
356         .uleb128  0
357 #endif
358         .uleb128 .LcallUR-.LSTARTCODE
359         .uleb128 .LENDCODE-.LcallUR
360         .uleb128 0
361         .uleb128  0
362 #ifndef __ASSUME_FUTEX_CLOCK_REALTIME
363         .uleb128 .LcallUR2-.LSTARTCODE
364         .uleb128 .LENDCODE2-.LcallUR2
365         .uleb128 0
366         .uleb128  0
367 #endif
368 .Lcstend:
371 #ifdef SHARED
372         .hidden DW.ref.__gcc_personality_v0
373         .weak   DW.ref.__gcc_personality_v0
374         .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
375         .align  LP_SIZE
376         .type   DW.ref.__gcc_personality_v0, @object
377         .size   DW.ref.__gcc_personality_v0, LP_SIZE
378 DW.ref.__gcc_personality_v0:
379         ASM_ADDR __gcc_personality_v0
380 #endif