about summary refs log tree commit diff
path: root/nptl/sysdeps/unix/sysv
diff options
context:
space:
mode:
Diffstat (limited to 'nptl/sysdeps/unix/sysv')
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S78
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S62
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sem_timedwait.c12
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sem_wait.c10
-rw-r--r--nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S75
-rw-r--r--nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S66
6 files changed, 252 insertions, 51 deletions
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S
index aa3d74593d..9afe85f205 100644
--- a/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S
@@ -37,7 +37,14 @@
 	.globl	sem_timedwait
 	.type	sem_timedwait,@function
 	.align	16
+	cfi_startproc
 sem_timedwait:
+	/* First check for cancellation.  */
+	movl	%gs:CANCELHANDLING, %eax
+	andl	$0xfffffff9, %eax
+	cmpl	$8, %eax
+	je	10f
+
 	movl	4(%esp), %ecx
 
 	movl	(%ecx), %eax
@@ -54,19 +61,28 @@ sem_timedwait:
 
 	/* Check whether the timeout value is valid.  */
 1:	pushl	%esi
+	cfi_adjust_cfa_offset(4)
 	pushl	%edi
+	cfi_adjust_cfa_offset(4)
 	pushl	%ebx
-	subl	$8, %esp
+	cfi_adjust_cfa_offset(4)
+	subl	$12, %esp
+	cfi_adjust_cfa_offset(12)
 
-	movl	%esp, %esi
-	movl	28(%esp), %edi
+	movl	32(%esp), %edi
+	cfi_offset(7, -12)		/* %edi */
 
 	/* Check for invalid nanosecond field.  */
 	cmpl	$1000000000, 4(%edi)
-	movl	$EINVAL, %eax
+	movl	$EINVAL, %esi
+	cfi_offset(6, -8)		/* %esi */
 	jae	6f
 
-7:	xorl	%ecx, %ecx
+	cfi_offset(3, -16)		/* %ebx */
+7:	call	__pthread_enable_asynccancel
+	movl	%eax, 8(%esp)
+
+	xorl	%ecx, %ecx
 	movl	%esp, %ebx
 	movl	%ecx, %edx
 	movl	$SYS_gettimeofday, %eax
@@ -84,20 +100,25 @@ sem_timedwait:
 	addl	$1000000000, %edx
 	subl	$1, %ecx
 5:	testl	%ecx, %ecx
-	movl	$ETIMEDOUT, %eax
+	movl	$ETIMEDOUT, %esi
 	js	6f		/* Time is already up.  */
 
 	movl	%ecx, (%esp)	/* Store relative timeout.  */
 	movl	%edx, 4(%esp)
-	movl	24(%esp), %ebx
+	movl	28(%esp), %ebx
 	xorl	%ecx, %ecx
+	movl	%esp, %esi
 	movl	$SYS_futex, %eax
 	xorl	%edx, %edx
 	ENTER_KERNEL
+	movl	%eax, %esi
+
+	movl	8(%esp), %eax
+	call	__pthread_disable_asynccancel
 
-	testl	%eax, %eax
+	testl	%esi, %esi
 	je,pt	9f
-	cmpl	$-EWOULDBLOCK, %eax
+	cmpl	$-EWOULDBLOCK, %esi
 	jne	3f
 
 9:	movl	(%ebx), %eax
@@ -109,14 +130,27 @@ sem_timedwait:
 	cmpxchgl %ecx, (%ebx)
 	jne,pn	8b
 
-	addl	$8, %esp
+	addl	$12, %esp
+	cfi_adjust_cfa_offset(-12)
 	xorl	%eax, %eax
 	popl	%ebx
+	cfi_adjust_cfa_offset(-4)
+	cfi_restore(3)
 	popl	%edi
+	cfi_adjust_cfa_offset(-4)
+	cfi_restore(7)
 	popl	%esi
+	cfi_adjust_cfa_offset(-4)
+	cfi_restore(6)
+	cfi_adjust_cfa_offset(-4)
+	cfi_restore(6)
 	ret
 
-3:	negl	%eax
+	cfi_adjust_cfa_offset(24)
+	cfi_offset(6, -8)		/* %esi */
+	cfi_offset(7, -12)		/* %edi */
+	cfi_offset(3, -16)		/* %ebx */
+3:	negl	%esi
 6:
 #ifdef PIC
 	call	__i686.get_pc_thunk.bx
@@ -128,17 +162,31 @@ sem_timedwait:
 #if USE___THREAD
 	movl	%gs:0, %edx
 	subl	errno@gottpoff(%ebx), %edx
-	movl	%eax, (%edx)
+	movl	%esi, (%edx)
 #else
-	movl	%eax, %edx
 	call	__errno_location@plt
-	movl	%edx, (%eax)
+	movl	%esi, (%eax)
 #endif
 
-	addl	$8, %esp
+	addl	$12, %esp
+	cfi_adjust_cfa_offset(-12)
 	orl	$-1, %eax
 	popl	%ebx
+	cfi_adjust_cfa_offset(-4)
+	cfi_restore(3)
 	popl	%edi
+	cfi_adjust_cfa_offset(-4)
+	cfi_restore(7)
 	popl	%esi
+	cfi_adjust_cfa_offset(-4)
+	cfi_restore(6)
 	ret
+
+10:	/* Canceled.  */
+	movl	$0xffffffff, %gs:RESULT
+	LOCK
+	orl	$0x10, %gs:CANCELHANDLING
+	movl	%gs:CLEANUP_JMP_BUF, %eax
+	jmp	__pthread_unwind
+	cfi_endproc
 	.size	sem_timedwait,.-sem_timedwait
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S
index eb01ca84f7..ba4f54cd64 100644
--- a/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S
@@ -36,12 +36,25 @@
 	.globl	__new_sem_wait
 	.type	__new_sem_wait,@function
 	.align	16
+	cfi_startproc
 __new_sem_wait:
+	/* First check for cancellation.  */
+	movl	%gs:CANCELHANDLING, %eax
+	andl	$0xfffffff9, %eax
+	cmpl	$8, %eax
+	je	5f
+
 	pushl	%ebx
+	cfi_adjust_cfa_offset(4)
 	pushl	%esi
+	cfi_adjust_cfa_offset(4)
+	subl	$4, %esp
+	cfi_adjust_cfa_offset(4)
 
-	movl	12(%esp), %ebx
+	movl	16(%esp), %ebx
+	cfi_offset(3, -8)		/* %ebx */
 
+	cfi_offset(6, -12)		/* %esi */
 3:	movl	(%ebx), %eax
 2:	testl	%eax, %eax
 	je,pn	1f
@@ -52,21 +65,35 @@ __new_sem_wait:
 	jne,pn	2b
 	xorl	%eax, %eax
 
-	popl	%esi
-	popl	%ebx
+	movl	4(%esp), %esi
+	cfi_restore(6)
+	movl	8(%esp), %ebx
+	cfi_restore(3)
+	addl	$12, %esp
+	cfi_adjust_cfa_offset(-12)
 	ret
 
-1:	xorl	%esi, %esi
+	cfi_adjust_cfa_offset(8)
+	cfi_offset(3, -8)		/* %ebx */
+	cfi_offset(6, -12)		/* %esi */
+1:	call	__pthread_enable_asynccancel
+	movl	%eax, (%esp)
+
+	xorl	%esi, %esi
 	movl	$SYS_futex, %eax
 	movl	%esi, %ecx
 	movl	%esi, %edx
 	ENTER_KERNEL
+	movl	%eax, %esi
+
+	movl	(%esp), %eax
+	call	__pthread_disable_asynccancel
 
-	testl	%eax, %eax
+	testl	%esi, %esi
 	je	3b
-	cmpl	$-EWOULDBLOCK, %eax
+	cmpl	$-EWOULDBLOCK, %esi
 	je	3b
-	negl	%eax
+	negl	%esi
 #ifdef PIC
 	call	__i686.get_pc_thunk.bx
 #else
@@ -77,16 +104,27 @@ __new_sem_wait:
 #if USE___THREAD
 	movl	%gs:0, %edx
 	subl	errno@gottpoff(%ebx), %edx
-	movl	%eax, (%edx)
+	movl	%esi, (%edx)
 #else
-	movl	%eax, %edx
 	call	__errno_location@plt
-	movl	%edx, (%eax)
+	movl	%esi, (%eax)
 #endif
 	orl	$-1, %eax
-	popl	%esi
-	popl	%ebx
+	movl	4(%esp), %esi
+	cfi_restore(6)
+	movl	8(%esp), %ebx
+	cfi_restore(3)
+	addl	$12, %esp
+	cfi_adjust_cfa_offset(-12)
 	ret
+
+5:	/* Canceled.  */
+	movl	$0xffffffff, %gs:RESULT
+	LOCK
+	orl	$0x10, %gs:CANCELHANDLING
+	movl	%gs:CLEANUP_JMP_BUF, %eax
+	jmp	__pthread_unwind
+	cfi_endproc
 	.size	__new_sem_wait,.-__new_sem_wait
 	versioned_symbol(libpthread, __new_sem_wait, sem_wait, GLIBC_2_1)
 #if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
diff --git a/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c b/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c
index 8a65ce2567..ef897c1e93 100644
--- a/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c
+++ b/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c
@@ -24,12 +24,16 @@
 #include <internaltypes.h>
 #include <semaphore.h>
 
+#include <pthreadP.h>
 #include <shlib-compat.h>
 
 
 int
 sem_timedwait (sem_t *sem, const struct timespec *abstime)
 {
+  /* First check for cancellation.  */
+  CANCELLATION_P (THREAD_SELF);
+
   int *futex = (int *) sem;
   int val;
   int err;
@@ -71,7 +75,15 @@ sem_timedwait (sem_t *sem, const struct timespec *abstime)
       /* Do wait.  */
       rt.tv_sec = sec;
       rt.tv_nsec = nsec;
+
+      /* Enable asynchronous cancellation.  Required by the standard.  */
+      int oldtype = __pthread_enable_asynccancel ();
+
       err = lll_futex_timed_wait (futex, 0, &rt);
+
+      /* Disable asynchronous cancellation.  */
+      __pthread_disable_asynccancel (oldtype);
+
       if (err != 0 && err != -EWOULDBLOCK)
 	goto error_return;
 
diff --git a/nptl/sysdeps/unix/sysv/linux/sem_wait.c b/nptl/sysdeps/unix/sysv/linux/sem_wait.c
index 1d39b7c408..36bb158e09 100644
--- a/nptl/sysdeps/unix/sysv/linux/sem_wait.c
+++ b/nptl/sysdeps/unix/sysv/linux/sem_wait.c
@@ -24,12 +24,16 @@
 #include <internaltypes.h>
 #include <semaphore.h>
 
+#include <pthreadP.h>
 #include <shlib-compat.h>
 
 
 int
 __new_sem_wait (sem_t *sem)
 {
+  /* First check for cancellation.  */
+  CANCELLATION_P (THREAD_SELF);
+
   int *futex = (int *) sem;
   int val;
   int err;
@@ -43,7 +47,13 @@ __new_sem_wait (sem_t *sem)
 	    return 0;
 	}
 
+      /* Enable asynchronous cancellation.  Required by the standard.  */
+      int oldtype = __pthread_enable_asynccancel ();
+
       err = lll_futex_wait (futex, 0);
+
+      /* Disable asynchronous cancellation.  */
+      __pthread_disable_asynccancel (oldtype);
     }
   while (err == 0 || err == -EWOULDBLOCK);
 
diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S b/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S
index 29bc1bcf46..7626d7b250 100644
--- a/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S
+++ b/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S
@@ -38,7 +38,14 @@
 	.globl	sem_timedwait
 	.type	sem_timedwait,@function
 	.align	16
+	cfi_startproc
 sem_timedwait:
+	/* First check for cancellation.  */
+	movl	%fs:CANCELHANDLING, %eax
+	andl	$0xfffffff9, %eax
+	cmpl	$8, %eax
+	je	11f
+
 	movl	(%rdi), %eax
 2:	testl	%eax, %eax
 	je	1f
@@ -53,18 +60,29 @@ sem_timedwait:
 
 	/* Check whether the timeout value is valid.  */
 1:	pushq	%r12
+	cfi_adjust_cfa_offset(8)
 	pushq	%r13
-	subq	$16, %rsp
+	cfi_adjust_cfa_offset(8)
+	pushq	%r14
+	cfi_adjust_cfa_offset(8)
+	subq	$24, %rsp
+	cfi_adjust_cfa_offset(24)
 
 	movq	%rdi, %r12
+	cfi_offset(12, -16)		/* %r12 */
 	movq	%rsi, %r13
+	cfi_offset(13, -24)		/* %r13 */
 
 	/* Check for invalid nanosecond field.  */
 	cmpq	$1000000000, 8(%r13)
-	movl	$EINVAL, %eax
+	movl	$EINVAL, %r14d
+	cfi_offset(14, -24)		/* %r14 */
 	jae	6f
 
-7:	xorq	%rsi, %rsi
+7:	call	__pthread_enable_asynccancel
+	movl	%eax, 16(%rsp)
+
+	xorq	%rsi, %rsi
 	movq	%rsp, %rdi
 	movq	$VSYSCALL_ADDR_vgettimeofday, %rax
 	callq	*%rax
@@ -74,14 +92,14 @@ sem_timedwait:
 	movq	$1000, %rdi
 	mul	%rdi		/* Milli seconds to nano seconds.  */
 	movq	(%r13), %rdi
-	movq	8(%r13), %rdi
+	movq	8(%r13), %rsi
 	subq	(%rsp), %rdi
-	subq	%rax, %rdi
+	subq	%rax, %rsi
 	jns	5f
 	addq	$1000000000, %rsi
 	decq	%rdi
 5:	testq	%rdi, %rdi
-	movl	$ETIMEDOUT, %eax
+	movl	$ETIMEDOUT, %r14d
 	js	6f		/* Time is already up.  */
 
 	movq	%rdi, (%rsp)	/* Store relative timeout.  */
@@ -93,38 +111,65 @@ sem_timedwait:
 	movq	$SYS_futex, %rax
 	xorl	%edx, %edx
 	syscall
+	movq	%rax, %r14
 
-	testq	%rax, %rax
+	movl	16(%rsp), %edi
+	call	__pthread_disable_asynccancel
+
+	testq	%r14, %r14
 	je	9f
-	cmpq	$-EWOULDBLOCK, %rax
+	cmpq	$-EWOULDBLOCK, %r14
 	jne	3f
 
-9:	movl	(%rdi), %eax
+9:	movl	(%r12), %eax
 8:	testl	%eax, %eax
 	je	7b
 
 	leaq	-1(%rax), %rcx
 	LOCK
-	cmpxchgl %ecx, (%rdi)
+	cmpxchgl %ecx, (%r12)
 	jne	8b
 
 	xorl	%eax, %eax
-10:	addq	$16, %rsp
+10:	addq	$24, %rsp
+	cfi_adjust_cfa_offset(-24)
+	popq	%r14
+	cfi_adjust_cfa_offset(-8)
+	cfi_restore(14)
 	popq	%r13
+	cfi_adjust_cfa_offset(-8)
+	cfi_restore(13)
 	popq	%r12
+	cfi_adjust_cfa_offset(-8)
+	cfi_restore(12)
 	retq
 
-3:	negq	%rax
+	cfi_adjust_cfa_offset(48)
+	cfi_offset(12, -16)		/* %r12 */
+	cfi_offset(13, -24)		/* %r13 */
+	cfi_offset(14, -32)		/* %r14 */
+3:	negq	%r14
 6:
 #if USE___THREAD
 	movq	errno@gottpoff(%rip), %rdx
-	movl	%eax, %fs:(%rdx)
+	movl	%r14d, %fs:(%rdx)
 #else
-	movl	%eax, %edx
 	callq	__errno_location@plt
-	movl	%edx, (%rax)
+	movl	%r14d, (%rax)
 #endif
 
 	orl	$-1, %eax
 	jmp	10b
+	cfi_adjust_cfa_offset(-48)
+	cfi_restore(14)
+	cfi_restore(13)
+	cfi_restore(12)
+
+11:	/* Canceled.  */
+	movq	$0xffffffffffffffff, %fs:RESULT
+	LOCK
+	orl	$0x10, %fs:CANCELHANDLING
+	movq	%fs:CLEANUP_JMP_BUF, %rdi
+	jmp	__pthread_unwind
+	cfi_endproc
 	.size	sem_timedwait,.-sem_timedwait
diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S b/nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S
index 877ee4c4dc..32742309fb 100644
--- a/nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S
+++ b/nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S
@@ -35,38 +35,86 @@
 	.globl	sem_wait
 	.type	sem_wait,@function
 	.align	16
+	cfi_startproc
 sem_wait:
-3:	movl	(%rdi), %eax
+	/* First check for cancellation.  */
+	movl	%fs:CANCELHANDLING, %eax
+	andl	$0xfffffff9, %eax
+	cmpl	$8, %eax
+	je	4f
+
+	pushq	%r12
+	cfi_adjust_cfa_offset(8)
+	cfi_offset(12, -16)
+	pushq	%r13
+	cfi_adjust_cfa_offset(8)
+	movq	%rdi, %r13
+	cfi_offset(13, -24)
+
+3:	movl	(%r13), %eax
 2:	testl	%eax, %eax
 	je	1f
 
 	leaq	-1(%rax), %rdx
 	LOCK
-	cmpxchgl %edx, (%rdi)
+	cmpxchgl %edx, (%r13)
 	jne	2b
 	xorl	%eax, %eax
 
+	popq	%r13
+	cfi_adjust_cfa_offset(-8)
+	cfi_restore(13)
+	popq	%r12
+	cfi_adjust_cfa_offset(-8)
+	cfi_restore(12)
+
 	retq
 
-1:	xorq	%r10, %r10
+	cfi_adjust_cfa_offset(16)
+	cfi_offset(12, -16)
+	cfi_offset(13, -24)
+1:	call	__pthread_enable_asynccancel
+	movl	%eax, %r8d
+
+	xorq	%r10, %r10
 	movq	$SYS_futex, %rax
+	movq	%r13, %rdi
 	movq	%r10, %rsi
 	movq	%r10, %rdx
 	syscall
+	movq	%rax, %r12
+
+	movl	%r8d, %edi
+	call	__pthread_disable_asynccancel
 
-	testq	%rax, %rax
+	testq	%r12, %r12
 	je	3b
-	cmpq	$-EWOULDBLOCK, %rax
+	cmpq	$-EWOULDBLOCK, %r12
 	je	3b
-	negq	%rax
+	negq	%r12
 #if USE___THREAD
 	movq	errno@gottpoff(%rip), %rdx
-	movl	%eax, %fs:(%rdx)
+	movl	%r12d, %fs:(%rdx)
 #else
-	movl	%eax, %edx
 	callq	__errno_location@plt
-	movl	%edx, (%rax)
+	movl	%r12d, (%rax)
 #endif
 	orl	$-1, %eax
+
+	popq	%r13
+	cfi_adjust_cfa_offset(-8)
+	cfi_restore(13)
+	popq	%r12
+	cfi_adjust_cfa_offset(-8)
+	cfi_restore(12)
+
 	retq
+
+4:	/* Canceled.  */
+	movq	$0xffffffffffffffff, %fs:RESULT
+	LOCK
+	orl	$0x10, %fs:CANCELHANDLING
+	movq	%fs:CLEANUP_JMP_BUF, %rdi
+	jmp	__pthread_unwind
+	cfi_endproc
 	.size	sem_wait,.-sem_wait