mirror of
https://sourceware.org/git/glibc.git
synced 2024-12-26 20:51:11 +00:00
381 lines
7.4 KiB
ArmAsm
381 lines
7.4 KiB
ArmAsm
/* Copyright (C) 2002-2014 Free Software Foundation, Inc.
|
|
This file is part of the GNU C Library.
|
|
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
|
|
|
The GNU C Library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
The GNU C Library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with the GNU C Library; if not, see
|
|
<http://www.gnu.org/licenses/>. */
|
|
|
|
#include <sysdep.h>
|
|
#include <kernel-features.h>
|
|
#include <lowlevellock.h>
|
|
#include <shlib-compat.h>
|
|
#include <pthread-errnos.h>
|
|
#include <structsem.h>
|
|
|
|
.text
|
|
|
|
.globl sem_timedwait
|
|
.type sem_timedwait,@function
|
|
.align 16
|
|
sem_timedwait:
|
|
.LSTARTCODE:
|
|
cfi_startproc
|
|
#ifdef SHARED
|
|
cfi_personality(DW_EH_PE_pcrel | DW_EH_PE_sdata4 | DW_EH_PE_indirect,
|
|
DW.ref.__gcc_personality_v0)
|
|
cfi_lsda(DW_EH_PE_pcrel | DW_EH_PE_sdata4, .LexceptSTART)
|
|
#else
|
|
cfi_personality(DW_EH_PE_udata4, __gcc_personality_v0)
|
|
cfi_lsda(DW_EH_PE_udata4, .LexceptSTART)
|
|
#endif
|
|
#if VALUE == 0
|
|
movl (%rdi), %eax
|
|
#else
|
|
movl VALUE(%rdi), %eax
|
|
#endif
|
|
2: testl %eax, %eax
|
|
je 1f
|
|
|
|
leaq -1(%rax), %rdx
|
|
LOCK
|
|
#if VALUE == 0
|
|
cmpxchgl %edx, (%rdi)
|
|
#else
|
|
cmpxchgl %edx, VALUE(%rdi)
|
|
#endif
|
|
jne 2b
|
|
|
|
xorl %eax, %eax
|
|
retq
|
|
|
|
/* Check whether the timeout value is valid. */
|
|
1: cmpq $1000000000, 8(%rsi)
|
|
jae 6f
|
|
|
|
#ifndef __ASSUME_FUTEX_CLOCK_REALTIME
|
|
# ifdef PIC
|
|
cmpl $0, __have_futex_clock_realtime(%rip)
|
|
# else
|
|
cmpl $0, __have_futex_clock_realtime
|
|
# endif
|
|
je .Lreltmo
|
|
#endif
|
|
|
|
cmpq $0, (%rsi)
|
|
js 16f
|
|
|
|
/* This push is only needed to store the sem_t pointer for the
|
|
exception handler. */
|
|
pushq %rdi
|
|
cfi_adjust_cfa_offset(8)
|
|
|
|
movq %rsi, %r10
|
|
|
|
LOCK
|
|
LP_OP(add) $1, NWAITERS(%rdi)
|
|
|
|
.LcleanupSTART:
|
|
13: call __pthread_enable_asynccancel
|
|
movl %eax, %r8d
|
|
|
|
#if VALUE != 0
|
|
leaq VALUE(%rdi), %rdi
|
|
#endif
|
|
movl $0xffffffff, %r9d
|
|
movl $FUTEX_WAIT_BITSET|FUTEX_CLOCK_REALTIME, %esi
|
|
orl PRIVATE(%rdi), %esi
|
|
movl $SYS_futex, %eax
|
|
xorl %edx, %edx
|
|
syscall
|
|
movq %rax, %r9
|
|
#if VALUE != 0
|
|
leaq -VALUE(%rdi), %rdi
|
|
#endif
|
|
|
|
xchgq %r8, %rdi
|
|
call __pthread_disable_asynccancel
|
|
.LcleanupEND:
|
|
movq %r8, %rdi
|
|
|
|
testq %r9, %r9
|
|
je 11f
|
|
cmpq $-EWOULDBLOCK, %r9
|
|
jne 3f
|
|
|
|
11:
|
|
#if VALUE == 0
|
|
movl (%rdi), %eax
|
|
#else
|
|
movl VALUE(%rdi), %eax
|
|
#endif
|
|
14: testl %eax, %eax
|
|
je 13b
|
|
|
|
leaq -1(%rax), %rcx
|
|
LOCK
|
|
#if VALUE == 0
|
|
cmpxchgl %ecx, (%rdi)
|
|
#else
|
|
cmpxchgl %ecx, VALUE(%rdi)
|
|
#endif
|
|
jne 14b
|
|
|
|
xorl %eax, %eax
|
|
|
|
15: LOCK
|
|
LP_OP(sub) $1, NWAITERS(%rdi)
|
|
|
|
leaq 8(%rsp), %rsp
|
|
cfi_adjust_cfa_offset(-8)
|
|
retq
|
|
|
|
cfi_adjust_cfa_offset(8)
|
|
3: negq %r9
|
|
movq errno@gottpoff(%rip), %rdx
|
|
movl %r9d, %fs:(%rdx)
|
|
|
|
orl $-1, %eax
|
|
jmp 15b
|
|
|
|
cfi_adjust_cfa_offset(-8)
|
|
6:
|
|
movq errno@gottpoff(%rip), %rdx
|
|
movl $EINVAL, %fs:(%rdx)
|
|
|
|
orl $-1, %eax
|
|
|
|
retq
|
|
|
|
16:
|
|
movq errno@gottpoff(%rip), %rdx
|
|
movl $ETIMEDOUT, %fs:(%rdx)
|
|
|
|
orl $-1, %eax
|
|
|
|
retq
|
|
|
|
#ifndef __ASSUME_FUTEX_CLOCK_REALTIME
|
|
.Lreltmo:
|
|
pushq %r12
|
|
cfi_adjust_cfa_offset(8)
|
|
cfi_rel_offset(%r12, 0)
|
|
pushq %r13
|
|
cfi_adjust_cfa_offset(8)
|
|
cfi_rel_offset(%r13, 0)
|
|
pushq %r14
|
|
cfi_adjust_cfa_offset(8)
|
|
cfi_rel_offset(%r14, 0)
|
|
|
|
#ifdef __ASSUME_FUTEX_CLOCK_REALTIME
|
|
# define STACKFRAME 8
|
|
#else
|
|
# define STACKFRAME 24
|
|
#endif
|
|
subq $STACKFRAME, %rsp
|
|
cfi_adjust_cfa_offset(STACKFRAME)
|
|
|
|
movq %rdi, %r12
|
|
movq %rsi, %r13
|
|
|
|
LOCK
|
|
LP_OP(add) $1, NWAITERS(%r12)
|
|
|
|
7: xorl %esi, %esi
|
|
movq %rsp,%rdi
|
|
/* This call works because we directly jump to a system call entry
|
|
which preserves all the registers. */
|
|
call JUMPTARGET(__gettimeofday)
|
|
|
|
/* Compute relative timeout. */
|
|
movq 8(%rsp), %rax
|
|
movl $1000, %edi
|
|
mul %rdi /* Milli seconds to nano seconds. */
|
|
movq (%r13), %rdi
|
|
movq 8(%r13), %rsi
|
|
subq (%rsp), %rdi
|
|
subq %rax, %rsi
|
|
jns 5f
|
|
addq $1000000000, %rsi
|
|
decq %rdi
|
|
5: testq %rdi, %rdi
|
|
movl $ETIMEDOUT, %r14d
|
|
js 36f /* Time is already up. */
|
|
|
|
movq %rdi, (%rsp) /* Store relative timeout. */
|
|
movq %rsi, 8(%rsp)
|
|
|
|
.LcleanupSTART2:
|
|
call __pthread_enable_asynccancel
|
|
movl %eax, 16(%rsp)
|
|
|
|
movq %rsp, %r10
|
|
# if VALUE == 0
|
|
movq %r12, %rdi
|
|
# else
|
|
leaq VALUE(%r12), %rdi
|
|
# endif
|
|
# if FUTEX_WAIT == 0
|
|
movl PRIVATE(%rdi), %esi
|
|
# else
|
|
movl $FUTEX_WAIT, %esi
|
|
orl PRIVATE(%rdi), %esi
|
|
# endif
|
|
movl $SYS_futex, %eax
|
|
xorl %edx, %edx
|
|
syscall
|
|
movq %rax, %r14
|
|
|
|
movl 16(%rsp), %edi
|
|
call __pthread_disable_asynccancel
|
|
.LcleanupEND2:
|
|
|
|
testq %r14, %r14
|
|
je 9f
|
|
cmpq $-EWOULDBLOCK, %r14
|
|
jne 33f
|
|
|
|
9:
|
|
# if VALUE == 0
|
|
movl (%r12), %eax
|
|
# else
|
|
movl VALUE(%r12), %eax
|
|
# endif
|
|
8: testl %eax, %eax
|
|
je 7b
|
|
|
|
leaq -1(%rax), %rcx
|
|
LOCK
|
|
# if VALUE == 0
|
|
cmpxchgl %ecx, (%r12)
|
|
# else
|
|
cmpxchgl %ecx, VALUE(%r12)
|
|
# endif
|
|
jne 8b
|
|
|
|
xorl %eax, %eax
|
|
|
|
45: LOCK
|
|
LP_OP(sub) $1, NWAITERS(%r12)
|
|
|
|
addq $STACKFRAME, %rsp
|
|
cfi_adjust_cfa_offset(-STACKFRAME)
|
|
popq %r14
|
|
cfi_adjust_cfa_offset(-8)
|
|
cfi_restore(%r14)
|
|
popq %r13
|
|
cfi_adjust_cfa_offset(-8)
|
|
cfi_restore(%r13)
|
|
popq %r12
|
|
cfi_adjust_cfa_offset(-8)
|
|
cfi_restore(%r12)
|
|
retq
|
|
|
|
cfi_adjust_cfa_offset(STACKFRAME + 3 * 8)
|
|
cfi_rel_offset(%r12, STACKFRAME + 2 * 8)
|
|
cfi_rel_offset(%r13, STACKFRAME + 1 * 8)
|
|
cfi_rel_offset(%r14, STACKFRAME)
|
|
33: negq %r14
|
|
36:
|
|
movq errno@gottpoff(%rip), %rdx
|
|
movl %r14d, %fs:(%rdx)
|
|
|
|
orl $-1, %eax
|
|
jmp 45b
|
|
#endif
|
|
cfi_endproc
|
|
.size sem_timedwait,.-sem_timedwait
|
|
|
|
|
|
.type sem_timedwait_cleanup,@function
|
|
sem_timedwait_cleanup:
|
|
cfi_startproc
|
|
cfi_adjust_cfa_offset(8)
|
|
|
|
movq (%rsp), %rdi
|
|
LOCK
|
|
LP_OP(sub) $1, NWAITERS(%rdi)
|
|
movq %rax, %rdi
|
|
.LcallUR:
|
|
call _Unwind_Resume@PLT
|
|
hlt
|
|
.LENDCODE:
|
|
cfi_endproc
|
|
.size sem_timedwait_cleanup,.-sem_timedwait_cleanup
|
|
|
|
|
|
#ifndef __ASSUME_FUTEX_CLOCK_REALTIME
|
|
.type sem_timedwait_cleanup2,@function
|
|
sem_timedwait_cleanup2:
|
|
cfi_startproc
|
|
cfi_adjust_cfa_offset(STACKFRAME + 3 * 8)
|
|
cfi_rel_offset(%r12, STACKFRAME + 2 * 8)
|
|
cfi_rel_offset(%r13, STACKFRAME + 1 * 8)
|
|
cfi_rel_offset(%r14, STACKFRAME)
|
|
|
|
LOCK
|
|
LP_OP(sub) $1, NWAITERS(%r12)
|
|
movq %rax, %rdi
|
|
movq STACKFRAME(%rsp), %r14
|
|
movq STACKFRAME+8(%rsp), %r13
|
|
movq STACKFRAME+16(%rsp), %r12
|
|
.LcallUR2:
|
|
call _Unwind_Resume@PLT
|
|
hlt
|
|
.LENDCODE2:
|
|
cfi_endproc
|
|
.size sem_timedwait_cleanup2,.-sem_timedwait_cleanup2
|
|
#endif
|
|
|
|
|
|
.section .gcc_except_table,"a",@progbits
|
|
.LexceptSTART:
|
|
.byte DW_EH_PE_omit # @LPStart format
|
|
.byte DW_EH_PE_omit # @TType format
|
|
.byte DW_EH_PE_uleb128 # call-site format
|
|
.uleb128 .Lcstend-.Lcstbegin
|
|
.Lcstbegin:
|
|
.uleb128 .LcleanupSTART-.LSTARTCODE
|
|
.uleb128 .LcleanupEND-.LcleanupSTART
|
|
.uleb128 sem_timedwait_cleanup-.LSTARTCODE
|
|
.uleb128 0
|
|
#ifndef __ASSUME_FUTEX_CLOCK_REALTIME
|
|
.uleb128 .LcleanupSTART2-.LSTARTCODE
|
|
.uleb128 .LcleanupEND2-.LcleanupSTART2
|
|
.uleb128 sem_timedwait_cleanup2-.LSTARTCODE
|
|
.uleb128 0
|
|
#endif
|
|
.uleb128 .LcallUR-.LSTARTCODE
|
|
.uleb128 .LENDCODE-.LcallUR
|
|
.uleb128 0
|
|
.uleb128 0
|
|
#ifndef __ASSUME_FUTEX_CLOCK_REALTIME
|
|
.uleb128 .LcallUR2-.LSTARTCODE
|
|
.uleb128 .LENDCODE2-.LcallUR2
|
|
.uleb128 0
|
|
.uleb128 0
|
|
#endif
|
|
.Lcstend:
|
|
|
|
|
|
#ifdef SHARED
|
|
.hidden DW.ref.__gcc_personality_v0
|
|
.weak DW.ref.__gcc_personality_v0
|
|
.section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
|
|
.align LP_SIZE
|
|
.type DW.ref.__gcc_personality_v0, @object
|
|
.size DW.ref.__gcc_personality_v0, LP_SIZE
|
|
DW.ref.__gcc_personality_v0:
|
|
ASM_ADDR __gcc_personality_v0
|
|
#endif
|