about summary refs log tree commit diff
path: root/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2003-09-22 04:41:12 +0000
committerUlrich Drepper <drepper@redhat.com>2003-09-22 04:41:12 +0000
commit3a226d33012ec69a480ddb58940f2aaa3e24f059 (patch)
tree7f689de76474cebc1b46441eb6765f04995fad9c /nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S
parent71451de2f1245b21ce3ba407068c453a866c03d6 (diff)
downloadglibc-3a226d33012ec69a480ddb58940f2aaa3e24f059.tar.gz
glibc-3a226d33012ec69a480ddb58940f2aaa3e24f059.tar.xz
glibc-3a226d33012ec69a480ddb58940f2aaa3e24f059.zip
Update.
	* sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/lowlevellock.S: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/lowlevelmutex.S: Removed.
	* sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S: Adjust
	for new mutex implementation.
	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S: Likewise.
	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise.
	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise.
	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S: Likewise.
	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S:
	Likewise.
	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S:
	Likewise.
	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S: Likewise.
	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S: Likewise
	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S:
	Likewise.
	* sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S:
	Likewise.
	* sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S: Likewise.
	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S: Likewise.
	Don't use requeue.
	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S: Likewise.
Diffstat (limited to 'nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S')
-rw-r--r--nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S135
1 files changed, 115 insertions, 20 deletions
diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S b/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S
index aff449b13a..a56c714aeb 100644
--- a/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S
+++ b/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S
@@ -38,34 +38,129 @@
 #define VSYSCALL_ADDR_vgettimeofday	0xffffffffff600000
 
 
-	/* Modified: %rax, %rsi.  */
-	.globl	__lll_lock_wait
-	.type	__lll_lock_wait,@function
-	.hidden	__lll_lock_wait
+	.globl	__lll_mutex_lock_wait
+	.type	__lll_mutex_lock_wait,@function
+	.hidden	__lll_mutex_lock_wait
 	.align	16
-__lll_lock_wait:
+__lll_mutex_lock_wait:
 	pushq	%r10
 	pushq	%rdx
 
 	xorq	%r10, %r10	/* No timeout.  */
+	movl	$2, %edx
+	movq	%r10, %rsi	/* movq $FUTEX_WAIT, %rsi */
 
 1:
-	leaq	-1(%rsi), %rdx	/* account for the preceeded xadd.  */
-	movq	%r10, %rsi	/* movq $FUTEX_WAIT, %rsi */
+	movl	$1, %eax
+	LOCK
+	cmpxchgl %edx, (%rdi)
+
+	testl	%eax, %eax
+	je	2f
+
 	movq	$SYS_futex, %rax
 	syscall
 
-	orl	$-1, %esi	/* Load -1.  */
-	LOCK
-	xaddl	%esi, (%rdi)
-	jne	1b
+	xorl	%eax, %eax
+2:	LOCK
+	cmpxchgl %edx, (%rdi)
 
-	movl	$-1, (%rdi)
+	jnz	1b
 
 	popq	%rdx
 	popq	%r10
 	retq
-	.size	__lll_lock_wait,.-__lll_lock_wait
+	.size	__lll_mutex_lock_wait,.-__lll_mutex_lock_wait
+
+
+#ifdef NOT_IN_libc
+	.globl	__lll_mutex_timedlock_wait
+	.type	__lll_mutex_timedlock_wait,@function
+	.hidden	__lll_mutex_timedlock_wait
+	.align	16
+__lll_mutex_timedlock_wait:
+	/* Check for a valid timeout value.  */
+	cmpq	$1000000000, 8(%rdx)
+	jae	3f
+
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+
+	/* Stack frame for the timespec and timeval structs.  */
+	subq	$16, %rsp
+
+	movq	%rdi, %r12
+	movq	%rdx, %r13
+
+1:
+	/* Get current time.  */
+	movq	%rsp, %rdi
+	xorq	%rsi, %rsi
+	movq	$VSYSCALL_ADDR_vgettimeofday, %rax
+	/* This is a regular function call, all calleer-save registers
+	   might be clobbered.  */
+	callq	*%rax
+
+	/* Compute relative timeout.  */
+	movq	8(%rsp), %rax
+	movq	$1000, %rdi
+	mul	%rdi		/* Milli seconds to nano seconds.  */
+	movq	(%r13), %rdi
+	movq	8(%r13), %rsi
+	subq	(%rsp), %rdi
+	subq	%rax, %rsi
+	jns	4f
+	addq	$1000000000, %rsi
+	decq	%rdi
+4:	testq	%rdi, %rdi
+	js	5f		/* Time is already up.  */
+
+	/* Futex call.  */
+	movq	%rdi, (%rsp)	/* Store relative timeout.  */
+	movq	%rsi, 8(%rsp)
+
+	movl	$1, %eax
+	movl	$2, %edx
+	LOCK
+	cmpxchgl %edx, (%r12)
+
+	testl	%eax, %eax
+	je	8f
+
+	movq	%rsp, %r10
+	xorq	%rsi, %rsi	/* movq $FUTEX_WAIT, %rsi */
+	movq	%r12, %rdi
+	movq	$SYS_futex, %rax
+	syscall
+	movq	%rax, %rcx
+
+	movl	$1, %eax
+	LOCK
+	cmpxchgl %edx, (%rdi)
+	jnz	7f
+
+	movl	$2, (%rdi)
+	xorl	%eax, %eax
+
+8:	addq	$16, %rsp
+	popq	%r14
+	popq	%r13
+	popq	%r12
+	retq
+
+	/* Check whether the time expired.  */
+7:	cmpq	$-ETIMEDOUT, %rcx
+	je	5f
+	jmp	1b
+
+3:	movl	$EINVAL, %eax
+	retq
+
+5:	movl	$ETIMEDOUT, %eax
+	jmp	8b
+	.size	__lll_mutex_timedlock_wait,.-__lll_mutex_timedlock_wait
+#endif
 
 
 #ifdef NOT_IN_libc
@@ -88,24 +183,24 @@ lll_unlock_wake_cb:
 #endif
 
 
-	.globl	__lll_unlock_wake
-	.type	__lll_unlock_wake,@function
-	.hidden	__lll_unlock_wake
+	.globl	__lll_mutex_unlock_wake
+	.type	__lll_mutex_unlock_wake,@function
+	.hidden	__lll_mutex_unlock_wake
 	.align	16
-__lll_unlock_wake:
+__lll_mutex_unlock_wake:
 	pushq	%rsi
 	pushq	%rdx
 
-1:	movq	$FUTEX_WAKE, %rsi
+	movl	$0, (%rdi)
+	movq	$FUTEX_WAKE, %rsi
 	movl	$1, %edx	/* Wake one thread.  */
 	movq	$SYS_futex, %rax
-	movl	%edx, (%rdi)	/* Stores '$1'.  */
 	syscall
 
 	popq	%rdx
 	popq	%rsi
 	retq
-	.size	__lll_unlock_wake,.-__lll_unlock_wake
+	.size	__lll_mutex_unlock_wake,.-__lll_mutex_unlock_wake
 
 
 #ifdef NOT_IN_libc