mirror of
				https://sourceware.org/git/glibc.git
				synced 2025-11-03 20:53:13 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			381 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			381 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
/* Copyright (C) 2002,2003,2005,2007,2009,2010,2011 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
 |