73a44fd
diff -rup a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S
73a44fd
--- a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S	2011-12-15 10:45:09.759232551 -0700
73a44fd
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S	2011-12-15 15:11:57.534479377 -0700
73a44fd
@@ -137,6 +137,7 @@ __pthread_cond_wait:
73a44fd
 	cmpl	$PI_BIT, %eax
73a44fd
 	jne	18f
73a44fd
 
73a44fd
+90:
73a44fd
 	movl	$(FUTEX_WAIT_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %ecx
73a44fd
 	movl	%ebp, %edx
73a44fd
 	xorl	%esi, %esi
73a44fd
@@ -150,6 +151,9 @@ __pthread_cond_wait:
73a44fd
 	sete	16(%esp)
73a44fd
 	je	19f
73a44fd
 
73a44fd
+	cmpl	$-EAGAIN, %eax
73a44fd
+	je	91f
73a44fd
+
73a44fd
 	/* Normal and PI futexes dont mix. Use normal futex functions only
73a44fd
 	   if the kernel does not support the PI futex functions.  */
73a44fd
 	cmpl	$-ENOSYS, %eax
73a44fd
@@ -394,6 +398,78 @@ __pthread_cond_wait:
73a44fd
 #endif
73a44fd
 	call	__lll_unlock_wake
73a44fd
 	jmp	11b
73a44fd
+
73a44fd
+91:
73a44fd
+.LcleanupSTART2:
73a44fd
+	/* FUTEX_WAIT_REQUEUE_PI returned EAGAIN.  We need to
73a44fd
+	   call it again.  */
73a44fd
+
73a44fd
+	/* Get internal lock.  */
73a44fd
+	movl	$1, %edx
73a44fd
+	xorl	%eax, %eax
73a44fd
+	LOCK
73a44fd
+#if cond_lock == 0
73a44fd
+	cmpxchgl %edx, (%ebx)
73a44fd
+#else
73a44fd
+	cmpxchgl %edx, cond_lock(%ebx)
73a44fd
+#endif
73a44fd
+	jz	92f
73a44fd
+
73a44fd
+#if cond_lock == 0
73a44fd
+	movl	%ebx, %edx
73a44fd
+#else
73a44fd
+	leal	cond_lock(%ebx), %edx
73a44fd
+#endif
73a44fd
+#if (LLL_SHARED-LLL_PRIVATE) > 255
73a44fd
+	xorl	%ecx, %ecx
73a44fd
+#endif
73a44fd
+	cmpl	$-1, dep_mutex(%ebx)
73a44fd
+	setne	%cl
73a44fd
+	subl	$1, %ecx
73a44fd
+	andl	$(LLL_SHARED-LLL_PRIVATE), %ecx
73a44fd
+#if LLL_PRIVATE != 0
73a44fd
+	addl	$LLL_PRIVATE, %ecx
73a44fd
+#endif
73a44fd
+	call	__lll_lock_wait
73a44fd
+
73a44fd
+92:
73a44fd
+	/* Increment the cond_futex value again, so it can be used as a new
73a44fd
+	   expected value. */
73a44fd
+	addl	$1, cond_futex(%ebx)
73a44fd
+	movl	cond_futex(%ebx), %ebp
73a44fd
+
73a44fd
+	/* Unlock.  */
73a44fd
+	LOCK
73a44fd
+#if cond_lock == 0
73a44fd
+	subl	$1, (%ebx)
73a44fd
+#else
73a44fd
+	subl	$1, cond_lock(%ebx)
73a44fd
+#endif
73a44fd
+	je	93f
73a44fd
+#if cond_lock == 0
73a44fd
+	movl	%ebx, %eax
73a44fd
+#else
73a44fd
+	leal	cond_lock(%ebx), %eax
73a44fd
+#endif
73a44fd
+#if (LLL_SHARED-LLL_PRIVATE) > 255
73a44fd
+	xorl	%ecx, %ecx
73a44fd
+#endif
73a44fd
+	cmpl	$-1, dep_mutex(%ebx)
73a44fd
+	setne	%cl
73a44fd
+	subl	$1, %ecx
73a44fd
+	andl	$(LLL_SHARED-LLL_PRIVATE), %ecx
73a44fd
+#if LLL_PRIVATE != 0
73a44fd
+	addl	$LLL_PRIVATE, %ecx
73a44fd
+#endif
73a44fd
+	call	__lll_unlock_wake
73a44fd
+
73a44fd
+93:
73a44fd
+	/* Set the rest of SYS_futex args for FUTEX_WAIT_REQUEUE_PI. */
73a44fd
+	xorl	%ecx, %ecx
73a44fd
+	movl	dep_mutex(%ebx), %edi
73a44fd
+	jmp	90b
73a44fd
+.LcleanupEND2:
73a44fd
+
73a44fd
 	.size	__pthread_cond_wait, .-__pthread_cond_wait
73a44fd
 versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
73a44fd
 		  GLIBC_2_3_2)
73a44fd
@@ -566,6 +642,10 @@ __condvar_w_cleanup:
73a44fd
 	.long	.LcleanupEND-.Lsub_cond_futex
73a44fd
 	.long	__condvar_w_cleanup-.LSTARTCODE
73a44fd
 	.uleb128  0
73a44fd
+	.long	.LcleanupSTART2-.LSTARTCODE
73a44fd
+	.long	.LcleanupEND2-.LcleanupSTART2
73a44fd
+	.long	__condvar_w_cleanup-.LSTARTCODE
73a44fd
+	.uleb128  0
73a44fd
 	.long	.LcallUR-.LSTARTCODE
73a44fd
 	.long	.LENDCODE-.LcallUR
73a44fd
 	.long	0
73a44fd
diff -rup a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S
73a44fd
--- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S	2011-12-15 10:45:09.764232551 -0700
73a44fd
+++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S	2011-12-15 15:12:49.287474417 -0700
73a44fd
@@ -23,6 +23,7 @@
73a44fd
 #include <lowlevelcond.h>
73a44fd
 #include <tcb-offsets.h>
73a44fd
 #include <pthread-pi-defines.h>
73a44fd
+#include <pthread-errnos.h>
73a44fd
 #include <stap-probe.h>
73a44fd
 
73a44fd
 #include <kernel-features.h>
73a44fd
@@ -136,11 +137,14 @@ __pthread_cond_wait:
73a44fd
 	cmpl	$PI_BIT, %eax
73a44fd
 	jne	61f
73a44fd
 
73a44fd
+90:
73a44fd
 	movl	$(FUTEX_WAIT_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %esi
73a44fd
 	movl	$SYS_futex, %eax
73a44fd
 	syscall
73a44fd
 
73a44fd
 	movl	$1, %r8d
73a44fd
+	cmpq	$-EAGAIN, %rax
73a44fd
+	je	91f
73a44fd
 #ifdef __ASSUME_REQUEUE_PI
73a44fd
 	jmp	62f
73a44fd
 #else
73a44fd
@@ -327,6 +331,70 @@ __pthread_cond_wait:
73a44fd
 
73a44fd
 13:	movq	%r10, %rax
73a44fd
 	jmp	14b
73a44fd
+
73a44fd
+91:
73a44fd
+.LcleanupSTART2:
73a44fd
+	/* FUTEX_WAIT_REQUEUE_PI returned EAGAIN.  We need to
73a44fd
+	   call it again.  */
73a44fd
+	movq	8(%rsp), %rdi
73a44fd
+
73a44fd
+	/* Get internal lock.  */
73a44fd
+	movl	$1, %esi
73a44fd
+	xorl	%eax, %eax
73a44fd
+	LOCK
73a44fd
+#if cond_lock == 0
73a44fd
+	cmpxchgl %esi, (%rdi)
73a44fd
+#else
73a44fd
+	cmpxchgl %esi, cond_lock(%rdi)
73a44fd
+#endif
73a44fd
+	jz	92f
73a44fd
+
73a44fd
+#if cond_lock != 0
73a44fd
+	addq	$cond_lock, %rdi
73a44fd
+#endif
73a44fd
+	cmpq	$-1, dep_mutex-cond_lock(%rdi)
73a44fd
+	movl	$LLL_PRIVATE, %eax
73a44fd
+	movl	$LLL_SHARED, %esi
73a44fd
+	cmovne	%eax, %esi
73a44fd
+	callq	__lll_lock_wait
73a44fd
+#if cond_lock != 0
73a44fd
+	subq	$cond_lock, %rdi
73a44fd
+#endif
73a44fd
+92:
73a44fd
+	/* Increment the cond_futex value again, so it can be used as a new
73a44fd
+	   expected value. */
73a44fd
+	incl	cond_futex(%rdi)
73a44fd
+	movl	cond_futex(%rdi), %edx
73a44fd
+
73a44fd
+	/* Release internal lock.  */
73a44fd
+	LOCK
73a44fd
+#if cond_lock == 0
73a44fd
+	decl	(%rdi)
73a44fd
+#else
73a44fd
+	decl	cond_lock(%rdi)
73a44fd
+#endif
73a44fd
+	jz	93f
73a44fd
+
73a44fd
+#if cond_lock != 0
73a44fd
+	addq	$cond_lock, %rdi
73a44fd
+#endif
73a44fd
+	cmpq	$-1, dep_mutex-cond_lock(%rdi)
73a44fd
+	movl	$LLL_PRIVATE, %eax
73a44fd
+	movl	$LLL_SHARED, %esi
73a44fd
+	cmovne	%eax, %esi
73a44fd
+	/* The call preserves %rdx.  */
73a44fd
+	callq	__lll_unlock_wake
73a44fd
+#if cond_lock != 0
73a44fd
+	subq	$cond_lock, %rdi
73a44fd
+#endif
73a44fd
+93:
73a44fd
+	/* Set the rest of SYS_futex args for FUTEX_WAIT_REQUEUE_PI. */
73a44fd
+	xorq	%r10, %r10
73a44fd
+	movq	dep_mutex(%rdi), %r8
73a44fd
+	leaq	cond_futex(%rdi), %rdi
73a44fd
+	jmp	90b
73a44fd
+.LcleanupEND2:
73a44fd
+
73a44fd
 	.size	__pthread_cond_wait, .-__pthread_cond_wait
73a44fd
 versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
73a44fd
 		  GLIBC_2_3_2)
73a44fd
@@ -479,11 +547,15 @@ __condvar_cleanup1:
73a44fd
 	.uleb128 .LcleanupSTART-.LSTARTCODE
73a44fd
 	.uleb128 .LcleanupEND-.LcleanupSTART
73a44fd
 	.uleb128 __condvar_cleanup1-.LSTARTCODE
73a44fd
-	.uleb128  0
73a44fd
+	.uleb128 0
73a44fd
+	.uleb128 .LcleanupSTART2-.LSTARTCODE
73a44fd
+	.uleb128 .LcleanupEND2-.LcleanupSTART2
73a44fd
+	.uleb128 __condvar_cleanup1-.LSTARTCODE
73a44fd
+	.uleb128 0
73a44fd
 	.uleb128 .LcallUR-.LSTARTCODE
73a44fd
 	.uleb128 .LENDCODE-.LcallUR
73a44fd
 	.uleb128 0
73a44fd
-	.uleb128  0
73a44fd
+	.uleb128 0
73a44fd
 .Lcstend:
73a44fd
 
73a44fd