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/>. */
20 #include <kernel-features.h>
21 #include <lowlevellock.h>
22 #include <shlib-compat.h>
23 #include <pthread-errnos.h>
24 #include <structsem.h>
29 .type sem_timedwait,@function
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)
39 cfi_personality(DW_EH_PE_udata4, __gcc_personality_v0)
40 cfi_lsda(DW_EH_PE_udata4, .LexceptSTART)
45 movl VALUE(%rdi), %eax
55 cmpxchgl %edx, VALUE(%rdi)
62 /* Check whether the timeout value is valid. */
63 1: cmpq $1000000000, 8(%rsi)
66 #ifndef __ASSUME_FUTEX_CLOCK_REALTIME
68 cmpl $0, __have_futex_clock_realtime(%rip)
70 cmpl $0, __have_futex_clock_realtime
78 /* This push is only needed to store the sem_t pointer for the
81 cfi_adjust_cfa_offset(8)
86 LP_OP(add) $1, NWAITERS(%rdi)
89 13: call __pthread_enable_asynccancel
93 leaq VALUE(%rdi), %rdi
95 movl $0xffffffff, %r9d
96 movl $FUTEX_WAIT_BITSET|FUTEX_CLOCK_REALTIME, %esi
97 orl PRIVATE(%rdi), %esi
103 leaq -VALUE(%rdi), %rdi
107 call __pthread_disable_asynccancel
113 cmpq $-EWOULDBLOCK, %r9
120 movl VALUE(%rdi), %eax
128 cmpxchgl %ecx, (%rdi)
130 cmpxchgl %ecx, VALUE(%rdi)
137 LP_OP(sub) $1, NWAITERS(%rdi)
140 cfi_adjust_cfa_offset(-8)
143 cfi_adjust_cfa_offset(8)
145 movq errno@gottpoff(%rip), %rdx
146 movl %r9d, %fs:(%rdx)
151 cfi_adjust_cfa_offset(-8)
153 movq errno@gottpoff(%rip), %rdx
154 movl $EINVAL, %fs:(%rdx)
161 movq errno@gottpoff(%rip), %rdx
162 movl $ETIMEDOUT, %fs:(%rdx)
168 #ifndef __ASSUME_FUTEX_CLOCK_REALTIME
171 cfi_adjust_cfa_offset(8)
172 cfi_rel_offset(%r12, 0)
174 cfi_adjust_cfa_offset(8)
175 cfi_rel_offset(%r13, 0)
177 cfi_adjust_cfa_offset(8)
178 cfi_rel_offset(%r14, 0)
180 #ifdef __ASSUME_FUTEX_CLOCK_REALTIME
181 # define STACKFRAME 8
183 # define STACKFRAME 24
185 subq $STACKFRAME, %rsp
186 cfi_adjust_cfa_offset(STACKFRAME)
192 LP_OP(add) $1, NWAITERS(%r12)
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. */
203 mul %rdi /* Milli seconds to nano seconds. */
209 addq $1000000000, %rsi
212 movl $ETIMEDOUT, %r14d
213 js 36f /* Time is already up. */
215 movq %rdi, (%rsp) /* Store relative timeout. */
219 call __pthread_enable_asynccancel
226 leaq VALUE(%r12), %rdi
229 movl PRIVATE(%rdi), %esi
231 movl $FUTEX_WAIT, %esi
232 orl PRIVATE(%rdi), %esi
234 movl $SYS_futex, %eax
240 call __pthread_disable_asynccancel
245 cmpq $-EWOULDBLOCK, %r14
252 movl VALUE(%r12), %eax
260 cmpxchgl %ecx, (%r12)
262 cmpxchgl %ecx, VALUE(%r12)
269 LP_OP(sub) $1, NWAITERS(%r12)
271 addq $STACKFRAME, %rsp
272 cfi_adjust_cfa_offset(-STACKFRAME)
274 cfi_adjust_cfa_offset(-8)
277 cfi_adjust_cfa_offset(-8)
280 cfi_adjust_cfa_offset(-8)
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)
290 movq errno@gottpoff(%rip), %rdx
291 movl %r14d, %fs:(%rdx)
297 .size sem_timedwait,.-sem_timedwait
300 .type sem_timedwait_cleanup,@function
301 sem_timedwait_cleanup:
303 cfi_adjust_cfa_offset(8)
307 LP_OP(sub) $1, NWAITERS(%rdi)
310 call _Unwind_Resume@PLT
314 .size sem_timedwait_cleanup,.-sem_timedwait_cleanup
317 #ifndef __ASSUME_FUTEX_CLOCK_REALTIME
318 .type sem_timedwait_cleanup2,@function
319 sem_timedwait_cleanup2:
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)
327 LP_OP(sub) $1, NWAITERS(%r12)
329 movq STACKFRAME(%rsp), %r14
330 movq STACKFRAME+8(%rsp), %r13
331 movq STACKFRAME+16(%rsp), %r12
333 call _Unwind_Resume@PLT
337 .size sem_timedwait_cleanup2,.-sem_timedwait_cleanup2
341 .section .gcc_except_table,"a",@progbits
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
348 .uleb128 .LcleanupSTART-.LSTARTCODE
349 .uleb128 .LcleanupEND-.LcleanupSTART
350 .uleb128 sem_timedwait_cleanup-.LSTARTCODE
352 #ifndef __ASSUME_FUTEX_CLOCK_REALTIME
353 .uleb128 .LcleanupSTART2-.LSTARTCODE
354 .uleb128 .LcleanupEND2-.LcleanupSTART2
355 .uleb128 sem_timedwait_cleanup2-.LSTARTCODE
358 .uleb128 .LcallUR-.LSTARTCODE
359 .uleb128 .LENDCODE-.LcallUR
362 #ifndef __ASSUME_FUTEX_CLOCK_REALTIME
363 .uleb128 .LcallUR2-.LSTARTCODE
364 .uleb128 .LENDCODE2-.LcallUR2
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
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