about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--nptl/ChangeLog13
-rw-r--r--nptl/pthreadP.h2
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S216
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S232
-rw-r--r--nptl/tst-cancel17.c147
-rw-r--r--nptl/tst-cond8.c2
-rw-r--r--sysdeps/pthread/aio_misc.h23
-rw-r--r--sysdeps/pthread/aio_suspend.c8
9 files changed, 475 insertions, 177 deletions
diff --git a/ChangeLog b/ChangeLog
index 69dce621b7..571330c35d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,7 +1,12 @@
 2003-06-23  Ulrich Drepper  <drepper@redhat.com>
 
-	* sysdeps/pthread/aio_suspend.c (aio_suspend): Set errno to EINTR
-	if this is what pthread_cond_wait returned.
+	* sysdeps/pthread/aio_misc.h: Mark __aio_requests_mutex,
+	__aio_enqueue_request, __aio_find_req, __aio_find_req_fd,
+	__aio_free_request, __aio_notify, and __aio_sigqueue as hidden.
+
+	* sysdeps/pthread/aio_suspend.c (aio_suspend): Set errno to the result
+	of pthread_cond_wait if there was an error.  Use pthread_cleanup_*
+	instead of __lbic_cleanup_region_*.
 
 2003-06-20  Richard Henderson  <rth@redhat.com>
 
diff --git a/nptl/ChangeLog b/nptl/ChangeLog
index 9a8f0a3800..c53fc8adf6 100644
--- a/nptl/ChangeLog
+++ b/nptl/ChangeLog
@@ -1,3 +1,16 @@
+2003-06-23  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Rewrite
+	to use exception-based cleanup handler.
+	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise.
+
+	* tst-cond8.c (ch): Announce that we are done.
+
+	* pthreadP.h (__pthread_mutex_cond_lock): Mark with internal_function.
+
+	* tst-cancel17.c (tf): Retry aio_suspend in case of EINTR.
+	Also test aio_suspend with timeout value.
+
 2003-06-22  Ulrich Drepper  <drepper@redhat.com>
 
 	* pthreadP.h: Mark __pthread_mutex_unlock_usercnt also hidden.
diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h
index 64d0657659..b67e0ddb65 100644
--- a/nptl/pthreadP.h
+++ b/nptl/pthreadP.h
@@ -254,7 +254,7 @@ extern int __pthread_mutex_lock (pthread_mutex_t *__mutex);
 extern int __pthread_mutex_lock_internal (pthread_mutex_t *__mutex)
      attribute_hidden;
 extern int __pthread_mutex_cond_lock (pthread_mutex_t *__mutex)
-     attribute_hidden;
+     attribute_hidden internal_function;
 extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex);
 extern int __pthread_mutex_unlock_internal (pthread_mutex_t *__mutex)
      attribute_hidden;
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S
index 2f598980e5..d7ce84ebe4 100644
--- a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S
@@ -81,32 +81,14 @@ __pthread_cond_timedwait:
 	addl	$1, total_seq(%ebx)
 	adcl	$0, total_seq+4(%ebx)
 
-	/* Install cancellation handler.  */
-#ifdef PIC
-	call	__i686.get_pc_thunk.cx
-	addl	$_GLOBAL_OFFSET_TABLE_, %ecx
-	leal	__condvar_cleanup@GOTOFF(%ecx), %eax
-#else
-	leal	__condvar_cleanup, %eax
-#endif
-	subl	$44, %esp
+	subl	$20, %esp
 .Lsubl:
-	leal	28(%esp), %edx
-	movl	%esp, 8(%esp)
-	movl	%eax, 4(%esp)
-	movl	%edx, (%esp)
-	call	__pthread_cleanup_push
-
-	/* Address of the mutex.  */
-	movl	68(%esp), %ecx
+
 	/* Get and store current wakeup_seq value.  */
 	movl	wakeup_seq(%ebx), %edi
 	movl	wakeup_seq+4(%ebx), %edx
-	movl	%edi, 20(%esp)
-	movl	%edx, 24(%esp)
-	/* Prepare structure passed to cancellation handler.  */
-	movl	%ecx, (%esp)
-	movl	%ebx, 4(%esp)
+	movl	%edi, 12(%esp)
+	movl	%edx, 16(%esp)
 
 	/* Unlock.  */
 8:	LOCK
@@ -117,18 +99,20 @@ __pthread_cond_timedwait:
 #endif
 	jne	3f
 
+.LcleanupSTART:
 4:	call	__pthread_enable_asynccancel
-	movl	%eax, 8(%esp)
+	movl	%eax, (%esp)
 
 	/* Get the current time.  */
 	movl	%ebx, %edx
+.LebxmovedUR:
 #ifdef __NR_clock_gettime
 	/* Get the clock number.  Note that the field in the condvar
 	   structure stores the number minus 1.  */
 	movl	cond_clock(%ebx), %ebx
 	/* Only clocks 0 and 1 are allowed.  Both are handled in the
 	   kernel.  */
-	leal	12(%esp), %ecx
+	leal	4(%esp), %ecx
 	movl	$__NR_clock_gettime, %eax
 	ENTER_KERNEL
 # ifndef __ASSUME_POSIX_TIMERS
@@ -136,27 +120,29 @@ __pthread_cond_timedwait:
 	je	19f
 # endif
 	movl	%edx, %ebx
+.LebxbackUR:
 
 	/* Compute relative timeout.  */
 	movl	(%ebp), %ecx
 	movl	4(%ebp), %edx
-	subl	12(%esp), %ecx
-	subl	16(%esp), %edx
+	subl	4(%esp), %ecx
+	subl	8(%esp), %edx
 #else
 	/* Get the current time.  */
-	leal	12(%esp), %ebx
+	leal	4(%esp), %ebx
 	xorl	%ecx, %ecx
 	movl	$SYS_gettimeofday, %eax
 	ENTER_KERNEL
 	movl	%edx, %ebx
+.LebxbackUR:
 
 	/* Compute relative timeout.  */
-	movl	16(%esp), %eax
+	movl	8(%esp), %eax
 	movl	$1000, %edx
 	mul	%edx		/* Milli seconds to nano seconds.  */
 	movl	(%ebp), %ecx
 	movl	4(%ebp), %edx
-	subl	12(%esp), %ecx
+	subl	4(%esp), %ecx
 	subl	%eax, %edx
 #endif
 	jns	12f
@@ -166,19 +152,22 @@ __pthread_cond_timedwait:
 	js	13f
 
 	/* Store relative timeout.  */
-21:	movl	%ecx, 12(%esp)
-	movl	%edx, 16(%esp)
-	leal	12(%esp), %esi
+21:	movl	%ecx, 4(%esp)
+	movl	%edx, 8(%esp)
+	leal	4(%esp), %esi
 	xorl	%ecx, %ecx	/* movl $FUTEX_WAIT, %ecx */
 	movl	%edi, %edx
 	addl	$wakeup_seq, %ebx
+.Ladd_wakeup:
 	movl	$SYS_futex, %eax
 	ENTER_KERNEL
 	subl	$wakeup_seq, %ebx
+.Lsub_wakeup:
 	movl	%eax, %esi
 
-	movl	8(%esp), %eax
+	movl	(%esp), %eax
 	call	__pthread_disable_asynccancel
+.LcleanupEND:
 
 	/* Lock.  */
 	movl	$1, %eax
@@ -197,10 +186,10 @@ __pthread_cond_timedwait:
 	movl	wakeup_seq(%ebx), %edi
 	movl	wakeup_seq+4(%ebx), %edx
 
-	cmpl	24(%esp), %edx
+	cmpl	16(%esp), %edx
 	ja	7f
 	jb	15f
-	cmpl	20(%esp), %edi
+	cmpl	12(%esp), %edi
 	jbe	15f
 
 7:	cmpl	%ecx, %edx
@@ -230,12 +219,9 @@ __pthread_cond_timedwait:
 	jne	10f
 
 	/* Remove cancellation handler.  */
-11:	movl	28+CLEANUP_PREV(%esp), %edx
-	movl	%edx, %gs:CLEANUP
-
-	/* Trick ahead:	 (%esp) contains the address of the mutex.  */
+11:	movl	44(%esp), %eax
 	call	__pthread_mutex_cond_lock
-	addl	$44, %esp
+	addl	$20, %esp
 .Laddl:
 
 	/* We return the result of the mutex_lock operation if it failed.  */
@@ -320,19 +306,19 @@ __pthread_cond_timedwait:
 #if defined __NR_clock_gettime && !defined __ASSUME_POSIX_TIMERS
 	/* clock_gettime not available.  */
 .LSbl4:
-19:	leal	12(%esp), %ebx
+19:	leal	4(%esp), %ebx
 	xorl	%ecx, %ecx
 	movl	$SYS_gettimeofday, %eax
 	ENTER_KERNEL
 	movl	%edx, %ebx
 
 	/* Compute relative timeout.  */
-	movl	16(%esp), %eax
+	movl	8(%esp), %eax
 	movl	$1000, %edx
 	mul	%edx		/* Milli seconds to nano seconds.  */
 	movl	(%ebp), %ecx
 	movl	4(%ebp), %edx
-	subl	12(%esp), %ecx
+	subl	4(%esp), %ecx
 	subl	%eax, %edx
 	jns	20f
 	addl	$1000000000, %edx
@@ -341,12 +327,112 @@ __pthread_cond_timedwait:
 	js	13b
 	jmp	21b
 #endif
-.LENDCODE:
 	.size	__pthread_cond_timedwait, .-__pthread_cond_timedwait
 versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
 		  GLIBC_2_3_2)
 
 
+	.type	__condvar_cleanup3, @function
+__condvar_cleanup3:
+	leal	wakeup_seq(%edx), %ebx # XXX Is this correct?  %edx preserved?
+.LSbl5:
+	.size	__condvar_cleanup3, .-__condvar_cleanup3
+	.type	__condvar_cleanup2, @function
+__condvar_cleanup2:
+	subl	$wakeup_seq, %ebx
+	.size	__condvar_cleanup2, .-__condvar_cleanup2
+	.type	__condvar_cleanup, @function
+__condvar_cleanup:
+	movl	%eax, %esi
+
+	/* Get internal lock.  */
+	movl	$1, %eax
+	LOCK
+#if cond_lock == 0
+	xaddl	%eax, (%ebx)
+#else
+	xaddl	%eax, cond_lock(%ebx)
+#endif
+	testl	%eax, %eax
+	je	1f
+
+#if cond_lock == 0
+	movl	%ebx, %ecx
+#else
+	leal	cond_lock(%ebx), %ecx
+#endif
+	call	__lll_mutex_lock_wait
+
+1:	addl	$1, wakeup_seq(%ebx)
+	adcl	$0, wakeup_seq+4(%ebx)
+
+	addl	$1, woken_seq(%ebx)
+	adcl	$0, woken_seq+4(%ebx)
+
+	LOCK
+	subl	$1, cond_lock(%ebx)
+	je	2f
+
+#if cond_lock == 0
+	movl	%ebx, %eax
+#else
+	leal	cond_lock(%ebx), %eax
+#endif
+	call	__lll_mutex_unlock_wake
+
+	/* Wake up all waiters to make sure no signal gets lost.  */
+2:	addl	$wakeup_seq, %ebx
+	movl	$FUTEX_WAKE, %ecx
+	movl	$SYS_futex, %eax
+	movl	$0x7fffffff, %edx
+	ENTER_KERNEL
+
+	movl	44(%esp), %eax
+	call	__pthread_mutex_cond_lock
+
+	movl	%esi, (%esp)
+.LcallUR:
+	call	_Unwind_Resume
+	hlt
+.LENDCODE:
+	.size	__condvar_cleanup, .-__condvar_cleanup
+
+
+	.section .gcc_except_table,"a",@progbits
+.LexceptSTART:
+	.byte	0xff				# @LPStart format (omit)
+	.byte	0xff				# @TType format (omit)
+	.byte	0x0b				# call-site format
+						# DW_EH_PE_sdata4
+	.uleb128 .Lcstend-.Lcstbegin
+.Lcstbegin:
+	.long	.LcleanupSTART-.LSTARTCODE
+	.long	.Ladd_wakeup-.LcleanupSTART
+	.long	__condvar_cleanup-.LSTARTCODE
+	.uleb128  0
+	.long	.LebxmovedUR-.LSTARTCODE
+	.long	.LebxbackUR-.LebxmovedUR
+	.long	__condvar_cleanup3-.LSTARTCODE
+	.uleb128  0
+	.long	.LebxmovedUR-.LSTARTCODE
+	.long	.Ladd_wakeup-.LebxmovedUR
+	.long	__condvar_cleanup-.LSTARTCODE
+	.uleb128  0
+	.long	.Ladd_wakeup-.LSTARTCODE
+	.long	.Lsub_wakeup-.Ladd_wakeup
+	.long	__condvar_cleanup2-.LSTARTCODE
+	.uleb128  0
+	.long	.Lsub_wakeup-.LSTARTCODE
+	.long	.LcleanupEND-.Lsub_wakeup
+	.long	__condvar_cleanup-.LSTARTCODE
+	.uleb128  0
+	.long	.LcallUR-.LSTARTCODE
+	.long	.LENDCODE-.LcallUR
+	.long	0
+	.uleb128  0
+.Lcstend:
+
+
 	.section .eh_frame,"a",@progbits
 .LSTARTFRAME:
 	.long	L(ENDCIE)-L(STARTCIE)		# Length of the CIE.
@@ -354,10 +440,10 @@ versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
 	.long	0				# CIE ID.
 	.byte	1				# Version number.
 #ifdef SHARED
-	.string	"zR"				# NUL-terminated augmentation
+	.string	"zPLR"				# NUL-terminated augmentation
 						# string.
 #else
-	.ascii	"\0"				# NUL-terminated augmentation
+	.string	"zPL"				# NUL-terminated augmentation
 						# string.
 #endif
 	.uleb128 1				# Code alignment factor.
@@ -365,9 +451,20 @@ versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
 	.byte	8				# Return address register
 						# column.
 #ifdef SHARED
-	.uleb128 1				# Augmentation value length.
-	.byte	0x1b				# Encoding: DW_EH_PE_pcrel
+	.uleb128 7				# Augmentation value length.
+	.byte	0x9b				# Personality: DW_EH_PE_pcrel
+						# + DW_EH_PE_sdata4
+						# + DW_EH_PE_indirect
+	.long	DW.ref.__gcc_personality_v0-.
+	.byte	0x1b				# LSDA Encoding: DW_EH_PE_pcrel
+						# + DW_EH_PE_sdata4.
+	.byte	0x1b				# FDE Encoding: DW_EH_PE_pcrel
 						# + DW_EH_PE_sdata4.
+#else
+	.uleb128 6				# Augmentation value length.
+	.byte	0x0				# Personality: absolute
+	.long	__gcc_personality_v0
+	.byte	0x0				# LSDA Encoding: absolute
 #endif
 	.byte 0x0c				# DW_CFA_def_cfa
 	.uleb128 4
@@ -387,8 +484,11 @@ versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
 	.long	.LSTARTCODE			# Start address of the code.
 #endif
 	.long	.LENDCODE-.LSTARTCODE		# Length of the code.
+	.uleb128 4				# Augmentation size
 #ifdef SHARED
-	.uleb128 0				# No augmentation data.
+	.long	.LexceptSTART-.
+#else
+	.long	.LexceptSTART
 #endif
 	.byte	0x40+.Lpush_ebp-.LSTARTCODE	# DW_CFA_advance_loc+N
 	.byte	14				# DW_CFA_def_cfa_offset
@@ -413,7 +513,7 @@ versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
 	.byte	2				# DW_CFA_advance_loc1
 	.byte	.Lsubl-.Lpush_ebx
 	.byte	14				# DW_CFA_def_cfa_offset
-	.uleb128 64
+	.uleb128 40
 	.byte	3				# DW_CFA_advance_loc2
 	.2byte	.Laddl-.Lsubl
 	.byte	14				# DW_CFA_def_cfa_offset
@@ -455,6 +555,22 @@ versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
 	.byte	0x40+.LSbl4-.LSbl3		# DW_CFA_advance_loc+N
 	.byte	14				# DW_CFA_def_cfa_offset
 	.uleb128 64
+	.byte	0x40+.LSbl5-.LSbl4		# DW_CFA_advance_loc+N
+#else
+	.byte	0x40+.LSbl5-.LSbl3		# DW_CFA_advance_loc+N
 #endif
+	.byte	14				# DW_CFA_def_cfa_offset
+	.uleb128 40
 	.align	4
 .LENDFDE:
+
+#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 4
+	.type   DW.ref.__gcc_personality_v0, @object
+	.size   DW.ref.__gcc_personality_v0, 4
+DW.ref.__gcc_personality_v0:
+	.long   __gcc_personality_v0
+#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S
index c98899ab05..6cf30cf41b 100644
--- a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S
@@ -35,64 +35,6 @@
 
 	.text
 
-	.align	16
-	.type	__condvar_cleanup, @function
-	.globl	__condvar_cleanup
-	.hidden	__condvar_cleanup
-__condvar_cleanup:
-	pushl	%ebx
-	pushl	%esi
-	movl	12(%esp), %esi
-
-	/* Get internal lock.  */
-	movl	4(%esi), %ebx
-	movl	$1, %eax
-	LOCK
-#if cond_lock == 0
-	xaddl	%eax, (%ebx)
-#else
-	xaddl	%eax, cond_lock(%ebx)
-#endif
-	testl	%eax, %eax
-	je	1f
-
-#if cond_lock == 0
-	movl	%ebx, %ecx
-#else
-	leal	cond_lock(%ebx), %ecx
-#endif
-	call	__lll_mutex_lock_wait
-
-1:	addl	$wakeup_seq, %ebx
-	addl	$1, (%ebx)
-	adcl	$0, 4(%ebx)
-
-	addl	$1, woken_seq-wakeup_seq(%ebx)
-	adcl	$0, woken_seq-wakeup_seq+4(%ebx)
-
-	LOCK
-	subl	$1, cond_lock-wakeup_seq(%ebx)
-	je	2f
-
-	leal	cond_lock-wakeup_seq(%ebx), %eax
-	call	__lll_mutex_unlock_wake
-
-	/* Wake up all waiters to make sure no signal gets lost.  */
-2:	movl	$FUTEX_WAKE, %ecx
-	movl	$SYS_futex, %eax
-	movl	$0x7fffffff, %edx
-	ENTER_KERNEL
-
-	pushl	(%esi)
-	call	__pthread_mutex_cond_lock
-	popl	%eax
-
-	popl	%esi
-	popl	%ebx
-	ret
-	.size	__condvar_cleanup, .-__condvar_cleanup
-
-
 /* int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)  */
 	.globl	__pthread_cond_wait
 	.type	__pthread_cond_wait, @function
@@ -136,31 +78,14 @@ __pthread_cond_wait:
 	addl	$1, total_seq(%ebx)
 	adcl	$0, total_seq+4(%ebx)
 
-	/* Install cancellation handler.  */
-#ifdef PIC
-	call	__i686.get_pc_thunk.cx
-	addl	$_GLOBAL_OFFSET_TABLE_, %ecx
-	leal	__condvar_cleanup@GOTOFF(%ecx), %eax
-#else
-	leal	__condvar_cleanup, %eax
-#endif
-	subl	$36, %esp
+	subl	$12, %esp
 .Lsubl:
-	leal	20(%esp), %edx
-	movl	%esp, 8(%esp)
-	movl	%eax, 4(%esp)
-	movl	%edx, (%esp)
-	call	__pthread_cleanup_push
 
 	/* Get and store current wakeup_seq value.  */
-	movl	56(%esp), %ecx
 	movl	wakeup_seq(%ebx), %edi
 	movl	wakeup_seq+4(%ebx), %edx
-	movl	%edi, 12(%esp)
-	movl	%edx, 16(%esp)
-	/* Prepare structure passed to cancellation handler.  */
-	movl	%ecx, (%esp)
-	movl	%ebx, 4(%esp)
+	movl	%edi, 4(%esp)
+	movl	%edx, 8(%esp)
 
 	/* Unlock.  */
 8:	LOCK
@@ -171,18 +96,22 @@ __pthread_cond_wait:
 #endif
 	jne	3f
 
+.LcleanupSTART:
 4:	call	__pthread_enable_asynccancel
-	movl	%eax, 8(%esp)
+	movl	%eax, (%esp)
 
 	movl	%esi, %ecx	/* movl $FUTEX_WAIT, %ecx */
 	movl	%edi, %edx
 	addl	$wakeup_seq, %ebx
+.Ladd_wakeup:
 	movl	$SYS_futex, %eax
 	ENTER_KERNEL
 	subl	$wakeup_seq, %ebx
+.Lsub_wakeup:
 
-	movl	8(%esp), %eax
+	movl	(%esp), %eax
 	call	__pthread_disable_asynccancel
+.LcleanupEND:
 
 	/* Lock.  */
 	movl	$1, %eax
@@ -201,10 +130,10 @@ __pthread_cond_wait:
 	movl	wakeup_seq(%ebx), %edi
 	movl	wakeup_seq+4(%ebx), %edx
 
-	cmpl	16(%esp), %edx
+	cmpl	8(%esp), %edx
 	ja	7f
 	jb	8b
-	cmpl	12(%esp), %edi
+	cmpl	4(%esp), %edi
 	jbe	8b
 
 7:	cmpl	%ecx, %edx
@@ -224,13 +153,9 @@ __pthread_cond_wait:
 #endif
 	jne	10f
 
-	/* Remove cancellation handler.  */
-11:	movl	20+CLEANUP_PREV(%esp), %edx
-	movl	%edx, %gs:CLEANUP
-
-	/* Trick ahead:	 (%esp) contains the address of the mutex.  */
+11:	movl	32(%esp), %eax
 	call	__pthread_mutex_cond_lock
-	addl	$36, %esp
+	addl	$12, %esp
 .Laddl:
 
 14:	popl	%ebx
@@ -306,23 +231,110 @@ __pthread_cond_wait:
 
 	movl	%esi, %eax
 	jmp	14b
-.LENDCODE:
 	.size	__pthread_cond_wait, .-__pthread_cond_wait
 versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
 		  GLIBC_2_3_2)
 
 
+	.type	__condvar_cleanup2, @function
+__condvar_cleanup2:
+	subl	$wakeup_seq, %ebx
+	.size	__condvar_cleanup2, .-__condvar_cleanup2
+.LSbl4:
+	.type	__condvar_cleanup, @function
+__condvar_cleanup:
+	movl	%eax, %esi
+
+	/* Get internal lock.  */
+	movl	$1, %eax
+	LOCK
+#if cond_lock == 0
+	xaddl	%eax, (%ebx)
+#else
+	xaddl	%eax, cond_lock(%ebx)
+#endif
+	testl	%eax, %eax
+	je	1f
+
+#if cond_lock == 0
+	movl	%ebx, %ecx
+#else
+	leal	cond_lock(%ebx), %ecx
+#endif
+	call	__lll_mutex_lock_wait
+
+1:	addl	$1, wakeup_seq(%ebx)
+	adcl	$0, wakeup_seq+4(%ebx)
+
+	addl	$1, woken_seq(%ebx)
+	adcl	$0, woken_seq+4(%ebx)
+
+	LOCK
+	subl	$1, cond_lock(%ebx)
+	je	2f
+
+#if cond_lock == 0
+	movl	%ebx, %eax
+#else
+	leal	cond_lock(%ebx), %eax
+#endif
+	call	__lll_mutex_unlock_wake
+
+	/* Wake up all waiters to make sure no signal gets lost.  */
+2:	addl	$wakeup_seq, %ebx
+	movl	$FUTEX_WAKE, %ecx
+	movl	$SYS_futex, %eax
+	movl	$0x7fffffff, %edx
+	ENTER_KERNEL
+
+	movl	32(%esp), %eax
+	call	__pthread_mutex_cond_lock
+
+	movl	%esi, (%esp)
+.LcallUR:
+	call	_Unwind_Resume
+	hlt
+.LENDCODE:
+	.size	__condvar_cleanup, .-__condvar_cleanup
+
+
+	.section .gcc_except_table,"a",@progbits
+.LexceptSTART:
+	.byte	0xff				# @LPStart format (omit)
+	.byte	0xff				# @TType format (omit)
+	.byte	0x0b				# call-site format
+						# DW_EH_PE_sdata4
+	.uleb128 .Lcstend-.Lcstbegin
+.Lcstbegin:
+	.long	.LcleanupSTART-.LSTARTCODE
+	.long	.Ladd_wakeup-.LcleanupSTART
+	.long	__condvar_cleanup-.LSTARTCODE
+	.uleb128  0
+	.long	.Ladd_wakeup-.LSTARTCODE
+	.long	.Lsub_wakeup-.Ladd_wakeup
+	.long	__condvar_cleanup2-.LSTARTCODE
+	.uleb128  0
+	.long	.Lsub_wakeup-.LSTARTCODE
+	.long	.LcleanupEND-.Lsub_wakeup
+	.long	__condvar_cleanup-.LSTARTCODE
+	.uleb128  0
+	.long	.LcallUR-.LSTARTCODE
+	.long	.LENDCODE-.LcallUR
+	.long	0
+	.uleb128  0
+.Lcstend:
+
 	.section .eh_frame,"a",@progbits
 .LSTARTFRAME:
-	.long	L(ENDCIE)-L(STARTCIE)	# Length of the CIE.
+	.long	L(ENDCIE)-L(STARTCIE)		# Length of the CIE.
 .LSTARTCIE:
 	.long	0				# CIE ID.
 	.byte	1				# Version number.
 #ifdef SHARED
-	.string	"zR"				# NUL-terminated augmentation
+	.string	"zPLR"				# NUL-terminated augmentation
 						# string.
 #else
-	.ascii	"\0"				# NUL-terminated augmentation
+	.string	"zPL"				# NUL-terminated augmentation
 						# string.
 #endif
 	.uleb128 1				# Code alignment factor.
@@ -330,9 +342,20 @@ versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
 	.byte	8				# Return address register
 						# column.
 #ifdef SHARED
-	.uleb128 1				# Augmentation value length.
-	.byte	0x1b				# Encoding: DW_EH_PE_pcrel
+	.uleb128 7				# Augmentation value length.
+	.byte	0x9b				# Personality: DW_EH_PE_pcrel
+						# + DW_EH_PE_sdata4
+						# + DW_EH_PE_indirect
+	.long	DW.ref.__gcc_personality_v0-.
+	.byte	0x1b				# LSDA Encoding: DW_EH_PE_pcrel
 						# + DW_EH_PE_sdata4.
+	.byte	0x1b				# FDE Encoding: DW_EH_PE_pcrel
+						# + DW_EH_PE_sdata4.
+#else
+	.uleb128 6				# Augmentation value length.
+	.byte	0x0				# Personality: absolute
+	.long	__gcc_personality_v0
+	.byte	0x0				# LSDA Encoding: absolute
 #endif
 	.byte 0x0c				# DW_CFA_def_cfa
 	.uleb128 4
@@ -352,8 +375,11 @@ versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
 	.long	.LSTARTCODE			# Start address of the code.
 #endif
 	.long	.LENDCODE-.LSTARTCODE		# Length of the code.
+	.uleb128 4				# Augmentation size
 #ifdef SHARED
-	.uleb128 0				# No augmentation data.
+	.long	.LexceptSTART-.
+#else
+	.long	.LexceptSTART
 #endif
 	.byte	0x40+.Lpush_edi-.LSTARTCODE	# DW_CFA_advance_loc+N
 	.byte	14				# DW_CFA_def_cfa_offset
@@ -373,7 +399,7 @@ versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
 	.byte	2				# DW_CFA_advance_loc1
 	.byte	.Lsubl-.Lpush_ebx
 	.byte	14				# DW_CFA_def_cfa_offset
-	.uleb128 52
+	.uleb128 36
 	.byte	2				# DW_CFA_advance_loc1
 	.byte	.Laddl-.Lsubl
 	.byte	14				# DW_CFA_def_cfa_offset
@@ -405,6 +431,9 @@ versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
 	.byte	0x40+.LSbl3-.LSbl2		# DW_CFA_advance_loc+N
 	.byte	14				# DW_CFA_def_cfa_offset
 	.uleb128 20
+	.byte	0x40+.LSbl4-.LSbl3		# DW_CFA_advance_loc+N
+	.byte	14				# DW_CFA_def_cfa_offset
+	.uleb128 28
 	.align	4
 .LENDFDE:
 
@@ -419,3 +448,14 @@ __i686.get_pc_thunk.cx:
 	ret
 	.size	__i686.get_pc_thunk.cx,.-__i686.get_pc_thunk.cx
 #endif
+
+#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 4
+	.type   DW.ref.__gcc_personality_v0, @object
+	.size   DW.ref.__gcc_personality_v0, 4
+DW.ref.__gcc_personality_v0:
+	.long   __gcc_personality_v0
+#endif
diff --git a/nptl/tst-cancel17.c b/nptl/tst-cancel17.c
index 65b8c73ef8..861ca5ea69 100644
--- a/nptl/tst-cancel17.c
+++ b/nptl/tst-cancel17.c
@@ -18,6 +18,7 @@
    02111-1307 USA.  */
 
 #include <aio.h>
+#include <errno.h>
 #include <pthread.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -44,19 +45,44 @@ tf (void *arg)
   int r = pthread_barrier_wait (&b);
   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
     {
-      puts ("barrier_wait failed");
+      puts ("tf: barrier_wait failed");
+      exit (1);
+    }
+
+  pthread_cleanup_push (cl, NULL);
+
+  const struct aiocb *l[1] = { arg };
+
+  TEMP_FAILURE_RETRY (aio_suspend (l, 1, NULL));
+
+  pthread_cleanup_pop (0);
+
+  puts ("tf: aio_suspend returned");
+
+  exit (1);
+}
+
+
+static void *
+tf2 (void *arg)
+{
+  int r = pthread_barrier_wait (&b);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("tf2: barrier_wait failed");
       exit (1);
     }
 
   pthread_cleanup_push (cl, NULL);
 
   const struct aiocb *l[1] = { arg };
+  struct timespec ts = { .tv_sec = 1000, .tv_nsec = 0 };
 
-  aio_suspend (l, 1, NULL);
+  TEMP_FAILURE_RETRY (aio_suspend (l, 1, &ts));
 
   pthread_cleanup_pop (0);
 
-  puts ("aio_suspend returned");
+  puts ("tf2: aio_suspend returned");
 
   exit (1);
 }
@@ -108,7 +134,7 @@ do_test (void)
   while (nanosleep (&ts, &ts) != 0)
     continue;
 
-  puts ("going to cancel in-time");
+  puts ("going to cancel tf in-time");
   if (pthread_cancel (th) != 0)
     {
       puts ("1st cancel failed");
@@ -129,12 +155,61 @@ do_test (void)
 
   if (cl_called == 0)
     {
-      puts ("cleanup handler not called");
+      puts ("tf cleanup handler not called");
       return 1;
     }
   if (cl_called > 1)
     {
-      puts ("cleanup handler called more than once");
+      puts ("tf cleanup handler called more than once");
+      return 1;
+    }
+
+  cl_called = 0;
+
+  if (pthread_create (&th, NULL, tf2, &a) != 0)
+    {
+      puts ("2nd create failed");
+      return 1;
+    }
+
+  r = pthread_barrier_wait (&b);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("2nd barrier_wait failed");
+      exit (1);
+    }
+
+  ts.tv_sec = 0;
+  ts.tv_nsec = 100000000;
+  while (nanosleep (&ts, &ts) != 0)
+    continue;
+
+  puts ("going to cancel tf2 in-time");
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("2nd cancel failed");
+      return 1;
+    }
+
+  if (pthread_join (th, &status) != 0)
+    {
+      puts ("2nd join failed");
+      return 1;
+    }
+  if (status != PTHREAD_CANCELED)
+    {
+      puts ("2nd thread not canceled");
+      return 1;
+    }
+
+  if (cl_called == 0)
+    {
+      puts ("tf2 cleanup handler not called");
+      return 1;
+    }
+  if (cl_called > 1)
+    {
+      puts ("tf2 cleanup handler called more than once");
       return 1;
     }
 
@@ -156,43 +231,87 @@ do_test (void)
 
   if (pthread_create (&th, NULL, tf, &a) != 0)
     {
-      puts ("2nd create failed");
+      puts ("3rd create failed");
       return 1;
     }
 
-  puts ("going to cancel early");
+  puts ("going to cancel tf early");
   if (pthread_cancel (th) != 0)
     {
-      puts ("2nd cancel failed");
+      puts ("3rd cancel failed");
       return 1;
     }
 
   r = pthread_barrier_wait (&b);
   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
     {
-      puts ("barrier_wait failed");
+      puts ("3rd barrier_wait failed");
       exit (1);
     }
 
   if (pthread_join (th, &status) != 0)
     {
-      puts ("2nd join failed");
+      puts ("3rd join failed");
       return 1;
     }
   if (status != PTHREAD_CANCELED)
     {
-      puts ("2nd thread not canceled");
+      puts ("3rd thread not canceled");
+      return 1;
+    }
+
+  if (cl_called == 0)
+    {
+      printf ("tf cleanup handler not called\n");
+      return 1;
+    }
+  if (cl_called > 1)
+    {
+      printf ("tf cleanup handler called more than once\n");
+      return 1;
+    }
+
+  cl_called = 0;
+
+  if (pthread_create (&th, NULL, tf2, &a) != 0)
+    {
+      puts ("4th create failed");
+      return 1;
+    }
+
+  puts ("going to cancel tf2 early");
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("4th cancel failed");
+      return 1;
+    }
+
+  r = pthread_barrier_wait (&b);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("4th barrier_wait failed");
+      exit (1);
+    }
+
+  if (pthread_join (th, &status) != 0)
+    {
+      puts ("4th join failed");
+      return 1;
+    }
+  if (status != PTHREAD_CANCELED)
+    {
+      puts ("4th thread not canceled");
       return 1;
     }
 
   if (cl_called == 0)
     {
-      printf ("cleanup handler not called\n");
+      printf ("tf2 cleanup handler not called\n");
       return 1;
     }
   if (cl_called > 1)
     {
-      printf ("cleanup handler called more than once\n");
+      printf ("tf2 cleanup handler called more than once\n");
       return 1;
     }
 
diff --git a/nptl/tst-cond8.c b/nptl/tst-cond8.c
index 48451e7813..9c97a96fac 100644
--- a/nptl/tst-cond8.c
+++ b/nptl/tst-cond8.c
@@ -52,6 +52,8 @@ ch (void *arg)
       puts ("ch: cannot unlock mutex");
       exit (1);
     }
+
+  puts ("ch done");
 }
 
 
diff --git a/sysdeps/pthread/aio_misc.h b/sysdeps/pthread/aio_misc.h
index ee0df52970..05e60e7d1e 100644
--- a/sysdeps/pthread/aio_misc.h
+++ b/sysdeps/pthread/aio_misc.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1997,99,2000,01 Free Software Foundation, Inc.
+/* Copyright (C) 1997, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -90,38 +90,41 @@ struct requestlist
 
 
 /* Lock for global I/O list of requests.  */
-extern pthread_mutex_t __aio_requests_mutex;
+extern pthread_mutex_t __aio_requests_mutex attribute_hidden;
 
 
 /* Enqueue request.  */
 extern struct requestlist *__aio_enqueue_request (aiocb_union *aiocbp,
 						  int operation)
-     internal_function;
+     attribute_hidden internal_function;
 
 /* Find request entry for given AIO control block.  */
 extern struct requestlist *__aio_find_req (aiocb_union *elem)
-     internal_function;
+     attribute_hidden internal_function;
 
 /* Find request entry for given file descriptor.  */
-extern struct requestlist *__aio_find_req_fd (int fildes) internal_function;
+extern struct requestlist *__aio_find_req_fd (int fildes)
+     attribute_hidden internal_function;
 
 /* Remove request from the list.  */
 extern void __aio_remove_request (struct requestlist *last,
 				  struct requestlist *req, int all)
-     internal_function;
+     attribute_hidden internal_function;
 
 /* Release the entry for the request.  */
-extern void __aio_free_request (struct requestlist *req) internal_function;
+extern void __aio_free_request (struct requestlist *req)
+     attribute_hidden internal_function;
 
 /* Notify initiator of request and tell this everybody listening.  */
-extern void __aio_notify (struct requestlist *req) internal_function;
+extern void __aio_notify (struct requestlist *req)
+     attribute_hidden internal_function;
 
 /* Notify initiator of request.  */
 extern int __aio_notify_only (struct sigevent *sigev, pid_t caller_pid)
-     internal_function;
+     attribute_hidden internal_function;
 
 /* Send the signal.  */
 extern int __aio_sigqueue (int sig, const union sigval val, pid_t caller_pid)
-     internal_function;
+     attribute_hidden internal_function;
 
 #endif /* aio_misc.h */
diff --git a/sysdeps/pthread/aio_suspend.c b/sysdeps/pthread/aio_suspend.c
index 92cac81036..8bc8f0e9a1 100644
--- a/sysdeps/pthread/aio_suspend.c
+++ b/sysdeps/pthread/aio_suspend.c
@@ -141,7 +141,7 @@ aio_suspend (list, nent, timeout)
 	  .nent = nent
 	};
 
-      __libc_cleanup_region_start (1, cleanup, &clparam);
+      pthread_cleanup_push (cleanup, &clparam);
 
       if (timeout == NULL)
 	result = pthread_cond_wait (&cond, &__aio_requests_mutex);
@@ -165,7 +165,7 @@ aio_suspend (list, nent, timeout)
 					   &abstime);
 	}
 
-      __libc_cleanup_region_end (0);
+      pthread_cleanup_pop (0);
     }
 
   /* Now remove the entry in the waiting list for all requests
@@ -199,8 +199,8 @@ aio_suspend (list, nent, timeout)
 	 form expected from `aio_suspend'.  */
       if (result == ETIMEDOUT)
 	__set_errno (EAGAIN);
-      else if (result == EINTR)
-	__set_errno (EINTR);
+      else
+	__set_errno (result);
 
       result = -1;
     }