All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] futex: cmpxchg_futex_value_locked API change
@ 2011-03-07  2:11 Michel Lespinasse
  2011-03-07  8:54 ` Martin Schwidefsky
                   ` (5 more replies)
  0 siblings, 6 replies; 42+ messages in thread
From: Michel Lespinasse @ 2011-03-07  2:11 UTC (permalink / raw)
  To: Darren Hart, Thomas Gleixner, Ingo Molnar, Peter Zijlstra
  Cc: Matt Turner, Russell King, David Howells, Tony Luck,
	Michal Simek, Ralf Baechle, James E.J. Bottomley,
	Benjamin Herrenschmidt, Martin Schwidefsky, Paul Mundt,
	David S. Miller, Chris Metcalf, Andrew Morton, Linus Torvalds,
	linux-kernel

Aplogies for the long CC list - as this proposal involves asm changes
in many architectures, and I have only been able to test on x86,
I have tried to include one maintainer from every arch so they can
hopefully double check me. I do think I got all architectures right,
but you can never be 100% sure...

------------------------------------8<---------------------------------

The cmpxchg_futex_value_locked API was funny in that it returned either
the original, user-exposed futex value OR an error code such as -EFAULT.
This was confusing at best, and could be a source of livelocks in places
that retry the cmpxchg_futex_value_locked after trying to fix the issue
by running fault_in_user_writeable().

This change makes the cmpxchg_futex_value_locked API more similar to the
get_futex_value_locked one, returning an error code and updating the
original value through a reference argument.

Signed-off-by: Michel Lespinasse <walken@google.com>
---
 arch/alpha/include/asm/futex.h      |   22 +++++++++-------
 arch/arm/include/asm/futex.h        |   23 +++++++++--------
 arch/frv/include/asm/futex.h        |    3 +-
 arch/ia64/include/asm/futex.h       |    9 ++++--
 arch/microblaze/include/asm/futex.h |   24 ++++++++++--------
 arch/mips/include/asm/futex.h       |   32 +++++++++++++-----------
 arch/parisc/include/asm/futex.h     |   18 +++++++-------
 arch/powerpc/include/asm/futex.h    |   20 ++++++++-------
 arch/s390/include/asm/futex.h       |    4 +-
 arch/s390/include/asm/uaccess.h     |    2 +-
 arch/s390/lib/uaccess.h             |    4 +-
 arch/s390/lib/uaccess_pt.c          |   13 ++++++----
 arch/s390/lib/uaccess_std.c         |    6 +++-
 arch/sh/include/asm/futex-irq.h     |    9 +++----
 arch/sh/include/asm/futex.h         |    5 ++-
 arch/sparc/include/asm/futex_64.h   |   16 +++++++----
 arch/tile/include/asm/futex.h       |    7 +++--
 arch/x86/include/asm/futex.h        |   16 +++++++-----
 include/asm-generic/futex.h         |    3 +-
 kernel/futex.c                      |   46 ++++++++++++----------------------
 20 files changed, 147 insertions(+), 135 deletions(-)

diff --git a/arch/alpha/include/asm/futex.h b/arch/alpha/include/asm/futex.h
index 945de22..c4e5c28 100644
--- a/arch/alpha/include/asm/futex.h
+++ b/arch/alpha/include/asm/futex.h
@@ -81,21 +81,22 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
+			      int oldval, int newval)
 {
-	int prev, cmp;
+	int ret = 0, prev, cmp;
 
 	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
 		return -EFAULT;
 
 	__asm__ __volatile__ (
 		__ASM_SMP_MB
-	"1:	ldl_l	%0,0(%2)\n"
-	"	cmpeq	%0,%3,%1\n"
-	"	beq	%1,3f\n"
-	"	mov	%4,%1\n"
-	"2:	stl_c	%1,0(%2)\n"
-	"	beq	%1,4f\n"
+	"1:	ldl_l	%1,0(%3)\n"
+	"	cmpeq	%1,%4,%2\n"
+	"	beq	%2,3f\n"
+	"	mov	%5,%2\n"
+	"2:	stl_c	%2,0(%3)\n"
+	"	beq	%2,4f\n"
 	"3:	.subsection 2\n"
 	"4:	br	1b\n"
 	"	.previous\n"
@@ -105,11 +106,12 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
 	"	.long	2b-.\n"
 	"	lda	$31,3b-2b(%0)\n"
 	"	.previous\n"
-	:	"=&r"(prev), "=&r"(cmp)
+	:	"+r"(ret), "=&r"(prev), "=&r"(cmp)
 	:	"r"(uaddr), "r"((long)oldval), "r"(newval)
 	:	"memory");
 
-	return prev;
+	*uval = prev;
+	return ret;
 }
 
 #endif /* __KERNEL__ */
diff --git a/arch/arm/include/asm/futex.h b/arch/arm/include/asm/futex.h
index b33fe70..d20b78f 100644
--- a/arch/arm/include/asm/futex.h
+++ b/arch/arm/include/asm/futex.h
@@ -88,36 +88,37 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
+			      int oldval, int newval)
 {
-	int val;
+	int ret = 0, val;
 
 	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
 		return -EFAULT;
 
-	pagefault_disable();	/* implies preempt_disable() */
+	/* Note that preemption is disabled by futex_atomic_cmpxchg_inatomic
+	 * call sites. */
 
 	__asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n"
-	"1:	" T(ldr) "	%0, [%3]\n"
-	"	teq	%0, %1\n"
+	"1:	" T(ldr) "	%1, [%4]\n"
+	"	teq	%1, %2\n"
 	"	it	eq	@ explicit IT needed for the 2b label\n"
-	"2:	" T(streq) "	%2, [%3]\n"
+	"2:	" T(streq) "	%3, [%4]\n"
 	"3:\n"
 	"	.pushsection __ex_table,\"a\"\n"
 	"	.align	3\n"
 	"	.long	1b, 4f, 2b, 4f\n"
 	"	.popsection\n"
 	"	.pushsection .fixup,\"ax\"\n"
-	"4:	mov	%0, %4\n"
+	"4:	mov	%0, %5\n"
 	"	b	3b\n"
 	"	.popsection"
-	: "=&r" (val)
+	: "+r" (ret), "=&r" (val)
 	: "r" (oldval), "r" (newval), "r" (uaddr), "Ir" (-EFAULT)
 	: "cc", "memory");
 
-	pagefault_enable();	/* subsumes preempt_enable() */
-
-	return val;
+	*uval = val;
+	return ret;
 }
 
 #endif /* !SMP */
diff --git a/arch/frv/include/asm/futex.h b/arch/frv/include/asm/futex.h
index 08b3d1d..0548f8e 100644
--- a/arch/frv/include/asm/futex.h
+++ b/arch/frv/include/asm/futex.h
@@ -10,7 +10,8 @@
 extern int futex_atomic_op_inuser(int encoded_op, int __user *uaddr);
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
+			      int oldval, int newval)
 {
 	return -ENOSYS;
 }
diff --git a/arch/ia64/include/asm/futex.h b/arch/ia64/include/asm/futex.h
index c7f0f06..b072840 100644
--- a/arch/ia64/include/asm/futex.h
+++ b/arch/ia64/include/asm/futex.h
@@ -100,23 +100,26 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
+			      int oldval, int newval)
 {
 	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
 		return -EFAULT;
 
 	{
-		register unsigned long r8 __asm ("r8");
+		register unsigned long r8 __asm ("r8") = 0;
+		unsigned long prev;
 		__asm__ __volatile__(
 			"	mf;;					\n"
 			"	mov ar.ccv=%3;;				\n"
 			"[1:]	cmpxchg4.acq %0=[%1],%2,ar.ccv		\n"
 			"	.xdata4 \"__ex_table\", 1b-., 2f-.	\n"
 			"[2:]"
-			: "=r" (r8)
+			: "=r" (prev)
 			: "r" (uaddr), "r" (newval),
 			  "rO" ((long) (unsigned) oldval)
 			: "memory");
+		*uval = prev;
 		return r8;
 	}
 }
diff --git a/arch/microblaze/include/asm/futex.h b/arch/microblaze/include/asm/futex.h
index ad3fd61..fa019ed 100644
--- a/arch/microblaze/include/asm/futex.h
+++ b/arch/microblaze/include/asm/futex.h
@@ -94,31 +94,33 @@ futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
+			      int oldval, int newval)
 {
-	int prev, cmp;
+	int ret = 0, prev, cmp;
 
 	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
 		return -EFAULT;
 
-	__asm__ __volatile__ ("1:	lwx	%0, %2, r0;		\
-					cmp	%1, %0, %3;		\
-					beqi	%1, 3f;			\
-				2:	swx	%4, %2, r0;		\
-					addic	%1, r0, 0;		\
-					bnei	%1, 1b;			\
+	__asm__ __volatile__ ("1:	lwx	%1, %3, r0;		\
+					cmp	%2, %1, %4;		\
+					beqi	%2, 3f;			\
+				2:	swx	%5, %3, r0;		\
+					addic	%2, r0, 0;		\
+					bnei	%2, 1b;			\
 				3:					\
 				.section .fixup,\"ax\";			\
 				4:	brid	3b;			\
-					addik	%0, r0, %5;		\
+					addik	%0, r0, %6;		\
 				.previous;				\
 				.section __ex_table,\"a\";		\
 				.word	1b,4b,2b,4b;			\
 				.previous;"				\
-		: "=&r" (prev), "=&r"(cmp)				\
+		: "+r" (ret), "=&r" (prev), "=&r"(cmp)	\
 		: "r" (uaddr), "r" (oldval), "r" (newval), "i" (-EFAULT));
 
-	return prev;
+	*uval = prev;
+	return ret;
 }
 
 #endif /* __KERNEL__ */
diff --git a/arch/mips/include/asm/futex.h b/arch/mips/include/asm/futex.h
index b9cce90..692a24b 100644
--- a/arch/mips/include/asm/futex.h
+++ b/arch/mips/include/asm/futex.h
@@ -132,9 +132,10 @@ futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
+			      int oldval, int newval)
 {
-	int retval;
+	int ret = 0, val;
 
 	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
 		return -EFAULT;
@@ -145,25 +146,25 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
 		"	.set	push					\n"
 		"	.set	noat					\n"
 		"	.set	mips3					\n"
-		"1:	ll	%0, %2					\n"
-		"	bne	%0, %z3, 3f				\n"
+		"1:	ll	%1, %3					\n"
+		"	bne	%1, %z4, 3f				\n"
 		"	.set	mips0					\n"
-		"	move	$1, %z4					\n"
+		"	move	$1, %z5					\n"
 		"	.set	mips3					\n"
-		"2:	sc	$1, %1					\n"
+		"2:	sc	$1, %2					\n"
 		"	beqzl	$1, 1b					\n"
 		__WEAK_LLSC_MB
 		"3:							\n"
 		"	.set	pop					\n"
 		"	.section .fixup,\"ax\"				\n"
-		"4:	li	%0, %5					\n"
+		"4:	li	%0, %6					\n"
 		"	j	3b					\n"
 		"	.previous					\n"
 		"	.section __ex_table,\"a\"			\n"
 		"	"__UA_ADDR "\t1b, 4b				\n"
 		"	"__UA_ADDR "\t2b, 4b				\n"
 		"	.previous					\n"
-		: "=&r" (retval), "=R" (*uaddr)
+		: "+r" (ret), "=&r" (val), "=R" (*uaddr)
 		: "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT)
 		: "memory");
 	} else if (cpu_has_llsc) {
@@ -172,31 +173,32 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
 		"	.set	push					\n"
 		"	.set	noat					\n"
 		"	.set	mips3					\n"
-		"1:	ll	%0, %2					\n"
-		"	bne	%0, %z3, 3f				\n"
+		"1:	ll	%1, %3					\n"
+		"	bne	%1, %z4, 3f				\n"
 		"	.set	mips0					\n"
-		"	move	$1, %z4					\n"
+		"	move	$1, %z5					\n"
 		"	.set	mips3					\n"
-		"2:	sc	$1, %1					\n"
+		"2:	sc	$1, %2					\n"
 		"	beqz	$1, 1b					\n"
 		__WEAK_LLSC_MB
 		"3:							\n"
 		"	.set	pop					\n"
 		"	.section .fixup,\"ax\"				\n"
-		"4:	li	%0, %5					\n"
+		"4:	li	%0, %6					\n"
 		"	j	3b					\n"
 		"	.previous					\n"
 		"	.section __ex_table,\"a\"			\n"
 		"	"__UA_ADDR "\t1b, 4b				\n"
 		"	"__UA_ADDR "\t2b, 4b				\n"
 		"	.previous					\n"
-		: "=&r" (retval), "=R" (*uaddr)
+		: "+r" (ret), "=&r" (val), "=R" (*uaddr)
 		: "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT)
 		: "memory");
 	} else
 		return -ENOSYS;
 
-	return retval;
+	*uval = val;
+	return ret;
 }
 
 #endif
diff --git a/arch/parisc/include/asm/futex.h b/arch/parisc/include/asm/futex.h
index 0c705c3..4c6d867 100644
--- a/arch/parisc/include/asm/futex.h
+++ b/arch/parisc/include/asm/futex.h
@@ -51,10 +51,10 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 
 /* Non-atomic version */
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
+			      int oldval, int newval)
 {
-	int err = 0;
-	int uval;
+	int val;
 
 	/* futex.c wants to do a cmpxchg_inatomic on kernel NULL, which is
 	 * our gateway page, and causes no end of trouble...
@@ -65,12 +65,12 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
 	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
 		return -EFAULT;
 
-	err = get_user(uval, uaddr);
-	if (err) return -EFAULT;
-	if (uval == oldval)
-		err = put_user(newval, uaddr);
-	if (err) return -EFAULT;
-	return uval;
+	if (get_user(val, uaddr))
+		return -EFAULT;
+	if (val == oldval && put_user(newval, uaddr))
+		return -EFAULT;
+	*uval = val;
+	return 0;
 }
 
 #endif /*__KERNEL__*/
diff --git a/arch/powerpc/include/asm/futex.h b/arch/powerpc/include/asm/futex.h
index 7c589ef..631e8da 100644
--- a/arch/powerpc/include/asm/futex.h
+++ b/arch/powerpc/include/asm/futex.h
@@ -82,35 +82,37 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
+			      int oldval, int newval)
 {
-	int prev;
+	int ret = 0, prev;
 
 	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
 		return -EFAULT;
 
         __asm__ __volatile__ (
         PPC_RELEASE_BARRIER
-"1:     lwarx   %0,0,%2         # futex_atomic_cmpxchg_inatomic\n\
-        cmpw    0,%0,%3\n\
+"1:     lwarx   %1,0,%3         # futex_atomic_cmpxchg_inatomic\n\
+        cmpw    0,%1,%4\n\
         bne-    3f\n"
-        PPC405_ERR77(0,%2)
-"2:     stwcx.  %4,0,%2\n\
+        PPC405_ERR77(0,%3)
+"2:     stwcx.  %5,0,%3\n\
         bne-    1b\n"
         PPC_ACQUIRE_BARRIER
 "3:	.section .fixup,\"ax\"\n\
-4:	li	%0,%5\n\
+4:	li	%0,%6\n\
 	b	3b\n\
 	.previous\n\
 	.section __ex_table,\"a\"\n\
 	.align 3\n\
 	" PPC_LONG "1b,4b,2b,4b\n\
 	.previous" \
-        : "=&r" (prev), "+m" (*uaddr)
+        : "+r" (ret), "=&r" (prev), "+m" (*uaddr)
         : "r" (uaddr), "r" (oldval), "r" (newval), "i" (-EFAULT)
         : "cc", "memory");
 
-        return prev;
+	*uval = prev;
+        return ret;
 }
 
 #endif /* __KERNEL__ */
diff --git a/arch/s390/include/asm/futex.h b/arch/s390/include/asm/futex.h
index 5c5d02d..27ac515 100644
--- a/arch/s390/include/asm/futex.h
+++ b/arch/s390/include/asm/futex.h
@@ -39,13 +39,13 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 	return ret;
 }
 
-static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr,
+static inline int futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
 						int oldval, int newval)
 {
 	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
 		return -EFAULT;
 
-	return uaccess.futex_atomic_cmpxchg(uaddr, oldval, newval);
+	return uaccess.futex_atomic_cmpxchg(uval, uaddr, oldval, newval);
 }
 
 #endif /* __KERNEL__ */
diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h
index d6b1ed0..549adf6 100644
--- a/arch/s390/include/asm/uaccess.h
+++ b/arch/s390/include/asm/uaccess.h
@@ -84,7 +84,7 @@ struct uaccess_ops {
 	size_t (*strnlen_user)(size_t, const char __user *);
 	size_t (*strncpy_from_user)(size_t, const char __user *, char *);
 	int (*futex_atomic_op)(int op, int __user *, int oparg, int *old);
-	int (*futex_atomic_cmpxchg)(int __user *, int old, int new);
+	int (*futex_atomic_cmpxchg)(int *, int __user *, int old, int new);
 };
 
 extern struct uaccess_ops uaccess;
diff --git a/arch/s390/lib/uaccess.h b/arch/s390/lib/uaccess.h
index 126011d..89a8067 100644
--- a/arch/s390/lib/uaccess.h
+++ b/arch/s390/lib/uaccess.h
@@ -12,12 +12,12 @@ extern size_t copy_from_user_std(size_t, const void __user *, void *);
 extern size_t copy_to_user_std(size_t, void __user *, const void *);
 extern size_t strnlen_user_std(size_t, const char __user *);
 extern size_t strncpy_from_user_std(size_t, const char __user *, char *);
-extern int futex_atomic_cmpxchg_std(int __user *, int, int);
+extern int futex_atomic_cmpxchg_std(int *, int __user *, int, int);
 extern int futex_atomic_op_std(int, int __user *, int, int *);
 
 extern size_t copy_from_user_pt(size_t, const void __user *, void *);
 extern size_t copy_to_user_pt(size_t, void __user *, const void *);
 extern int futex_atomic_op_pt(int, int __user *, int, int *);
-extern int futex_atomic_cmpxchg_pt(int __user *, int, int);
+extern int futex_atomic_cmpxchg_pt(int *, int __user *, int, int);
 
 #endif /* __ARCH_S390_LIB_UACCESS_H */
diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c
index 404f2de..e4f9ad8 100644
--- a/arch/s390/lib/uaccess_pt.c
+++ b/arch/s390/lib/uaccess_pt.c
@@ -354,26 +354,29 @@ int futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old)
 	return ret;
 }
 
-static int __futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval)
+static int __futex_atomic_cmpxchg_pt(int *uval, int __user *uaddr,
+				     int oldval, int newval)
 {
 	int ret;
 
 	asm volatile("0: cs   %1,%4,0(%5)\n"
-		     "1: lr   %0,%1\n"
+		     "1: l    %0,0\n"
 		     "2:\n"
 		     EX_TABLE(0b,2b) EX_TABLE(1b,2b)
 		     : "=d" (ret), "+d" (oldval), "=m" (*uaddr)
 		     : "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr)
 		     : "cc", "memory" );
+	*uval = oldval;
 	return ret;
 }
 
-int futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval)
+int futex_atomic_cmpxchg_pt(int *uval, int __user *uaddr,
+			    int oldval, int newval)
 {
 	int ret;
 
 	if (segment_eq(get_fs(), KERNEL_DS))
-		return __futex_atomic_cmpxchg_pt(uaddr, oldval, newval);
+		return __futex_atomic_cmpxchg_pt(uval, uaddr, oldval, newval);
 	spin_lock(&current->mm->page_table_lock);
 	uaddr = (int __user *) __dat_user_addr((unsigned long) uaddr);
 	if (!uaddr) {
@@ -382,7 +385,7 @@ int futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval)
 	}
 	get_page(virt_to_page(uaddr));
 	spin_unlock(&current->mm->page_table_lock);
-	ret = __futex_atomic_cmpxchg_pt(uaddr, oldval, newval);
+	ret = __futex_atomic_cmpxchg_pt(uval, uaddr, oldval, newval);
 	put_page(virt_to_page(uaddr));
 	return ret;
 }
diff --git a/arch/s390/lib/uaccess_std.c b/arch/s390/lib/uaccess_std.c
index a6c4f7e..5c568b3 100644
--- a/arch/s390/lib/uaccess_std.c
+++ b/arch/s390/lib/uaccess_std.c
@@ -287,19 +287,21 @@ int futex_atomic_op_std(int op, int __user *uaddr, int oparg, int *old)
 	return ret;
 }
 
-int futex_atomic_cmpxchg_std(int __user *uaddr, int oldval, int newval)
+int futex_atomic_cmpxchg_std(int *uval, int __user *uaddr,
+			     int oldval, int newval)
 {
 	int ret;
 
 	asm volatile(
 		"   sacf 256\n"
 		"0: cs   %1,%4,0(%5)\n"
-		"1: lr   %0,%1\n"
+		"1: l    %0,0\n"
 		"2: sacf 0\n"
 		EX_TABLE(0b,2b) EX_TABLE(1b,2b)
 		: "=d" (ret), "+d" (oldval), "=m" (*uaddr)
 		: "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr)
 		: "cc", "memory" );
+	*uval = oldval;
 	return ret;
 }
 
diff --git a/arch/sh/include/asm/futex-irq.h b/arch/sh/include/asm/futex-irq.h
index a9f16a7..7b701cb 100644
--- a/arch/sh/include/asm/futex-irq.h
+++ b/arch/sh/include/asm/futex-irq.h
@@ -88,7 +88,8 @@ static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr,
 	return ret;
 }
 
-static inline int atomic_futex_op_cmpxchg_inatomic(int __user *uaddr,
+static inline int atomic_futex_op_cmpxchg_inatomic(int *uval,
+						   int __user *uaddr,
 						   int oldval, int newval)
 {
 	unsigned long flags;
@@ -102,10 +103,8 @@ static inline int atomic_futex_op_cmpxchg_inatomic(int __user *uaddr,
 
 	local_irq_restore(flags);
 
-	if (ret)
-		return ret;
-
-	return prev;
+	*uval = prev;
+	return ret;
 }
 
 #endif /* __ASM_SH_FUTEX_IRQ_H */
diff --git a/arch/sh/include/asm/futex.h b/arch/sh/include/asm/futex.h
index 68256ec..a8a5125 100644
--- a/arch/sh/include/asm/futex.h
+++ b/arch/sh/include/asm/futex.h
@@ -65,12 +65,13 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
+			      int oldval, int newval)
 {
 	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
 		return -EFAULT;
 
-	return atomic_futex_op_cmpxchg_inatomic(uaddr, oldval, newval);
+	return atomic_futex_op_cmpxchg_inatomic(uval, uaddr, oldval, newval);
 }
 
 #endif /* __KERNEL__ */
diff --git a/arch/sparc/include/asm/futex_64.h b/arch/sparc/include/asm/futex_64.h
index 47f9583..e086220 100644
--- a/arch/sparc/include/asm/futex_64.h
+++ b/arch/sparc/include/asm/futex_64.h
@@ -85,26 +85,30 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
+			      int oldval, int newval)
 {
+	int ret = 0;
+
 	__asm__ __volatile__(
-	"\n1:	casa	[%3] %%asi, %2, %0\n"
+	"\n1:	casa	[%4] %%asi, %3, %1\n"
 	"2:\n"
 	"	.section .fixup,#alloc,#execinstr\n"
 	"	.align	4\n"
 	"3:	sethi	%%hi(2b), %0\n"
 	"	jmpl	%0 + %%lo(2b), %%g0\n"
-	"	 mov	%4, %0\n"
+	"	mov	%5, %0\n"
 	"	.previous\n"
 	"	.section __ex_table,\"a\"\n"
 	"	.align	4\n"
 	"	.word	1b, 3b\n"
 	"	.previous\n"
-	: "=r" (newval)
-	: "0" (newval), "r" (oldval), "r" (uaddr), "i" (-EFAULT)
+	: "+r" (ret), "=r" (newval)
+	: "1" (newval), "r" (oldval), "r" (uaddr), "i" (-EFAULT)
 	: "memory");
 
-	return newval;
+	*uval = newval;
+	return ret;
 }
 
 #endif /* !(_SPARC64_FUTEX_H) */
diff --git a/arch/tile/include/asm/futex.h b/arch/tile/include/asm/futex.h
index fe0d10d..664b20a 100644
--- a/arch/tile/include/asm/futex.h
+++ b/arch/tile/include/asm/futex.h
@@ -119,8 +119,8 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 	return ret;
 }
 
-static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval,
-						int newval)
+static inline int futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
+						int oldval, int newval)
 {
 	struct __get_user asm_ret;
 
@@ -128,7 +128,8 @@ static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval,
 		return -EFAULT;
 
 	asm_ret = futex_cmpxchg(uaddr, oldval, newval);
-	return asm_ret.err ? asm_ret.err : asm_ret.val;
+	*uval = asm_ret.val;
+	return asm_ret.err;
 }
 
 #ifndef __tilegx__
diff --git a/arch/x86/include/asm/futex.h b/arch/x86/include/asm/futex.h
index 1f11ce4..884c0b5 100644
--- a/arch/x86/include/asm/futex.h
+++ b/arch/x86/include/asm/futex.h
@@ -109,9 +109,10 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 	return ret;
 }
 
-static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval,
-						int newval)
+static inline int futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
+						int oldval, int newval)
 {
+	int ret = 0;
 
 #if defined(CONFIG_X86_32) && !defined(CONFIG_X86_BSWAP)
 	/* Real i386 machines have no cmpxchg instruction */
@@ -122,18 +123,19 @@ static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval,
 	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
 		return -EFAULT;
 
-	asm volatile("1:\t" LOCK_PREFIX "cmpxchgl %3, %1\n"
+	asm volatile("1:\t" LOCK_PREFIX "cmpxchgl %4, %2\n"
 		     "2:\t.section .fixup, \"ax\"\n"
-		     "3:\tmov     %2, %0\n"
+		     "3:\tmov     %3, %0\n"
 		     "\tjmp     2b\n"
 		     "\t.previous\n"
 		     _ASM_EXTABLE(1b, 3b)
-		     : "=a" (oldval), "+m" (*uaddr)
-		     : "i" (-EFAULT), "r" (newval), "0" (oldval)
+		     : "+r" (ret), "=a" (oldval), "+m" (*uaddr)
+		     : "i" (-EFAULT), "r" (newval), "1" (oldval)
 		     : "memory"
 	);
 
-	return oldval;
+	*uval = oldval;
+	return ret;
 }
 
 #endif
diff --git a/include/asm-generic/futex.h b/include/asm-generic/futex.h
index 3c2344f..132bf52 100644
--- a/include/asm-generic/futex.h
+++ b/include/asm-generic/futex.h
@@ -48,7 +48,8 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
+			      int oldval, int newval)
 {
 	return -ENOSYS;
 }
diff --git a/kernel/futex.c b/kernel/futex.c
index 3184d3b..53b783f 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -381,15 +381,16 @@ static struct futex_q *futex_top_waiter(struct futex_hash_bucket *hb,
 	return NULL;
 }
 
-static u32 cmpxchg_futex_value_locked(u32 __user *uaddr, u32 uval, u32 newval)
+static int cmpxchg_futex_value_locked(u32 *curval, u32 __user *uaddr,
+				      u32 uval, u32 newval)
 {
-	u32 curval;
+	int ret;
 
 	pagefault_disable();
-	curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval);
+	ret = futex_atomic_cmpxchg_inatomic(curval, uaddr, uval, newval);
 	pagefault_enable();
 
-	return curval;
+	return ret;
 }
 
 static int get_futex_value_locked(u32 *dest, u32 __user *from)
@@ -688,9 +689,7 @@ retry:
 	if (set_waiters)
 		newval |= FUTEX_WAITERS;
 
-	curval = cmpxchg_futex_value_locked(uaddr, 0, newval);
-
-	if (unlikely(curval == -EFAULT))
+	if (unlikely(cmpxchg_futex_value_locked(&curval, uaddr, 0, newval)))
 		return -EFAULT;
 
 	/*
@@ -728,9 +727,7 @@ retry:
 		lock_taken = 1;
 	}
 
-	curval = cmpxchg_futex_value_locked(uaddr, uval, newval);
-
-	if (unlikely(curval == -EFAULT))
+	if (unlikely(cmpxchg_futex_value_locked(&curval, uaddr, uval, newval)))
 		return -EFAULT;
 	if (unlikely(curval != uval))
 		goto retry;
@@ -843,9 +840,7 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this)
 
 		newval = FUTEX_WAITERS | task_pid_vnr(new_owner);
 
-		curval = cmpxchg_futex_value_locked(uaddr, uval, newval);
-
-		if (curval == -EFAULT)
+		if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval))
 			ret = -EFAULT;
 		else if (curval != uval)
 			ret = -EINVAL;
@@ -880,10 +875,8 @@ static int unlock_futex_pi(u32 __user *uaddr, u32 uval)
 	 * There is no waiter, so we unlock the futex. The owner died
 	 * bit has not to be preserved here. We are the owner:
 	 */
-	oldval = cmpxchg_futex_value_locked(uaddr, uval, 0);
-
-	if (oldval == -EFAULT)
-		return oldval;
+	if (cmpxchg_futex_value_locked(&oldval, uaddr, uval, 0))
+		return -EFAULT;
 	if (oldval != uval)
 		return -EAGAIN;
 
@@ -1578,9 +1571,7 @@ retry:
 	while (1) {
 		newval = (uval & FUTEX_OWNER_DIED) | newtid;
 
-		curval = cmpxchg_futex_value_locked(uaddr, uval, newval);
-
-		if (curval == -EFAULT)
+		if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval))
 			goto handle_fault;
 		if (curval == uval)
 			break;
@@ -2073,11 +2064,9 @@ retry:
 	 * again. If it succeeds then we can return without waking
 	 * anyone else up:
 	 */
-	if (!(uval & FUTEX_OWNER_DIED))
-		uval = cmpxchg_futex_value_locked(uaddr, task_pid_vnr(current), 0);
-
-
-	if (unlikely(uval == -EFAULT))
+	if (!(uval & FUTEX_OWNER_DIED) &&
+	    unlikely(cmpxchg_futex_value_locked(&uval, uaddr,
+						task_pid_vnr(current), 0)))
 		goto pi_faulted;
 	/*
 	 * Rare case: we managed to release the lock atomically,
@@ -2464,9 +2453,7 @@ retry:
 		 * userspace.
 		 */
 		mval = (uval & FUTEX_WAITERS) | FUTEX_OWNER_DIED;
-		nval = futex_atomic_cmpxchg_inatomic(uaddr, uval, mval);
-
-		if (nval == -EFAULT)
+		if (futex_atomic_cmpxchg_inatomic(&nval, uaddr, uval, mval))
 			return -1;
 
 		if (nval != uval)
@@ -2679,8 +2666,7 @@ static int __init futex_init(void)
 	 * implementation, the non-functional ones will return
 	 * -ENOSYS.
 	 */
-	curval = cmpxchg_futex_value_locked(NULL, 0, 0);
-	if (curval == -EFAULT)
+	if (cmpxchg_futex_value_locked(&curval, NULL, 0, 0) == -EFAULT)
 		futex_cmpxchg_enabled = 1;
 
 	for (i = 0; i < ARRAY_SIZE(futex_queues); i++) {
-- 
1.7.3.1



-- 
Michel "Walken" Lespinasse
A program is never fully debugged until the last user dies.

^ permalink raw reply related	[flat|nested] 42+ messages in thread

* Re: [PATCH] futex: cmpxchg_futex_value_locked API change
  2011-03-07  2:11 [PATCH] futex: cmpxchg_futex_value_locked API change Michel Lespinasse
@ 2011-03-07  8:54 ` Martin Schwidefsky
  2011-03-07 14:25 ` Chris Metcalf
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 42+ messages in thread
From: Martin Schwidefsky @ 2011-03-07  8:54 UTC (permalink / raw)
  To: Michel Lespinasse
  Cc: Darren Hart, Thomas Gleixner, Ingo Molnar, Peter Zijlstra,
	Matt Turner, Russell King, David Howells, Tony Luck,
	Michal Simek, Ralf Baechle, James E.J. Bottomley,
	Benjamin Herrenschmidt, Paul Mundt, David S. Miller,
	Chris Metcalf, Andrew Morton, Linus Torvalds, linux-kernel

On Sun, 6 Mar 2011 18:11:27 -0800
Michel Lespinasse <walken@google.com> wrote:

> Aplogies for the long CC list - as this proposal involves asm changes
> in many architectures, and I have only been able to test on x86,
> I have tried to include one maintainer from every arch so they can
> hopefully double check me. I do think I got all architectures right,
> but you can never be 100% sure...
> 
> -static int __futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval)
> +static int __futex_atomic_cmpxchg_pt(int *uval, int __user *uaddr,
> +				     int oldval, int newval)
>  {
>  	int ret;
> 
>  	asm volatile("0: cs   %1,%4,0(%5)\n"
> -		     "1: lr   %0,%1\n"
> +		     "1: l    %0,0\n"
>  		     "2:\n"
>  		     EX_TABLE(0b,2b) EX_TABLE(1b,2b)
>  		     : "=d" (ret), "+d" (oldval), "=m" (*uaddr)
>  		     : "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr)
>  		     : "cc", "memory" );
> +	*uval = oldval;
>  	return ret;
>  }

That "l %0,0" is incorrect; if you want to load a zero into %0 you can use "la %0,0".

-- 
blue skies,
   Martin.

"Reality continues to ruin my life." - Calvin.


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH] futex: cmpxchg_futex_value_locked API change
  2011-03-07  2:11 [PATCH] futex: cmpxchg_futex_value_locked API change Michel Lespinasse
  2011-03-07  8:54 ` Martin Schwidefsky
@ 2011-03-07 14:25 ` Chris Metcalf
  2011-03-07 21:58 ` Luck, Tony
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 42+ messages in thread
From: Chris Metcalf @ 2011-03-07 14:25 UTC (permalink / raw)
  To: Michel Lespinasse
  Cc: Darren Hart, Thomas Gleixner, Ingo Molnar, Peter Zijlstra,
	Matt Turner, Russell King, David Howells, Tony Luck,
	Michal Simek, Ralf Baechle, James E.J. Bottomley,
	Benjamin Herrenschmidt, Martin Schwidefsky, Paul Mundt,
	David S. Miller, Andrew Morton, Linus Torvalds, linux-kernel

On 3/6/2011 9:11 PM, Michel Lespinasse wrote:
> The cmpxchg_futex_value_locked API was funny in that it returned either
> the original, user-exposed futex value OR an error code such as -EFAULT.
> This was confusing at best, and could be a source of livelocks in places
> that retry the cmpxchg_futex_value_locked after trying to fix the issue
> by running fault_in_user_writeable().
>
> This change makes the cmpxchg_futex_value_locked API more similar to the
> get_futex_value_locked one, returning an error code and updating the
> original value through a reference argument.
> [...]
> diff --git a/arch/tile/include/asm/futex.h b/arch/tile/include/asm/futex.h

Makes sense to me; that API is a little crazy.

For the tile changes:

Acked-by: Chris Metcalf <cmetcalf@tilera.com>

-- 
Chris Metcalf, Tilera Corp.
http://www.tilera.com


^ permalink raw reply	[flat|nested] 42+ messages in thread

* RE: [PATCH] futex: cmpxchg_futex_value_locked API change
  2011-03-07  2:11 [PATCH] futex: cmpxchg_futex_value_locked API change Michel Lespinasse
  2011-03-07  8:54 ` Martin Schwidefsky
  2011-03-07 14:25 ` Chris Metcalf
@ 2011-03-07 21:58 ` Luck, Tony
  2011-03-08 20:17 ` Thomas Gleixner
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 42+ messages in thread
From: Luck, Tony @ 2011-03-07 21:58 UTC (permalink / raw)
  To: Michel Lespinasse, Darren Hart, Thomas Gleixner, Ingo Molnar,
	Peter Zijlstra
  Cc: Matt Turner, Russell King, David Howells, Michal Simek,
	Ralf Baechle, James E.J. Bottomley, Benjamin Herrenschmidt,
	Martin Schwidefsky, Paul Mundt, David S. Miller, Chris Metcalf,
	Andrew Morton, Linus Torvalds, linux-kernel

Tried out the ia64 bits. They seem fine.

Acked-by: Tony Luck <tony.luck@intel.com>

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH] futex: cmpxchg_futex_value_locked API change
  2011-03-07  2:11 [PATCH] futex: cmpxchg_futex_value_locked API change Michel Lespinasse
                   ` (2 preceding siblings ...)
  2011-03-07 21:58 ` Luck, Tony
@ 2011-03-08 20:17 ` Thomas Gleixner
  2011-03-09 11:25   ` Michel Lespinasse
  2011-03-09 11:08 ` [PATCH] futex: cmpxchg_futex_value_locked API change Michal Simek
  2011-03-09 12:41 ` David Howells
  5 siblings, 1 reply; 42+ messages in thread
From: Thomas Gleixner @ 2011-03-08 20:17 UTC (permalink / raw)
  To: Michel Lespinasse
  Cc: Darren Hart, Ingo Molnar, Peter Zijlstra, Matt Turner,
	Russell King, David Howells, Tony Luck, Michal Simek,
	Ralf Baechle, James E.J. Bottomley, Benjamin Herrenschmidt,
	Martin Schwidefsky, Paul Mundt, David S. Miller, Chris Metcalf,
	Andrew Morton, Linus Torvalds, LKML

On Sun, 6 Mar 2011, Michel Lespinasse wrote:
> The cmpxchg_futex_value_locked API was funny in that it returned either
> the original, user-exposed futex value OR an error code such as -EFAULT.
> This was confusing at best, and could be a source of livelocks in places
> that retry the cmpxchg_futex_value_locked after trying to fix the issue
> by running fault_in_user_writeable().
> 
> This change makes the cmpxchg_futex_value_locked API more similar to the
> get_futex_value_locked one, returning an error code and updating the
> original value through a reference argument.

Ack.

>  static inline int
> -futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
> +futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
> +			      int oldval, int newval)

Can we please change the arguments to u32 while at it? The futex core
code uses u32 all over the place so those inlines should do the same.

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH] futex: cmpxchg_futex_value_locked API change
  2011-03-07  2:11 [PATCH] futex: cmpxchg_futex_value_locked API change Michel Lespinasse
                   ` (3 preceding siblings ...)
  2011-03-08 20:17 ` Thomas Gleixner
@ 2011-03-09 11:08 ` Michal Simek
  2011-03-09 12:41 ` David Howells
  5 siblings, 0 replies; 42+ messages in thread
From: Michal Simek @ 2011-03-09 11:08 UTC (permalink / raw)
  To: Michel Lespinasse
  Cc: Darren Hart, Thomas Gleixner, Ingo Molnar, Peter Zijlstra,
	Matt Turner, Russell King, David Howells, Tony Luck,
	Ralf Baechle, James E.J. Bottomley, Benjamin Herrenschmidt,
	Martin Schwidefsky, Paul Mundt, David S. Miller, Chris Metcalf,
	Andrew Morton, Linus Torvalds, linux-kernel

Michel Lespinasse wrote:
> Aplogies for the long CC list - as this proposal involves asm changes
> in many architectures, and I have only been able to test on x86,
> I have tried to include one maintainer from every arch so they can
> hopefully double check me. I do think I got all architectures right,
> but you can never be 100% sure...
> 
> ------------------------------------8<---------------------------------
> 
> The cmpxchg_futex_value_locked API was funny in that it returned either
> the original, user-exposed futex value OR an error code such as -EFAULT.
> This was confusing at best, and could be a source of livelocks in places
> that retry the cmpxchg_futex_value_locked after trying to fix the issue
> by running fault_in_user_writeable().
> 
> This change makes the cmpxchg_futex_value_locked API more similar to the
> get_futex_value_locked one, returning an error code and updating the
> original value through a reference argument.
> 
> Signed-off-by: Michel Lespinasse <walken@google.com>
> ---
>  arch/alpha/include/asm/futex.h      |   22 +++++++++-------
>  arch/arm/include/asm/futex.h        |   23 +++++++++--------
>  arch/frv/include/asm/futex.h        |    3 +-
>  arch/ia64/include/asm/futex.h       |    9 ++++--
>  arch/microblaze/include/asm/futex.h |   24 ++++++++++--------

For microblaze:
Tested-by: Michal Simek <monstr@monstr.eu>

M

-- 
Michal Simek, Ing. (M.Eng)
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel 2.6 Microblaze Linux - http://www.monstr.eu/fdt/
Microblaze U-BOOT custodian

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH] futex: cmpxchg_futex_value_locked API change
  2011-03-08 20:17 ` Thomas Gleixner
@ 2011-03-09 11:25   ` Michel Lespinasse
  2011-03-09 15:04     ` Thomas Gleixner
                       ` (3 more replies)
  0 siblings, 4 replies; 42+ messages in thread
From: Michel Lespinasse @ 2011-03-09 11:25 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Darren Hart, Ingo Molnar, Peter Zijlstra, Matt Turner,
	Russell King, David Howells, Tony Luck, Michal Simek,
	Ralf Baechle, James E.J. Bottomley, Benjamin Herrenschmidt,
	Martin Schwidefsky, Paul Mundt, David S. Miller, Chris Metcalf,
	Andrew Morton, Linus Torvalds, LKML

On Tue, Mar 08, 2011 at 09:17:11PM +0100, Thomas Gleixner wrote:
> On Sun, 6 Mar 2011, Michel Lespinasse wrote:
> > The cmpxchg_futex_value_locked API was funny in that it returned either
> > the original, user-exposed futex value OR an error code such as -EFAULT.
> > This was confusing at best, and could be a source of livelocks in places
> > that retry the cmpxchg_futex_value_locked after trying to fix the issue
> > by running fault_in_user_writeable().
> > 
> > This change makes the cmpxchg_futex_value_locked API more similar to the
> > get_futex_value_locked one, returning an error code and updating the
> > original value through a reference argument.
> 
> Ack.
> 
> >  static inline int
> > -futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
> > +futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
> > +			      int oldval, int newval)
> 
> Can we please change the arguments to u32 while at it? The futex core
> code uses u32 all over the place so those inlines should do the same.

All right. Attaching updated version of the diff. I also fixed the s390
issue reported by Martin Schwidefsky.

What's the proper path to check this in, could you send it towards
the -next tree so it gets more testing ?

--------------------------------------8<-------------------------------

The cmpxchg_futex_value_locked API was funny in that it returned either
the original, user-exposed futex value OR an error code such as -EFAULT.
This was confusing at best, and could be a source of livelocks in places
that retry the cmpxchg_futex_value_locked after trying to fix the issue
by running fault_in_user_writeable().

This change makes the cmpxchg_futex_value_locked API more similar to the
get_futex_value_locked one, returning an error code and updating the
original value through a reference argument.

Additionally, the futex pointer types have been changed to u32 * in both
futex_atomic_cmpxchg_inatomic and futex_atomic_op_inuser internal APIs
as suggested by Thomas Gleixner.

Signed-off-by: Michel Lespinasse <walken@google.com>
Acked-by: Chris Metcalf <cmetcalf@tilera.com>  (for tile)
Acked-by: Tony Luck <tony.luck@intel.com>  (for ia64)
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Michal Simek <monstr@monstr.eu>  (for microblaze)

---
 arch/alpha/include/asm/futex.h      |   29 ++++++++++++----------
 arch/arm/include/asm/futex.h        |   30 ++++++++++++----------
 arch/frv/include/asm/futex.h        |    5 ++-
 arch/frv/kernel/futex.c             |   14 +++++-----
 arch/ia64/include/asm/futex.h       |   15 +++++++----
 arch/microblaze/include/asm/futex.h |   31 +++++++++++++----------
 arch/mips/include/asm/futex.h       |   39 ++++++++++++++++-------------
 arch/parisc/include/asm/futex.h     |   24 +++++++++---------
 arch/powerpc/include/asm/futex.h    |   27 +++++++++++---------
 arch/s390/include/asm/futex.h       |   12 ++++----
 arch/s390/include/asm/uaccess.h     |    4 +-
 arch/s390/lib/uaccess.h             |    8 +++---
 arch/s390/lib/uaccess_pt.c          |   17 +++++++-----
 arch/s390/lib/uaccess_std.c         |    8 ++++--
 arch/sh/include/asm/futex-irq.h     |   24 +++++++++---------
 arch/sh/include/asm/futex.h         |   11 ++++----
 arch/sparc/include/asm/futex_64.h   |   20 +++++++++------
 arch/tile/include/asm/futex.h       |   27 ++++++++++----------
 arch/x86/include/asm/futex.h        |   22 +++++++++-------
 include/asm-generic/futex.h         |    7 +++--
 kernel/futex.c                      |   46 ++++++++++++----------------------
 21 files changed, 219 insertions(+), 201 deletions(-)

diff --git a/arch/alpha/include/asm/futex.h b/arch/alpha/include/asm/futex.h
index 945de22..e8a761a 100644
--- a/arch/alpha/include/asm/futex.h
+++ b/arch/alpha/include/asm/futex.h
@@ -29,7 +29,7 @@
 	:	"r" (uaddr), "r"(oparg)				\
 	:	"memory")
 
-static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -39,7 +39,7 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -81,21 +81,23 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
-	int prev, cmp;
+	int ret = 0, cmp;
+	u32 prev;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	__asm__ __volatile__ (
 		__ASM_SMP_MB
-	"1:	ldl_l	%0,0(%2)\n"
-	"	cmpeq	%0,%3,%1\n"
-	"	beq	%1,3f\n"
-	"	mov	%4,%1\n"
-	"2:	stl_c	%1,0(%2)\n"
-	"	beq	%1,4f\n"
+	"1:	ldl_l	%1,0(%3)\n"
+	"	cmpeq	%1,%4,%2\n"
+	"	beq	%2,3f\n"
+	"	mov	%5,%2\n"
+	"2:	stl_c	%2,0(%3)\n"
+	"	beq	%2,4f\n"
 	"3:	.subsection 2\n"
 	"4:	br	1b\n"
 	"	.previous\n"
@@ -105,11 +107,12 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
 	"	.long	2b-.\n"
 	"	lda	$31,3b-2b(%0)\n"
 	"	.previous\n"
-	:	"=&r"(prev), "=&r"(cmp)
+	:	"+r"(ret), "=&r"(prev), "=&r"(cmp)
 	:	"r"(uaddr), "r"((long)oldval), "r"(newval)
 	:	"memory");
 
-	return prev;
+	*uval = prev;
+	return ret;
 }
 
 #endif /* __KERNEL__ */
diff --git a/arch/arm/include/asm/futex.h b/arch/arm/include/asm/futex.h
index b33fe70..0e29d8e 100644
--- a/arch/arm/include/asm/futex.h
+++ b/arch/arm/include/asm/futex.h
@@ -35,7 +35,7 @@
 	: "cc", "memory")
 
 static inline int
-futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -46,7 +46,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();	/* implies preempt_disable() */
@@ -88,36 +88,38 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
-	int val;
+	int ret = 0;
+	u32 val;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
-	pagefault_disable();	/* implies preempt_disable() */
+	/* Note that preemption is disabled by futex_atomic_cmpxchg_inatomic
+	 * call sites. */
 
 	__asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n"
-	"1:	" T(ldr) "	%0, [%3]\n"
-	"	teq	%0, %1\n"
+	"1:	" T(ldr) "	%1, [%4]\n"
+	"	teq	%1, %2\n"
 	"	it	eq	@ explicit IT needed for the 2b label\n"
-	"2:	" T(streq) "	%2, [%3]\n"
+	"2:	" T(streq) "	%3, [%4]\n"
 	"3:\n"
 	"	.pushsection __ex_table,\"a\"\n"
 	"	.align	3\n"
 	"	.long	1b, 4f, 2b, 4f\n"
 	"	.popsection\n"
 	"	.pushsection .fixup,\"ax\"\n"
-	"4:	mov	%0, %4\n"
+	"4:	mov	%0, %5\n"
 	"	b	3b\n"
 	"	.popsection"
-	: "=&r" (val)
+	: "+r" (ret), "=&r" (val)
 	: "r" (oldval), "r" (newval), "r" (uaddr), "Ir" (-EFAULT)
 	: "cc", "memory");
 
-	pagefault_enable();	/* subsumes preempt_enable() */
-
-	return val;
+	*uval = val;
+	return ret;
 }
 
 #endif /* !SMP */
diff --git a/arch/frv/include/asm/futex.h b/arch/frv/include/asm/futex.h
index 08b3d1d..4bea27f 100644
--- a/arch/frv/include/asm/futex.h
+++ b/arch/frv/include/asm/futex.h
@@ -7,10 +7,11 @@
 #include <asm/errno.h>
 #include <asm/uaccess.h>
 
-extern int futex_atomic_op_inuser(int encoded_op, int __user *uaddr);
+extern int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr);
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
 	return -ENOSYS;
 }
diff --git a/arch/frv/kernel/futex.c b/arch/frv/kernel/futex.c
index 14f64b0..d155ca9 100644
--- a/arch/frv/kernel/futex.c
+++ b/arch/frv/kernel/futex.c
@@ -18,7 +18,7 @@
  * the various futex operations; MMU fault checking is ignored under no-MMU
  * conditions
  */
-static inline int atomic_futex_op_xchg_set(int oparg, int __user *uaddr, int *_oldval)
+static inline int atomic_futex_op_xchg_set(int oparg, u32 __user *uaddr, int *_oldval)
 {
 	int oldval, ret;
 
@@ -50,7 +50,7 @@ static inline int atomic_futex_op_xchg_set(int oparg, int __user *uaddr, int *_o
 	return ret;
 }
 
-static inline int atomic_futex_op_xchg_add(int oparg, int __user *uaddr, int *_oldval)
+static inline int atomic_futex_op_xchg_add(int oparg, u32 __user *uaddr, int *_oldval)
 {
 	int oldval, ret;
 
@@ -83,7 +83,7 @@ static inline int atomic_futex_op_xchg_add(int oparg, int __user *uaddr, int *_o
 	return ret;
 }
 
-static inline int atomic_futex_op_xchg_or(int oparg, int __user *uaddr, int *_oldval)
+static inline int atomic_futex_op_xchg_or(int oparg, u32 __user *uaddr, int *_oldval)
 {
 	int oldval, ret;
 
@@ -116,7 +116,7 @@ static inline int atomic_futex_op_xchg_or(int oparg, int __user *uaddr, int *_ol
 	return ret;
 }
 
-static inline int atomic_futex_op_xchg_and(int oparg, int __user *uaddr, int *_oldval)
+static inline int atomic_futex_op_xchg_and(int oparg, u32 __user *uaddr, int *_oldval)
 {
 	int oldval, ret;
 
@@ -149,7 +149,7 @@ static inline int atomic_futex_op_xchg_and(int oparg, int __user *uaddr, int *_o
 	return ret;
 }
 
-static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr, int *_oldval)
+static inline int atomic_futex_op_xchg_xor(int oparg, u32 __user *uaddr, int *_oldval)
 {
 	int oldval, ret;
 
@@ -186,7 +186,7 @@ static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr, int *_o
 /*
  * do the futex operations
  */
-int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -197,7 +197,7 @@ int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
diff --git a/arch/ia64/include/asm/futex.h b/arch/ia64/include/asm/futex.h
index c7f0f06..8428525 100644
--- a/arch/ia64/include/asm/futex.h
+++ b/arch/ia64/include/asm/futex.h
@@ -46,7 +46,7 @@ do {									\
 } while (0)
 
 static inline int
-futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -56,7 +56,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -100,23 +100,26 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	{
-		register unsigned long r8 __asm ("r8");
+		register unsigned long r8 __asm ("r8") = 0;
+		unsigned long prev;
 		__asm__ __volatile__(
 			"	mf;;					\n"
 			"	mov ar.ccv=%3;;				\n"
 			"[1:]	cmpxchg4.acq %0=[%1],%2,ar.ccv		\n"
 			"	.xdata4 \"__ex_table\", 1b-., 2f-.	\n"
 			"[2:]"
-			: "=r" (r8)
+			: "=r" (prev)
 			: "r" (uaddr), "r" (newval),
 			  "rO" ((long) (unsigned) oldval)
 			: "memory");
+		*uval = prev;
 		return r8;
 	}
 }
diff --git a/arch/microblaze/include/asm/futex.h b/arch/microblaze/include/asm/futex.h
index ad3fd61..b0526d2 100644
--- a/arch/microblaze/include/asm/futex.h
+++ b/arch/microblaze/include/asm/futex.h
@@ -29,7 +29,7 @@
 })
 
 static inline int
-futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -39,7 +39,7 @@ futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -94,31 +94,34 @@ futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
-	int prev, cmp;
+	int ret = 0, cmp;
+	u32 prev;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
-	__asm__ __volatile__ ("1:	lwx	%0, %2, r0;		\
-					cmp	%1, %0, %3;		\
-					beqi	%1, 3f;			\
-				2:	swx	%4, %2, r0;		\
-					addic	%1, r0, 0;		\
-					bnei	%1, 1b;			\
+	__asm__ __volatile__ ("1:	lwx	%1, %3, r0;		\
+					cmp	%2, %1, %4;		\
+					beqi	%2, 3f;			\
+				2:	swx	%5, %3, r0;		\
+					addic	%2, r0, 0;		\
+					bnei	%2, 1b;			\
 				3:					\
 				.section .fixup,\"ax\";			\
 				4:	brid	3b;			\
-					addik	%0, r0, %5;		\
+					addik	%0, r0, %6;		\
 				.previous;				\
 				.section __ex_table,\"a\";		\
 				.word	1b,4b,2b,4b;			\
 				.previous;"				\
-		: "=&r" (prev), "=&r"(cmp)				\
+		: "+r" (ret), "=&r" (prev), "=&r"(cmp)	\
 		: "r" (uaddr), "r" (oldval), "r" (newval), "i" (-EFAULT));
 
-	return prev;
+	*uval = prev;
+	return ret;
 }
 
 #endif /* __KERNEL__ */
diff --git a/arch/mips/include/asm/futex.h b/arch/mips/include/asm/futex.h
index b9cce90..6ebf173 100644
--- a/arch/mips/include/asm/futex.h
+++ b/arch/mips/include/asm/futex.h
@@ -75,7 +75,7 @@
 }
 
 static inline int
-futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -85,7 +85,7 @@ futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -132,11 +132,13 @@ futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
-	int retval;
+	int ret = 0;
+	u32 val;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	if (cpu_has_llsc && R10000_LLSC_WAR) {
@@ -145,25 +147,25 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
 		"	.set	push					\n"
 		"	.set	noat					\n"
 		"	.set	mips3					\n"
-		"1:	ll	%0, %2					\n"
-		"	bne	%0, %z3, 3f				\n"
+		"1:	ll	%1, %3					\n"
+		"	bne	%1, %z4, 3f				\n"
 		"	.set	mips0					\n"
-		"	move	$1, %z4					\n"
+		"	move	$1, %z5					\n"
 		"	.set	mips3					\n"
-		"2:	sc	$1, %1					\n"
+		"2:	sc	$1, %2					\n"
 		"	beqzl	$1, 1b					\n"
 		__WEAK_LLSC_MB
 		"3:							\n"
 		"	.set	pop					\n"
 		"	.section .fixup,\"ax\"				\n"
-		"4:	li	%0, %5					\n"
+		"4:	li	%0, %6					\n"
 		"	j	3b					\n"
 		"	.previous					\n"
 		"	.section __ex_table,\"a\"			\n"
 		"	"__UA_ADDR "\t1b, 4b				\n"
 		"	"__UA_ADDR "\t2b, 4b				\n"
 		"	.previous					\n"
-		: "=&r" (retval), "=R" (*uaddr)
+		: "+r" (ret), "=&r" (val), "=R" (*uaddr)
 		: "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT)
 		: "memory");
 	} else if (cpu_has_llsc) {
@@ -172,31 +174,32 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
 		"	.set	push					\n"
 		"	.set	noat					\n"
 		"	.set	mips3					\n"
-		"1:	ll	%0, %2					\n"
-		"	bne	%0, %z3, 3f				\n"
+		"1:	ll	%1, %3					\n"
+		"	bne	%1, %z4, 3f				\n"
 		"	.set	mips0					\n"
-		"	move	$1, %z4					\n"
+		"	move	$1, %z5					\n"
 		"	.set	mips3					\n"
-		"2:	sc	$1, %1					\n"
+		"2:	sc	$1, %2					\n"
 		"	beqz	$1, 1b					\n"
 		__WEAK_LLSC_MB
 		"3:							\n"
 		"	.set	pop					\n"
 		"	.section .fixup,\"ax\"				\n"
-		"4:	li	%0, %5					\n"
+		"4:	li	%0, %6					\n"
 		"	j	3b					\n"
 		"	.previous					\n"
 		"	.section __ex_table,\"a\"			\n"
 		"	"__UA_ADDR "\t1b, 4b				\n"
 		"	"__UA_ADDR "\t2b, 4b				\n"
 		"	.previous					\n"
-		: "=&r" (retval), "=R" (*uaddr)
+		: "+r" (ret), "=&r" (val), "=R" (*uaddr)
 		: "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT)
 		: "memory");
 	} else
 		return -ENOSYS;
 
-	return retval;
+	*uval = val;
+	return ret;
 }
 
 #endif
diff --git a/arch/parisc/include/asm/futex.h b/arch/parisc/include/asm/futex.h
index 0c705c3..67a33cc 100644
--- a/arch/parisc/include/asm/futex.h
+++ b/arch/parisc/include/asm/futex.h
@@ -8,7 +8,7 @@
 #include <asm/errno.h>
 
 static inline int
-futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -18,7 +18,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -51,10 +51,10 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 
 /* Non-atomic version */
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
-	int err = 0;
-	int uval;
+	u32 val;
 
 	/* futex.c wants to do a cmpxchg_inatomic on kernel NULL, which is
 	 * our gateway page, and causes no end of trouble...
@@ -62,15 +62,15 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
 	if (segment_eq(KERNEL_DS, get_fs()) && !uaddr)
 		return -EFAULT;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
-	err = get_user(uval, uaddr);
-	if (err) return -EFAULT;
-	if (uval == oldval)
-		err = put_user(newval, uaddr);
-	if (err) return -EFAULT;
-	return uval;
+	if (get_user(val, uaddr))
+		return -EFAULT;
+	if (val == oldval && put_user(newval, uaddr))
+		return -EFAULT;
+	*uval = val;
+	return 0;
 }
 
 #endif /*__KERNEL__*/
diff --git a/arch/powerpc/include/asm/futex.h b/arch/powerpc/include/asm/futex.h
index 7c589ef..c94e4a3 100644
--- a/arch/powerpc/include/asm/futex.h
+++ b/arch/powerpc/include/asm/futex.h
@@ -30,7 +30,7 @@
 	: "b" (uaddr), "i" (-EFAULT), "r" (oparg) \
 	: "cr0", "memory")
 
-static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -40,7 +40,7 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -82,35 +82,38 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
-	int prev;
+	int ret = 0;
+	u32 prev;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
         __asm__ __volatile__ (
         PPC_RELEASE_BARRIER
-"1:     lwarx   %0,0,%2         # futex_atomic_cmpxchg_inatomic\n\
-        cmpw    0,%0,%3\n\
+"1:     lwarx   %1,0,%3         # futex_atomic_cmpxchg_inatomic\n\
+        cmpw    0,%1,%4\n\
         bne-    3f\n"
-        PPC405_ERR77(0,%2)
-"2:     stwcx.  %4,0,%2\n\
+        PPC405_ERR77(0,%3)
+"2:     stwcx.  %5,0,%3\n\
         bne-    1b\n"
         PPC_ACQUIRE_BARRIER
 "3:	.section .fixup,\"ax\"\n\
-4:	li	%0,%5\n\
+4:	li	%0,%6\n\
 	b	3b\n\
 	.previous\n\
 	.section __ex_table,\"a\"\n\
 	.align 3\n\
 	" PPC_LONG "1b,4b,2b,4b\n\
 	.previous" \
-        : "=&r" (prev), "+m" (*uaddr)
+        : "+r" (ret), "=&r" (prev), "+m" (*uaddr)
         : "r" (uaddr), "r" (oldval), "r" (newval), "i" (-EFAULT)
         : "cc", "memory");
 
-        return prev;
+	*uval = prev;
+        return ret;
 }
 
 #endif /* __KERNEL__ */
diff --git a/arch/s390/include/asm/futex.h b/arch/s390/include/asm/futex.h
index 5c5d02d..81cf36b 100644
--- a/arch/s390/include/asm/futex.h
+++ b/arch/s390/include/asm/futex.h
@@ -7,7 +7,7 @@
 #include <linux/uaccess.h>
 #include <asm/errno.h>
 
-static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -18,7 +18,7 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -39,13 +39,13 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 	return ret;
 }
 
-static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr,
-						int oldval, int newval)
+static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+						u32 oldval, u32 newval)
 {
-	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
-	return uaccess.futex_atomic_cmpxchg(uaddr, oldval, newval);
+	return uaccess.futex_atomic_cmpxchg(uval, uaddr, oldval, newval);
 }
 
 #endif /* __KERNEL__ */
diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h
index d6b1ed0..2d9ea11f 100644
--- a/arch/s390/include/asm/uaccess.h
+++ b/arch/s390/include/asm/uaccess.h
@@ -83,8 +83,8 @@ struct uaccess_ops {
 	size_t (*clear_user)(size_t, void __user *);
 	size_t (*strnlen_user)(size_t, const char __user *);
 	size_t (*strncpy_from_user)(size_t, const char __user *, char *);
-	int (*futex_atomic_op)(int op, int __user *, int oparg, int *old);
-	int (*futex_atomic_cmpxchg)(int __user *, int old, int new);
+	int (*futex_atomic_op)(int op, u32 __user *, int oparg, int *old);
+	int (*futex_atomic_cmpxchg)(u32 *, u32 __user *, u32 old, u32 new);
 };
 
 extern struct uaccess_ops uaccess;
diff --git a/arch/s390/lib/uaccess.h b/arch/s390/lib/uaccess.h
index 126011d..1d2536c 100644
--- a/arch/s390/lib/uaccess.h
+++ b/arch/s390/lib/uaccess.h
@@ -12,12 +12,12 @@ extern size_t copy_from_user_std(size_t, const void __user *, void *);
 extern size_t copy_to_user_std(size_t, void __user *, const void *);
 extern size_t strnlen_user_std(size_t, const char __user *);
 extern size_t strncpy_from_user_std(size_t, const char __user *, char *);
-extern int futex_atomic_cmpxchg_std(int __user *, int, int);
-extern int futex_atomic_op_std(int, int __user *, int, int *);
+extern int futex_atomic_cmpxchg_std(u32 *, u32 __user *, u32, u32);
+extern int futex_atomic_op_std(int, u32 __user *, int, int *);
 
 extern size_t copy_from_user_pt(size_t, const void __user *, void *);
 extern size_t copy_to_user_pt(size_t, void __user *, const void *);
-extern int futex_atomic_op_pt(int, int __user *, int, int *);
-extern int futex_atomic_cmpxchg_pt(int __user *, int, int);
+extern int futex_atomic_op_pt(int, u32 __user *, int, int *);
+extern int futex_atomic_cmpxchg_pt(u32 *, u32 __user *, u32, u32);
 
 #endif /* __ARCH_S390_LIB_UACCESS_H */
diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c
index 404f2de..afc716a 100644
--- a/arch/s390/lib/uaccess_pt.c
+++ b/arch/s390/lib/uaccess_pt.c
@@ -302,7 +302,7 @@ fault:
 		     : "0" (-EFAULT), "d" (oparg), "a" (uaddr),		\
 		       "m" (*uaddr) : "cc" );
 
-static int __futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old)
+static int __futex_atomic_op_pt(int op, u32 __user *uaddr, int oparg, int *old)
 {
 	int oldval = 0, newval, ret;
 
@@ -335,7 +335,7 @@ static int __futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old)
 	return ret;
 }
 
-int futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old)
+int futex_atomic_op_pt(int op, u32 __user *uaddr, int oparg, int *old)
 {
 	int ret;
 
@@ -354,26 +354,29 @@ int futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old)
 	return ret;
 }
 
-static int __futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval)
+static int __futex_atomic_cmpxchg_pt(u32 *uval, u32 __user *uaddr,
+				     u32 oldval, u32 newval)
 {
 	int ret;
 
 	asm volatile("0: cs   %1,%4,0(%5)\n"
-		     "1: lr   %0,%1\n"
+		     "1: la   %0,0\n"
 		     "2:\n"
 		     EX_TABLE(0b,2b) EX_TABLE(1b,2b)
 		     : "=d" (ret), "+d" (oldval), "=m" (*uaddr)
 		     : "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr)
 		     : "cc", "memory" );
+	*uval = oldval;
 	return ret;
 }
 
-int futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval)
+int futex_atomic_cmpxchg_pt(int *uval, int __user *uaddr,
+			    int oldval, int newval)
 {
 	int ret;
 
 	if (segment_eq(get_fs(), KERNEL_DS))
-		return __futex_atomic_cmpxchg_pt(uaddr, oldval, newval);
+		return __futex_atomic_cmpxchg_pt(uval, uaddr, oldval, newval);
 	spin_lock(&current->mm->page_table_lock);
 	uaddr = (int __user *) __dat_user_addr((unsigned long) uaddr);
 	if (!uaddr) {
@@ -382,7 +385,7 @@ int futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval)
 	}
 	get_page(virt_to_page(uaddr));
 	spin_unlock(&current->mm->page_table_lock);
-	ret = __futex_atomic_cmpxchg_pt(uaddr, oldval, newval);
+	ret = __futex_atomic_cmpxchg_pt(uval, uaddr, oldval, newval);
 	put_page(virt_to_page(uaddr));
 	return ret;
 }
diff --git a/arch/s390/lib/uaccess_std.c b/arch/s390/lib/uaccess_std.c
index a6c4f7e..bb1a7ee 100644
--- a/arch/s390/lib/uaccess_std.c
+++ b/arch/s390/lib/uaccess_std.c
@@ -255,7 +255,7 @@ size_t strncpy_from_user_std(size_t size, const char __user *src, char *dst)
 		: "0" (-EFAULT), "d" (oparg), "a" (uaddr),		\
 		  "m" (*uaddr) : "cc");
 
-int futex_atomic_op_std(int op, int __user *uaddr, int oparg, int *old)
+int futex_atomic_op_std(int op, u32 __user *uaddr, int oparg, int *old)
 {
 	int oldval = 0, newval, ret;
 
@@ -287,19 +287,21 @@ int futex_atomic_op_std(int op, int __user *uaddr, int oparg, int *old)
 	return ret;
 }
 
-int futex_atomic_cmpxchg_std(int __user *uaddr, int oldval, int newval)
+int futex_atomic_cmpxchg_std(u32 *uval, u32 __user *uaddr,
+			     u32 oldval, u32 newval)
 {
 	int ret;
 
 	asm volatile(
 		"   sacf 256\n"
 		"0: cs   %1,%4,0(%5)\n"
-		"1: lr   %0,%1\n"
+		"1: la   %0,0\n"
 		"2: sacf 0\n"
 		EX_TABLE(0b,2b) EX_TABLE(1b,2b)
 		: "=d" (ret), "+d" (oldval), "=m" (*uaddr)
 		: "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr)
 		: "cc", "memory" );
+	*uval = oldval;
 	return ret;
 }
 
diff --git a/arch/sh/include/asm/futex-irq.h b/arch/sh/include/asm/futex-irq.h
index a9f16a7..6cb9f19 100644
--- a/arch/sh/include/asm/futex-irq.h
+++ b/arch/sh/include/asm/futex-irq.h
@@ -3,7 +3,7 @@
 
 #include <asm/system.h>
 
-static inline int atomic_futex_op_xchg_set(int oparg, int __user *uaddr,
+static inline int atomic_futex_op_xchg_set(int oparg, u32 __user *uaddr,
 					   int *oldval)
 {
 	unsigned long flags;
@@ -20,7 +20,7 @@ static inline int atomic_futex_op_xchg_set(int oparg, int __user *uaddr,
 	return ret;
 }
 
-static inline int atomic_futex_op_xchg_add(int oparg, int __user *uaddr,
+static inline int atomic_futex_op_xchg_add(int oparg, u32 __user *uaddr,
 					   int *oldval)
 {
 	unsigned long flags;
@@ -37,7 +37,7 @@ static inline int atomic_futex_op_xchg_add(int oparg, int __user *uaddr,
 	return ret;
 }
 
-static inline int atomic_futex_op_xchg_or(int oparg, int __user *uaddr,
+static inline int atomic_futex_op_xchg_or(int oparg, u32 __user *uaddr,
 					  int *oldval)
 {
 	unsigned long flags;
@@ -54,7 +54,7 @@ static inline int atomic_futex_op_xchg_or(int oparg, int __user *uaddr,
 	return ret;
 }
 
-static inline int atomic_futex_op_xchg_and(int oparg, int __user *uaddr,
+static inline int atomic_futex_op_xchg_and(int oparg, u32 __user *uaddr,
 					   int *oldval)
 {
 	unsigned long flags;
@@ -71,7 +71,7 @@ static inline int atomic_futex_op_xchg_and(int oparg, int __user *uaddr,
 	return ret;
 }
 
-static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr,
+static inline int atomic_futex_op_xchg_xor(int oparg, u32 __user *uaddr,
 					   int *oldval)
 {
 	unsigned long flags;
@@ -88,11 +88,13 @@ static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr,
 	return ret;
 }
 
-static inline int atomic_futex_op_cmpxchg_inatomic(int __user *uaddr,
-						   int oldval, int newval)
+static inline int atomic_futex_op_cmpxchg_inatomic(u32 *uval,
+						   u32 __user *uaddr,
+						   u32 oldval, u32 newval)
 {
 	unsigned long flags;
-	int ret, prev = 0;
+	int ret;
+	u32 prev = 0;
 
 	local_irq_save(flags);
 
@@ -102,10 +104,8 @@ static inline int atomic_futex_op_cmpxchg_inatomic(int __user *uaddr,
 
 	local_irq_restore(flags);
 
-	if (ret)
-		return ret;
-
-	return prev;
+	*uval = prev;
+	return ret;
 }
 
 #endif /* __ASM_SH_FUTEX_IRQ_H */
diff --git a/arch/sh/include/asm/futex.h b/arch/sh/include/asm/futex.h
index 68256ec..7be39a6 100644
--- a/arch/sh/include/asm/futex.h
+++ b/arch/sh/include/asm/futex.h
@@ -10,7 +10,7 @@
 /* XXX: UP variants, fix for SH-4A and SMP.. */
 #include <asm/futex-irq.h>
 
-static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -21,7 +21,7 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -65,12 +65,13 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
-	return atomic_futex_op_cmpxchg_inatomic(uaddr, oldval, newval);
+	return atomic_futex_op_cmpxchg_inatomic(uval, uaddr, oldval, newval);
 }
 
 #endif /* __KERNEL__ */
diff --git a/arch/sparc/include/asm/futex_64.h b/arch/sparc/include/asm/futex_64.h
index 47f9583..444e7be 100644
--- a/arch/sparc/include/asm/futex_64.h
+++ b/arch/sparc/include/asm/futex_64.h
@@ -30,7 +30,7 @@
 	: "r" (uaddr), "r" (oparg), "i" (-EFAULT)	\
 	: "memory")
 
-static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -38,7 +38,7 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 	int cmparg = (encoded_op << 20) >> 20;
 	int oldval = 0, ret, tem;
 
-	if (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(int))))
+	if (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))))
 		return -EFAULT;
 	if (unlikely((((unsigned long) uaddr) & 0x3UL)))
 		return -EINVAL;
@@ -85,26 +85,30 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
+	int ret = 0;
+
 	__asm__ __volatile__(
-	"\n1:	casa	[%3] %%asi, %2, %0\n"
+	"\n1:	casa	[%4] %%asi, %3, %1\n"
 	"2:\n"
 	"	.section .fixup,#alloc,#execinstr\n"
 	"	.align	4\n"
 	"3:	sethi	%%hi(2b), %0\n"
 	"	jmpl	%0 + %%lo(2b), %%g0\n"
-	"	 mov	%4, %0\n"
+	"	mov	%5, %0\n"
 	"	.previous\n"
 	"	.section __ex_table,\"a\"\n"
 	"	.align	4\n"
 	"	.word	1b, 3b\n"
 	"	.previous\n"
-	: "=r" (newval)
-	: "0" (newval), "r" (oldval), "r" (uaddr), "i" (-EFAULT)
+	: "+r" (ret), "=r" (newval)
+	: "1" (newval), "r" (oldval), "r" (uaddr), "i" (-EFAULT)
 	: "memory");
 
-	return newval;
+	*uval = newval;
+	return ret;
 }
 
 #endif /* !(_SPARC64_FUTEX_H) */
diff --git a/arch/tile/include/asm/futex.h b/arch/tile/include/asm/futex.h
index fe0d10d..d03ec12 100644
--- a/arch/tile/include/asm/futex.h
+++ b/arch/tile/include/asm/futex.h
@@ -29,16 +29,16 @@
 #include <linux/uaccess.h>
 #include <linux/errno.h>
 
-extern struct __get_user futex_set(int __user *v, int i);
-extern struct __get_user futex_add(int __user *v, int n);
-extern struct __get_user futex_or(int __user *v, int n);
-extern struct __get_user futex_andn(int __user *v, int n);
-extern struct __get_user futex_cmpxchg(int __user *v, int o, int n);
+extern struct __get_user futex_set(u32 __user *v, int i);
+extern struct __get_user futex_add(u32 __user *v, int n);
+extern struct __get_user futex_or(u32 __user *v, int n);
+extern struct __get_user futex_andn(u32 __user *v, int n);
+extern struct __get_user futex_cmpxchg(u32 __user *v, int o, int n);
 
 #ifndef __tilegx__
-extern struct __get_user futex_xor(int __user *v, int n);
+extern struct __get_user futex_xor(u32 __user *v, int n);
 #else
-static inline struct __get_user futex_xor(int __user *uaddr, int n)
+static inline struct __get_user futex_xor(u32 __user *uaddr, int n)
 {
 	struct __get_user asm_ret = __get_user_4(uaddr);
 	if (!asm_ret.err) {
@@ -53,7 +53,7 @@ static inline struct __get_user futex_xor(int __user *uaddr, int n)
 }
 #endif
 
-static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -65,7 +65,7 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -119,16 +119,17 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 	return ret;
 }
 
-static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval,
-						int newval)
+static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+						u32 oldval, u32 newval)
 {
 	struct __get_user asm_ret;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	asm_ret = futex_cmpxchg(uaddr, oldval, newval);
-	return asm_ret.err ? asm_ret.err : asm_ret.val;
+	*uval = asm_ret.val;
+	return asm_ret.err;
 }
 
 #ifndef __tilegx__
diff --git a/arch/x86/include/asm/futex.h b/arch/x86/include/asm/futex.h
index 1f11ce4..d09bb03 100644
--- a/arch/x86/include/asm/futex.h
+++ b/arch/x86/include/asm/futex.h
@@ -37,7 +37,7 @@
 		       "+m" (*uaddr), "=&r" (tem)		\
 		     : "r" (oparg), "i" (-EFAULT), "1" (0))
 
-static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -48,7 +48,7 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 #if defined(CONFIG_X86_32) && !defined(CONFIG_X86_BSWAP)
@@ -109,9 +109,10 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 	return ret;
 }
 
-static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval,
-						int newval)
+static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+						u32 oldval, u32 newval)
 {
+	int ret = 0;
 
 #if defined(CONFIG_X86_32) && !defined(CONFIG_X86_BSWAP)
 	/* Real i386 machines have no cmpxchg instruction */
@@ -119,21 +120,22 @@ static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval,
 		return -ENOSYS;
 #endif
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
-	asm volatile("1:\t" LOCK_PREFIX "cmpxchgl %3, %1\n"
+	asm volatile("1:\t" LOCK_PREFIX "cmpxchgl %4, %2\n"
 		     "2:\t.section .fixup, \"ax\"\n"
-		     "3:\tmov     %2, %0\n"
+		     "3:\tmov     %3, %0\n"
 		     "\tjmp     2b\n"
 		     "\t.previous\n"
 		     _ASM_EXTABLE(1b, 3b)
-		     : "=a" (oldval), "+m" (*uaddr)
-		     : "i" (-EFAULT), "r" (newval), "0" (oldval)
+		     : "+r" (ret), "=a" (oldval), "+m" (*uaddr)
+		     : "i" (-EFAULT), "r" (newval), "1" (oldval)
 		     : "memory"
 	);
 
-	return oldval;
+	*uval = oldval;
+	return ret;
 }
 
 #endif
diff --git a/include/asm-generic/futex.h b/include/asm-generic/futex.h
index 3c2344f..01f227e 100644
--- a/include/asm-generic/futex.h
+++ b/include/asm-generic/futex.h
@@ -6,7 +6,7 @@
 #include <asm/errno.h>
 
 static inline int
-futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -16,7 +16,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -48,7 +48,8 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
 	return -ENOSYS;
 }
diff --git a/kernel/futex.c b/kernel/futex.c
index 3184d3b..53b783f 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -381,15 +381,16 @@ static struct futex_q *futex_top_waiter(struct futex_hash_bucket *hb,
 	return NULL;
 }
 
-static u32 cmpxchg_futex_value_locked(u32 __user *uaddr, u32 uval, u32 newval)
+static int cmpxchg_futex_value_locked(u32 *curval, u32 __user *uaddr,
+				      u32 uval, u32 newval)
 {
-	u32 curval;
+	int ret;
 
 	pagefault_disable();
-	curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval);
+	ret = futex_atomic_cmpxchg_inatomic(curval, uaddr, uval, newval);
 	pagefault_enable();
 
-	return curval;
+	return ret;
 }
 
 static int get_futex_value_locked(u32 *dest, u32 __user *from)
@@ -688,9 +689,7 @@ retry:
 	if (set_waiters)
 		newval |= FUTEX_WAITERS;
 
-	curval = cmpxchg_futex_value_locked(uaddr, 0, newval);
-
-	if (unlikely(curval == -EFAULT))
+	if (unlikely(cmpxchg_futex_value_locked(&curval, uaddr, 0, newval)))
 		return -EFAULT;
 
 	/*
@@ -728,9 +727,7 @@ retry:
 		lock_taken = 1;
 	}
 
-	curval = cmpxchg_futex_value_locked(uaddr, uval, newval);
-
-	if (unlikely(curval == -EFAULT))
+	if (unlikely(cmpxchg_futex_value_locked(&curval, uaddr, uval, newval)))
 		return -EFAULT;
 	if (unlikely(curval != uval))
 		goto retry;
@@ -843,9 +840,7 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this)
 
 		newval = FUTEX_WAITERS | task_pid_vnr(new_owner);
 
-		curval = cmpxchg_futex_value_locked(uaddr, uval, newval);
-
-		if (curval == -EFAULT)
+		if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval))
 			ret = -EFAULT;
 		else if (curval != uval)
 			ret = -EINVAL;
@@ -880,10 +875,8 @@ static int unlock_futex_pi(u32 __user *uaddr, u32 uval)
 	 * There is no waiter, so we unlock the futex. The owner died
 	 * bit has not to be preserved here. We are the owner:
 	 */
-	oldval = cmpxchg_futex_value_locked(uaddr, uval, 0);
-
-	if (oldval == -EFAULT)
-		return oldval;
+	if (cmpxchg_futex_value_locked(&oldval, uaddr, uval, 0))
+		return -EFAULT;
 	if (oldval != uval)
 		return -EAGAIN;
 
@@ -1578,9 +1571,7 @@ retry:
 	while (1) {
 		newval = (uval & FUTEX_OWNER_DIED) | newtid;
 
-		curval = cmpxchg_futex_value_locked(uaddr, uval, newval);
-
-		if (curval == -EFAULT)
+		if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval))
 			goto handle_fault;
 		if (curval == uval)
 			break;
@@ -2073,11 +2064,9 @@ retry:
 	 * again. If it succeeds then we can return without waking
 	 * anyone else up:
 	 */
-	if (!(uval & FUTEX_OWNER_DIED))
-		uval = cmpxchg_futex_value_locked(uaddr, task_pid_vnr(current), 0);
-
-
-	if (unlikely(uval == -EFAULT))
+	if (!(uval & FUTEX_OWNER_DIED) &&
+	    unlikely(cmpxchg_futex_value_locked(&uval, uaddr,
+						task_pid_vnr(current), 0)))
 		goto pi_faulted;
 	/*
 	 * Rare case: we managed to release the lock atomically,
@@ -2464,9 +2453,7 @@ retry:
 		 * userspace.
 		 */
 		mval = (uval & FUTEX_WAITERS) | FUTEX_OWNER_DIED;
-		nval = futex_atomic_cmpxchg_inatomic(uaddr, uval, mval);
-
-		if (nval == -EFAULT)
+		if (futex_atomic_cmpxchg_inatomic(&nval, uaddr, uval, mval))
 			return -1;
 
 		if (nval != uval)
@@ -2679,8 +2666,7 @@ static int __init futex_init(void)
 	 * implementation, the non-functional ones will return
 	 * -ENOSYS.
 	 */
-	curval = cmpxchg_futex_value_locked(NULL, 0, 0);
-	if (curval == -EFAULT)
+	if (cmpxchg_futex_value_locked(&curval, NULL, 0, 0) == -EFAULT)
 		futex_cmpxchg_enabled = 1;
 
 	for (i = 0; i < ARRAY_SIZE(futex_queues); i++) {


-- 
Michel "Walken" Lespinasse
A program is never fully debugged until the last user dies.

^ permalink raw reply related	[flat|nested] 42+ messages in thread

* Re: [PATCH] futex: cmpxchg_futex_value_locked API change
  2011-03-07  2:11 [PATCH] futex: cmpxchg_futex_value_locked API change Michel Lespinasse
                   ` (4 preceding siblings ...)
  2011-03-09 11:08 ` [PATCH] futex: cmpxchg_futex_value_locked API change Michal Simek
@ 2011-03-09 12:41 ` David Howells
  5 siblings, 0 replies; 42+ messages in thread
From: David Howells @ 2011-03-09 12:41 UTC (permalink / raw)
  To: Michel Lespinasse
  Cc: dhowells, Darren Hart, Thomas Gleixner, Ingo Molnar,
	Peter Zijlstra, Matt Turner, Russell King, Tony Luck,
	Michal Simek, Ralf Baechle, James E.J. Bottomley,
	Benjamin Herrenschmidt, Martin Schwidefsky, Paul Mundt,
	David S. Miller, Chris Metcalf, Andrew Morton, Linus Torvalds,
	linux-kernel

Michel Lespinasse <walken@google.com> wrote:

> The cmpxchg_futex_value_locked API was funny in that it returned either
> the original, user-exposed futex value OR an error code such as -EFAULT.
> This was confusing at best, and could be a source of livelocks in places
> that retry the cmpxchg_futex_value_locked after trying to fix the issue
> by running fault_in_user_writeable().
> 
> This change makes the cmpxchg_futex_value_locked API more similar to the
> get_futex_value_locked one, returning an error code and updating the
> original value through a reference argument.
> 
> Signed-off-by: Michel Lespinasse <walken@google.com>

Acked-by: David Howells <dhowells@redhat.com> [FRV]

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH] futex: cmpxchg_futex_value_locked API change
  2011-03-09 11:25   ` Michel Lespinasse
@ 2011-03-09 15:04     ` Thomas Gleixner
  2011-03-09 15:08     ` Martin Schwidefsky
                       ` (2 subsequent siblings)
  3 siblings, 0 replies; 42+ messages in thread
From: Thomas Gleixner @ 2011-03-09 15:04 UTC (permalink / raw)
  To: Michel Lespinasse
  Cc: Darren Hart, Ingo Molnar, Peter Zijlstra, Matt Turner,
	Russell King, David Howells, Tony Luck, Michal Simek,
	Ralf Baechle, James E.J. Bottomley, Benjamin Herrenschmidt,
	Martin Schwidefsky, Paul Mundt, David S. Miller, Chris Metcalf,
	Andrew Morton, Linus Torvalds, LKML

On Wed, 9 Mar 2011, Michel Lespinasse wrote:

> On Tue, Mar 08, 2011 at 09:17:11PM +0100, Thomas Gleixner wrote:
> > On Sun, 6 Mar 2011, Michel Lespinasse wrote:
> > > The cmpxchg_futex_value_locked API was funny in that it returned either
> > > the original, user-exposed futex value OR an error code such as -EFAULT.
> > > This was confusing at best, and could be a source of livelocks in places
> > > that retry the cmpxchg_futex_value_locked after trying to fix the issue
> > > by running fault_in_user_writeable().
> > > 
> > > This change makes the cmpxchg_futex_value_locked API more similar to the
> > > get_futex_value_locked one, returning an error code and updating the
> > > original value through a reference argument.
> > 
> > Ack.
> > 
> > >  static inline int
> > > -futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
> > > +futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
> > > +			      int oldval, int newval)
> > 
> > Can we please change the arguments to u32 while at it? The futex core
> > code uses u32 all over the place so those inlines should do the same.
> 
> All right. Attaching updated version of the diff. I also fixed the s390
> issue reported by Martin Schwidefsky.
> 
> What's the proper path to check this in, could you send it towards
> the -next tree so it gets more testing ?

I'll pick it up and wait what explodes :)

Thanks,

	tglx

> --------------------------------------8<-------------------------------
> 
> The cmpxchg_futex_value_locked API was funny in that it returned either
> the original, user-exposed futex value OR an error code such as -EFAULT.
> This was confusing at best, and could be a source of livelocks in places
> that retry the cmpxchg_futex_value_locked after trying to fix the issue
> by running fault_in_user_writeable().
> 
> This change makes the cmpxchg_futex_value_locked API more similar to the
> get_futex_value_locked one, returning an error code and updating the
> original value through a reference argument.
> 
> Additionally, the futex pointer types have been changed to u32 * in both
> futex_atomic_cmpxchg_inatomic and futex_atomic_op_inuser internal APIs
> as suggested by Thomas Gleixner.
> 
> Signed-off-by: Michel Lespinasse <walken@google.com>
> Acked-by: Chris Metcalf <cmetcalf@tilera.com>  (for tile)
> Acked-by: Tony Luck <tony.luck@intel.com>  (for ia64)
> Acked-by: Thomas Gleixner <tglx@linutronix.de>
> Tested-by: Michal Simek <monstr@monstr.eu>  (for microblaze)
> 
> ---
>  arch/alpha/include/asm/futex.h      |   29 ++++++++++++----------
>  arch/arm/include/asm/futex.h        |   30 ++++++++++++----------
>  arch/frv/include/asm/futex.h        |    5 ++-
>  arch/frv/kernel/futex.c             |   14 +++++-----
>  arch/ia64/include/asm/futex.h       |   15 +++++++----
>  arch/microblaze/include/asm/futex.h |   31 +++++++++++++----------
>  arch/mips/include/asm/futex.h       |   39 ++++++++++++++++-------------
>  arch/parisc/include/asm/futex.h     |   24 +++++++++---------
>  arch/powerpc/include/asm/futex.h    |   27 +++++++++++---------
>  arch/s390/include/asm/futex.h       |   12 ++++----
>  arch/s390/include/asm/uaccess.h     |    4 +-
>  arch/s390/lib/uaccess.h             |    8 +++---
>  arch/s390/lib/uaccess_pt.c          |   17 +++++++-----
>  arch/s390/lib/uaccess_std.c         |    8 ++++--
>  arch/sh/include/asm/futex-irq.h     |   24 +++++++++---------
>  arch/sh/include/asm/futex.h         |   11 ++++----
>  arch/sparc/include/asm/futex_64.h   |   20 +++++++++------
>  arch/tile/include/asm/futex.h       |   27 ++++++++++----------
>  arch/x86/include/asm/futex.h        |   22 +++++++++-------
>  include/asm-generic/futex.h         |    7 +++--
>  kernel/futex.c                      |   46 ++++++++++++----------------------
>  21 files changed, 219 insertions(+), 201 deletions(-)
> 
> diff --git a/arch/alpha/include/asm/futex.h b/arch/alpha/include/asm/futex.h
> index 945de22..e8a761a 100644
> --- a/arch/alpha/include/asm/futex.h
> +++ b/arch/alpha/include/asm/futex.h
> @@ -29,7 +29,7 @@
>  	:	"r" (uaddr), "r"(oparg)				\
>  	:	"memory")
>  
> -static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
> +static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
>  {
>  	int op = (encoded_op >> 28) & 7;
>  	int cmp = (encoded_op >> 24) & 15;
> @@ -39,7 +39,7 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
>  	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
>  		oparg = 1 << oparg;
>  
> -	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
> +	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
>  		return -EFAULT;
>  
>  	pagefault_disable();
> @@ -81,21 +81,23 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
>  }
>  
>  static inline int
> -futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
> +futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
> +			      u32 oldval, u32 newval)
>  {
> -	int prev, cmp;
> +	int ret = 0, cmp;
> +	u32 prev;
>  
> -	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
> +	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
>  		return -EFAULT;
>  
>  	__asm__ __volatile__ (
>  		__ASM_SMP_MB
> -	"1:	ldl_l	%0,0(%2)\n"
> -	"	cmpeq	%0,%3,%1\n"
> -	"	beq	%1,3f\n"
> -	"	mov	%4,%1\n"
> -	"2:	stl_c	%1,0(%2)\n"
> -	"	beq	%1,4f\n"
> +	"1:	ldl_l	%1,0(%3)\n"
> +	"	cmpeq	%1,%4,%2\n"
> +	"	beq	%2,3f\n"
> +	"	mov	%5,%2\n"
> +	"2:	stl_c	%2,0(%3)\n"
> +	"	beq	%2,4f\n"
>  	"3:	.subsection 2\n"
>  	"4:	br	1b\n"
>  	"	.previous\n"
> @@ -105,11 +107,12 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
>  	"	.long	2b-.\n"
>  	"	lda	$31,3b-2b(%0)\n"
>  	"	.previous\n"
> -	:	"=&r"(prev), "=&r"(cmp)
> +	:	"+r"(ret), "=&r"(prev), "=&r"(cmp)
>  	:	"r"(uaddr), "r"((long)oldval), "r"(newval)
>  	:	"memory");
>  
> -	return prev;
> +	*uval = prev;
> +	return ret;
>  }
>  
>  #endif /* __KERNEL__ */
> diff --git a/arch/arm/include/asm/futex.h b/arch/arm/include/asm/futex.h
> index b33fe70..0e29d8e 100644
> --- a/arch/arm/include/asm/futex.h
> +++ b/arch/arm/include/asm/futex.h
> @@ -35,7 +35,7 @@
>  	: "cc", "memory")
>  
>  static inline int
> -futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
> +futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
>  {
>  	int op = (encoded_op >> 28) & 7;
>  	int cmp = (encoded_op >> 24) & 15;
> @@ -46,7 +46,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
>  	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
>  		oparg = 1 << oparg;
>  
> -	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
> +	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
>  		return -EFAULT;
>  
>  	pagefault_disable();	/* implies preempt_disable() */
> @@ -88,36 +88,38 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
>  }
>  
>  static inline int
> -futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
> +futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
> +			      u32 oldval, u32 newval)
>  {
> -	int val;
> +	int ret = 0;
> +	u32 val;
>  
> -	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
> +	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
>  		return -EFAULT;
>  
> -	pagefault_disable();	/* implies preempt_disable() */
> +	/* Note that preemption is disabled by futex_atomic_cmpxchg_inatomic
> +	 * call sites. */
>  
>  	__asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n"
> -	"1:	" T(ldr) "	%0, [%3]\n"
> -	"	teq	%0, %1\n"
> +	"1:	" T(ldr) "	%1, [%4]\n"
> +	"	teq	%1, %2\n"
>  	"	it	eq	@ explicit IT needed for the 2b label\n"
> -	"2:	" T(streq) "	%2, [%3]\n"
> +	"2:	" T(streq) "	%3, [%4]\n"
>  	"3:\n"
>  	"	.pushsection __ex_table,\"a\"\n"
>  	"	.align	3\n"
>  	"	.long	1b, 4f, 2b, 4f\n"
>  	"	.popsection\n"
>  	"	.pushsection .fixup,\"ax\"\n"
> -	"4:	mov	%0, %4\n"
> +	"4:	mov	%0, %5\n"
>  	"	b	3b\n"
>  	"	.popsection"
> -	: "=&r" (val)
> +	: "+r" (ret), "=&r" (val)
>  	: "r" (oldval), "r" (newval), "r" (uaddr), "Ir" (-EFAULT)
>  	: "cc", "memory");
>  
> -	pagefault_enable();	/* subsumes preempt_enable() */
> -
> -	return val;
> +	*uval = val;
> +	return ret;
>  }
>  
>  #endif /* !SMP */
> diff --git a/arch/frv/include/asm/futex.h b/arch/frv/include/asm/futex.h
> index 08b3d1d..4bea27f 100644
> --- a/arch/frv/include/asm/futex.h
> +++ b/arch/frv/include/asm/futex.h
> @@ -7,10 +7,11 @@
>  #include <asm/errno.h>
>  #include <asm/uaccess.h>
>  
> -extern int futex_atomic_op_inuser(int encoded_op, int __user *uaddr);
> +extern int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr);
>  
>  static inline int
> -futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
> +futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
> +			      u32 oldval, u32 newval)
>  {
>  	return -ENOSYS;
>  }
> diff --git a/arch/frv/kernel/futex.c b/arch/frv/kernel/futex.c
> index 14f64b0..d155ca9 100644
> --- a/arch/frv/kernel/futex.c
> +++ b/arch/frv/kernel/futex.c
> @@ -18,7 +18,7 @@
>   * the various futex operations; MMU fault checking is ignored under no-MMU
>   * conditions
>   */
> -static inline int atomic_futex_op_xchg_set(int oparg, int __user *uaddr, int *_oldval)
> +static inline int atomic_futex_op_xchg_set(int oparg, u32 __user *uaddr, int *_oldval)
>  {
>  	int oldval, ret;
>  
> @@ -50,7 +50,7 @@ static inline int atomic_futex_op_xchg_set(int oparg, int __user *uaddr, int *_o
>  	return ret;
>  }
>  
> -static inline int atomic_futex_op_xchg_add(int oparg, int __user *uaddr, int *_oldval)
> +static inline int atomic_futex_op_xchg_add(int oparg, u32 __user *uaddr, int *_oldval)
>  {
>  	int oldval, ret;
>  
> @@ -83,7 +83,7 @@ static inline int atomic_futex_op_xchg_add(int oparg, int __user *uaddr, int *_o
>  	return ret;
>  }
>  
> -static inline int atomic_futex_op_xchg_or(int oparg, int __user *uaddr, int *_oldval)
> +static inline int atomic_futex_op_xchg_or(int oparg, u32 __user *uaddr, int *_oldval)
>  {
>  	int oldval, ret;
>  
> @@ -116,7 +116,7 @@ static inline int atomic_futex_op_xchg_or(int oparg, int __user *uaddr, int *_ol
>  	return ret;
>  }
>  
> -static inline int atomic_futex_op_xchg_and(int oparg, int __user *uaddr, int *_oldval)
> +static inline int atomic_futex_op_xchg_and(int oparg, u32 __user *uaddr, int *_oldval)
>  {
>  	int oldval, ret;
>  
> @@ -149,7 +149,7 @@ static inline int atomic_futex_op_xchg_and(int oparg, int __user *uaddr, int *_o
>  	return ret;
>  }
>  
> -static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr, int *_oldval)
> +static inline int atomic_futex_op_xchg_xor(int oparg, u32 __user *uaddr, int *_oldval)
>  {
>  	int oldval, ret;
>  
> @@ -186,7 +186,7 @@ static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr, int *_o
>  /*
>   * do the futex operations
>   */
> -int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
> +int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
>  {
>  	int op = (encoded_op >> 28) & 7;
>  	int cmp = (encoded_op >> 24) & 15;
> @@ -197,7 +197,7 @@ int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
>  	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
>  		oparg = 1 << oparg;
>  
> -	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
> +	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
>  		return -EFAULT;
>  
>  	pagefault_disable();
> diff --git a/arch/ia64/include/asm/futex.h b/arch/ia64/include/asm/futex.h
> index c7f0f06..8428525 100644
> --- a/arch/ia64/include/asm/futex.h
> +++ b/arch/ia64/include/asm/futex.h
> @@ -46,7 +46,7 @@ do {									\
>  } while (0)
>  
>  static inline int
> -futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
> +futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
>  {
>  	int op = (encoded_op >> 28) & 7;
>  	int cmp = (encoded_op >> 24) & 15;
> @@ -56,7 +56,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
>  	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
>  		oparg = 1 << oparg;
>  
> -	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
> +	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
>  		return -EFAULT;
>  
>  	pagefault_disable();
> @@ -100,23 +100,26 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
>  }
>  
>  static inline int
> -futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
> +futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
> +			      u32 oldval, u32 newval)
>  {
> -	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
> +	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
>  		return -EFAULT;
>  
>  	{
> -		register unsigned long r8 __asm ("r8");
> +		register unsigned long r8 __asm ("r8") = 0;
> +		unsigned long prev;
>  		__asm__ __volatile__(
>  			"	mf;;					\n"
>  			"	mov ar.ccv=%3;;				\n"
>  			"[1:]	cmpxchg4.acq %0=[%1],%2,ar.ccv		\n"
>  			"	.xdata4 \"__ex_table\", 1b-., 2f-.	\n"
>  			"[2:]"
> -			: "=r" (r8)
> +			: "=r" (prev)
>  			: "r" (uaddr), "r" (newval),
>  			  "rO" ((long) (unsigned) oldval)
>  			: "memory");
> +		*uval = prev;
>  		return r8;
>  	}
>  }
> diff --git a/arch/microblaze/include/asm/futex.h b/arch/microblaze/include/asm/futex.h
> index ad3fd61..b0526d2 100644
> --- a/arch/microblaze/include/asm/futex.h
> +++ b/arch/microblaze/include/asm/futex.h
> @@ -29,7 +29,7 @@
>  })
>  
>  static inline int
> -futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
> +futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
>  {
>  	int op = (encoded_op >> 28) & 7;
>  	int cmp = (encoded_op >> 24) & 15;
> @@ -39,7 +39,7 @@ futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
>  	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
>  		oparg = 1 << oparg;
>  
> -	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
> +	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
>  		return -EFAULT;
>  
>  	pagefault_disable();
> @@ -94,31 +94,34 @@ futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
>  }
>  
>  static inline int
> -futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
> +futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
> +			      u32 oldval, u32 newval)
>  {
> -	int prev, cmp;
> +	int ret = 0, cmp;
> +	u32 prev;
>  
> -	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
> +	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
>  		return -EFAULT;
>  
> -	__asm__ __volatile__ ("1:	lwx	%0, %2, r0;		\
> -					cmp	%1, %0, %3;		\
> -					beqi	%1, 3f;			\
> -				2:	swx	%4, %2, r0;		\
> -					addic	%1, r0, 0;		\
> -					bnei	%1, 1b;			\
> +	__asm__ __volatile__ ("1:	lwx	%1, %3, r0;		\
> +					cmp	%2, %1, %4;		\
> +					beqi	%2, 3f;			\
> +				2:	swx	%5, %3, r0;		\
> +					addic	%2, r0, 0;		\
> +					bnei	%2, 1b;			\
>  				3:					\
>  				.section .fixup,\"ax\";			\
>  				4:	brid	3b;			\
> -					addik	%0, r0, %5;		\
> +					addik	%0, r0, %6;		\
>  				.previous;				\
>  				.section __ex_table,\"a\";		\
>  				.word	1b,4b,2b,4b;			\
>  				.previous;"				\
> -		: "=&r" (prev), "=&r"(cmp)				\
> +		: "+r" (ret), "=&r" (prev), "=&r"(cmp)	\
>  		: "r" (uaddr), "r" (oldval), "r" (newval), "i" (-EFAULT));
>  
> -	return prev;
> +	*uval = prev;
> +	return ret;
>  }
>  
>  #endif /* __KERNEL__ */
> diff --git a/arch/mips/include/asm/futex.h b/arch/mips/include/asm/futex.h
> index b9cce90..6ebf173 100644
> --- a/arch/mips/include/asm/futex.h
> +++ b/arch/mips/include/asm/futex.h
> @@ -75,7 +75,7 @@
>  }
>  
>  static inline int
> -futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
> +futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
>  {
>  	int op = (encoded_op >> 28) & 7;
>  	int cmp = (encoded_op >> 24) & 15;
> @@ -85,7 +85,7 @@ futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
>  	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
>  		oparg = 1 << oparg;
>  
> -	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
> +	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
>  		return -EFAULT;
>  
>  	pagefault_disable();
> @@ -132,11 +132,13 @@ futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
>  }
>  
>  static inline int
> -futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
> +futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
> +			      u32 oldval, u32 newval)
>  {
> -	int retval;
> +	int ret = 0;
> +	u32 val;
>  
> -	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
> +	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
>  		return -EFAULT;
>  
>  	if (cpu_has_llsc && R10000_LLSC_WAR) {
> @@ -145,25 +147,25 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
>  		"	.set	push					\n"
>  		"	.set	noat					\n"
>  		"	.set	mips3					\n"
> -		"1:	ll	%0, %2					\n"
> -		"	bne	%0, %z3, 3f				\n"
> +		"1:	ll	%1, %3					\n"
> +		"	bne	%1, %z4, 3f				\n"
>  		"	.set	mips0					\n"
> -		"	move	$1, %z4					\n"
> +		"	move	$1, %z5					\n"
>  		"	.set	mips3					\n"
> -		"2:	sc	$1, %1					\n"
> +		"2:	sc	$1, %2					\n"
>  		"	beqzl	$1, 1b					\n"
>  		__WEAK_LLSC_MB
>  		"3:							\n"
>  		"	.set	pop					\n"
>  		"	.section .fixup,\"ax\"				\n"
> -		"4:	li	%0, %5					\n"
> +		"4:	li	%0, %6					\n"
>  		"	j	3b					\n"
>  		"	.previous					\n"
>  		"	.section __ex_table,\"a\"			\n"
>  		"	"__UA_ADDR "\t1b, 4b				\n"
>  		"	"__UA_ADDR "\t2b, 4b				\n"
>  		"	.previous					\n"
> -		: "=&r" (retval), "=R" (*uaddr)
> +		: "+r" (ret), "=&r" (val), "=R" (*uaddr)
>  		: "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT)
>  		: "memory");
>  	} else if (cpu_has_llsc) {
> @@ -172,31 +174,32 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
>  		"	.set	push					\n"
>  		"	.set	noat					\n"
>  		"	.set	mips3					\n"
> -		"1:	ll	%0, %2					\n"
> -		"	bne	%0, %z3, 3f				\n"
> +		"1:	ll	%1, %3					\n"
> +		"	bne	%1, %z4, 3f				\n"
>  		"	.set	mips0					\n"
> -		"	move	$1, %z4					\n"
> +		"	move	$1, %z5					\n"
>  		"	.set	mips3					\n"
> -		"2:	sc	$1, %1					\n"
> +		"2:	sc	$1, %2					\n"
>  		"	beqz	$1, 1b					\n"
>  		__WEAK_LLSC_MB
>  		"3:							\n"
>  		"	.set	pop					\n"
>  		"	.section .fixup,\"ax\"				\n"
> -		"4:	li	%0, %5					\n"
> +		"4:	li	%0, %6					\n"
>  		"	j	3b					\n"
>  		"	.previous					\n"
>  		"	.section __ex_table,\"a\"			\n"
>  		"	"__UA_ADDR "\t1b, 4b				\n"
>  		"	"__UA_ADDR "\t2b, 4b				\n"
>  		"	.previous					\n"
> -		: "=&r" (retval), "=R" (*uaddr)
> +		: "+r" (ret), "=&r" (val), "=R" (*uaddr)
>  		: "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT)
>  		: "memory");
>  	} else
>  		return -ENOSYS;
>  
> -	return retval;
> +	*uval = val;
> +	return ret;
>  }
>  
>  #endif
> diff --git a/arch/parisc/include/asm/futex.h b/arch/parisc/include/asm/futex.h
> index 0c705c3..67a33cc 100644
> --- a/arch/parisc/include/asm/futex.h
> +++ b/arch/parisc/include/asm/futex.h
> @@ -8,7 +8,7 @@
>  #include <asm/errno.h>
>  
>  static inline int
> -futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
> +futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
>  {
>  	int op = (encoded_op >> 28) & 7;
>  	int cmp = (encoded_op >> 24) & 15;
> @@ -18,7 +18,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
>  	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
>  		oparg = 1 << oparg;
>  
> -	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
> +	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
>  		return -EFAULT;
>  
>  	pagefault_disable();
> @@ -51,10 +51,10 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
>  
>  /* Non-atomic version */
>  static inline int
> -futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
> +futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
> +			      u32 oldval, u32 newval)
>  {
> -	int err = 0;
> -	int uval;
> +	u32 val;
>  
>  	/* futex.c wants to do a cmpxchg_inatomic on kernel NULL, which is
>  	 * our gateway page, and causes no end of trouble...
> @@ -62,15 +62,15 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
>  	if (segment_eq(KERNEL_DS, get_fs()) && !uaddr)
>  		return -EFAULT;
>  
> -	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
> +	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
>  		return -EFAULT;
>  
> -	err = get_user(uval, uaddr);
> -	if (err) return -EFAULT;
> -	if (uval == oldval)
> -		err = put_user(newval, uaddr);
> -	if (err) return -EFAULT;
> -	return uval;
> +	if (get_user(val, uaddr))
> +		return -EFAULT;
> +	if (val == oldval && put_user(newval, uaddr))
> +		return -EFAULT;
> +	*uval = val;
> +	return 0;
>  }
>  
>  #endif /*__KERNEL__*/
> diff --git a/arch/powerpc/include/asm/futex.h b/arch/powerpc/include/asm/futex.h
> index 7c589ef..c94e4a3 100644
> --- a/arch/powerpc/include/asm/futex.h
> +++ b/arch/powerpc/include/asm/futex.h
> @@ -30,7 +30,7 @@
>  	: "b" (uaddr), "i" (-EFAULT), "r" (oparg) \
>  	: "cr0", "memory")
>  
> -static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
> +static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
>  {
>  	int op = (encoded_op >> 28) & 7;
>  	int cmp = (encoded_op >> 24) & 15;
> @@ -40,7 +40,7 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
>  	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
>  		oparg = 1 << oparg;
>  
> -	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
> +	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
>  		return -EFAULT;
>  
>  	pagefault_disable();
> @@ -82,35 +82,38 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
>  }
>  
>  static inline int
> -futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
> +futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
> +			      u32 oldval, u32 newval)
>  {
> -	int prev;
> +	int ret = 0;
> +	u32 prev;
>  
> -	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
> +	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
>  		return -EFAULT;
>  
>          __asm__ __volatile__ (
>          PPC_RELEASE_BARRIER
> -"1:     lwarx   %0,0,%2         # futex_atomic_cmpxchg_inatomic\n\
> -        cmpw    0,%0,%3\n\
> +"1:     lwarx   %1,0,%3         # futex_atomic_cmpxchg_inatomic\n\
> +        cmpw    0,%1,%4\n\
>          bne-    3f\n"
> -        PPC405_ERR77(0,%2)
> -"2:     stwcx.  %4,0,%2\n\
> +        PPC405_ERR77(0,%3)
> +"2:     stwcx.  %5,0,%3\n\
>          bne-    1b\n"
>          PPC_ACQUIRE_BARRIER
>  "3:	.section .fixup,\"ax\"\n\
> -4:	li	%0,%5\n\
> +4:	li	%0,%6\n\
>  	b	3b\n\
>  	.previous\n\
>  	.section __ex_table,\"a\"\n\
>  	.align 3\n\
>  	" PPC_LONG "1b,4b,2b,4b\n\
>  	.previous" \
> -        : "=&r" (prev), "+m" (*uaddr)
> +        : "+r" (ret), "=&r" (prev), "+m" (*uaddr)
>          : "r" (uaddr), "r" (oldval), "r" (newval), "i" (-EFAULT)
>          : "cc", "memory");
>  
> -        return prev;
> +	*uval = prev;
> +        return ret;
>  }
>  
>  #endif /* __KERNEL__ */
> diff --git a/arch/s390/include/asm/futex.h b/arch/s390/include/asm/futex.h
> index 5c5d02d..81cf36b 100644
> --- a/arch/s390/include/asm/futex.h
> +++ b/arch/s390/include/asm/futex.h
> @@ -7,7 +7,7 @@
>  #include <linux/uaccess.h>
>  #include <asm/errno.h>
>  
> -static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
> +static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
>  {
>  	int op = (encoded_op >> 28) & 7;
>  	int cmp = (encoded_op >> 24) & 15;
> @@ -18,7 +18,7 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
>  	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
>  		oparg = 1 << oparg;
>  
> -	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
> +	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
>  		return -EFAULT;
>  
>  	pagefault_disable();
> @@ -39,13 +39,13 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
>  	return ret;
>  }
>  
> -static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr,
> -						int oldval, int newval)
> +static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
> +						u32 oldval, u32 newval)
>  {
> -	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
> +	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
>  		return -EFAULT;
>  
> -	return uaccess.futex_atomic_cmpxchg(uaddr, oldval, newval);
> +	return uaccess.futex_atomic_cmpxchg(uval, uaddr, oldval, newval);
>  }
>  
>  #endif /* __KERNEL__ */
> diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h
> index d6b1ed0..2d9ea11f 100644
> --- a/arch/s390/include/asm/uaccess.h
> +++ b/arch/s390/include/asm/uaccess.h
> @@ -83,8 +83,8 @@ struct uaccess_ops {
>  	size_t (*clear_user)(size_t, void __user *);
>  	size_t (*strnlen_user)(size_t, const char __user *);
>  	size_t (*strncpy_from_user)(size_t, const char __user *, char *);
> -	int (*futex_atomic_op)(int op, int __user *, int oparg, int *old);
> -	int (*futex_atomic_cmpxchg)(int __user *, int old, int new);
> +	int (*futex_atomic_op)(int op, u32 __user *, int oparg, int *old);
> +	int (*futex_atomic_cmpxchg)(u32 *, u32 __user *, u32 old, u32 new);
>  };
>  
>  extern struct uaccess_ops uaccess;
> diff --git a/arch/s390/lib/uaccess.h b/arch/s390/lib/uaccess.h
> index 126011d..1d2536c 100644
> --- a/arch/s390/lib/uaccess.h
> +++ b/arch/s390/lib/uaccess.h
> @@ -12,12 +12,12 @@ extern size_t copy_from_user_std(size_t, const void __user *, void *);
>  extern size_t copy_to_user_std(size_t, void __user *, const void *);
>  extern size_t strnlen_user_std(size_t, const char __user *);
>  extern size_t strncpy_from_user_std(size_t, const char __user *, char *);
> -extern int futex_atomic_cmpxchg_std(int __user *, int, int);
> -extern int futex_atomic_op_std(int, int __user *, int, int *);
> +extern int futex_atomic_cmpxchg_std(u32 *, u32 __user *, u32, u32);
> +extern int futex_atomic_op_std(int, u32 __user *, int, int *);
>  
>  extern size_t copy_from_user_pt(size_t, const void __user *, void *);
>  extern size_t copy_to_user_pt(size_t, void __user *, const void *);
> -extern int futex_atomic_op_pt(int, int __user *, int, int *);
> -extern int futex_atomic_cmpxchg_pt(int __user *, int, int);
> +extern int futex_atomic_op_pt(int, u32 __user *, int, int *);
> +extern int futex_atomic_cmpxchg_pt(u32 *, u32 __user *, u32, u32);
>  
>  #endif /* __ARCH_S390_LIB_UACCESS_H */
> diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c
> index 404f2de..afc716a 100644
> --- a/arch/s390/lib/uaccess_pt.c
> +++ b/arch/s390/lib/uaccess_pt.c
> @@ -302,7 +302,7 @@ fault:
>  		     : "0" (-EFAULT), "d" (oparg), "a" (uaddr),		\
>  		       "m" (*uaddr) : "cc" );
>  
> -static int __futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old)
> +static int __futex_atomic_op_pt(int op, u32 __user *uaddr, int oparg, int *old)
>  {
>  	int oldval = 0, newval, ret;
>  
> @@ -335,7 +335,7 @@ static int __futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old)
>  	return ret;
>  }
>  
> -int futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old)
> +int futex_atomic_op_pt(int op, u32 __user *uaddr, int oparg, int *old)
>  {
>  	int ret;
>  
> @@ -354,26 +354,29 @@ int futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old)
>  	return ret;
>  }
>  
> -static int __futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval)
> +static int __futex_atomic_cmpxchg_pt(u32 *uval, u32 __user *uaddr,
> +				     u32 oldval, u32 newval)
>  {
>  	int ret;
>  
>  	asm volatile("0: cs   %1,%4,0(%5)\n"
> -		     "1: lr   %0,%1\n"
> +		     "1: la   %0,0\n"
>  		     "2:\n"
>  		     EX_TABLE(0b,2b) EX_TABLE(1b,2b)
>  		     : "=d" (ret), "+d" (oldval), "=m" (*uaddr)
>  		     : "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr)
>  		     : "cc", "memory" );
> +	*uval = oldval;
>  	return ret;
>  }
>  
> -int futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval)
> +int futex_atomic_cmpxchg_pt(int *uval, int __user *uaddr,
> +			    int oldval, int newval)
>  {
>  	int ret;
>  
>  	if (segment_eq(get_fs(), KERNEL_DS))
> -		return __futex_atomic_cmpxchg_pt(uaddr, oldval, newval);
> +		return __futex_atomic_cmpxchg_pt(uval, uaddr, oldval, newval);
>  	spin_lock(&current->mm->page_table_lock);
>  	uaddr = (int __user *) __dat_user_addr((unsigned long) uaddr);
>  	if (!uaddr) {
> @@ -382,7 +385,7 @@ int futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval)
>  	}
>  	get_page(virt_to_page(uaddr));
>  	spin_unlock(&current->mm->page_table_lock);
> -	ret = __futex_atomic_cmpxchg_pt(uaddr, oldval, newval);
> +	ret = __futex_atomic_cmpxchg_pt(uval, uaddr, oldval, newval);
>  	put_page(virt_to_page(uaddr));
>  	return ret;
>  }
> diff --git a/arch/s390/lib/uaccess_std.c b/arch/s390/lib/uaccess_std.c
> index a6c4f7e..bb1a7ee 100644
> --- a/arch/s390/lib/uaccess_std.c
> +++ b/arch/s390/lib/uaccess_std.c
> @@ -255,7 +255,7 @@ size_t strncpy_from_user_std(size_t size, const char __user *src, char *dst)
>  		: "0" (-EFAULT), "d" (oparg), "a" (uaddr),		\
>  		  "m" (*uaddr) : "cc");
>  
> -int futex_atomic_op_std(int op, int __user *uaddr, int oparg, int *old)
> +int futex_atomic_op_std(int op, u32 __user *uaddr, int oparg, int *old)
>  {
>  	int oldval = 0, newval, ret;
>  
> @@ -287,19 +287,21 @@ int futex_atomic_op_std(int op, int __user *uaddr, int oparg, int *old)
>  	return ret;
>  }
>  
> -int futex_atomic_cmpxchg_std(int __user *uaddr, int oldval, int newval)
> +int futex_atomic_cmpxchg_std(u32 *uval, u32 __user *uaddr,
> +			     u32 oldval, u32 newval)
>  {
>  	int ret;
>  
>  	asm volatile(
>  		"   sacf 256\n"
>  		"0: cs   %1,%4,0(%5)\n"
> -		"1: lr   %0,%1\n"
> +		"1: la   %0,0\n"
>  		"2: sacf 0\n"
>  		EX_TABLE(0b,2b) EX_TABLE(1b,2b)
>  		: "=d" (ret), "+d" (oldval), "=m" (*uaddr)
>  		: "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr)
>  		: "cc", "memory" );
> +	*uval = oldval;
>  	return ret;
>  }
>  
> diff --git a/arch/sh/include/asm/futex-irq.h b/arch/sh/include/asm/futex-irq.h
> index a9f16a7..6cb9f19 100644
> --- a/arch/sh/include/asm/futex-irq.h
> +++ b/arch/sh/include/asm/futex-irq.h
> @@ -3,7 +3,7 @@
>  
>  #include <asm/system.h>
>  
> -static inline int atomic_futex_op_xchg_set(int oparg, int __user *uaddr,
> +static inline int atomic_futex_op_xchg_set(int oparg, u32 __user *uaddr,
>  					   int *oldval)
>  {
>  	unsigned long flags;
> @@ -20,7 +20,7 @@ static inline int atomic_futex_op_xchg_set(int oparg, int __user *uaddr,
>  	return ret;
>  }
>  
> -static inline int atomic_futex_op_xchg_add(int oparg, int __user *uaddr,
> +static inline int atomic_futex_op_xchg_add(int oparg, u32 __user *uaddr,
>  					   int *oldval)
>  {
>  	unsigned long flags;
> @@ -37,7 +37,7 @@ static inline int atomic_futex_op_xchg_add(int oparg, int __user *uaddr,
>  	return ret;
>  }
>  
> -static inline int atomic_futex_op_xchg_or(int oparg, int __user *uaddr,
> +static inline int atomic_futex_op_xchg_or(int oparg, u32 __user *uaddr,
>  					  int *oldval)
>  {
>  	unsigned long flags;
> @@ -54,7 +54,7 @@ static inline int atomic_futex_op_xchg_or(int oparg, int __user *uaddr,
>  	return ret;
>  }
>  
> -static inline int atomic_futex_op_xchg_and(int oparg, int __user *uaddr,
> +static inline int atomic_futex_op_xchg_and(int oparg, u32 __user *uaddr,
>  					   int *oldval)
>  {
>  	unsigned long flags;
> @@ -71,7 +71,7 @@ static inline int atomic_futex_op_xchg_and(int oparg, int __user *uaddr,
>  	return ret;
>  }
>  
> -static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr,
> +static inline int atomic_futex_op_xchg_xor(int oparg, u32 __user *uaddr,
>  					   int *oldval)
>  {
>  	unsigned long flags;
> @@ -88,11 +88,13 @@ static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr,
>  	return ret;
>  }
>  
> -static inline int atomic_futex_op_cmpxchg_inatomic(int __user *uaddr,
> -						   int oldval, int newval)
> +static inline int atomic_futex_op_cmpxchg_inatomic(u32 *uval,
> +						   u32 __user *uaddr,
> +						   u32 oldval, u32 newval)
>  {
>  	unsigned long flags;
> -	int ret, prev = 0;
> +	int ret;
> +	u32 prev = 0;
>  
>  	local_irq_save(flags);
>  
> @@ -102,10 +104,8 @@ static inline int atomic_futex_op_cmpxchg_inatomic(int __user *uaddr,
>  
>  	local_irq_restore(flags);
>  
> -	if (ret)
> -		return ret;
> -
> -	return prev;
> +	*uval = prev;
> +	return ret;
>  }
>  
>  #endif /* __ASM_SH_FUTEX_IRQ_H */
> diff --git a/arch/sh/include/asm/futex.h b/arch/sh/include/asm/futex.h
> index 68256ec..7be39a6 100644
> --- a/arch/sh/include/asm/futex.h
> +++ b/arch/sh/include/asm/futex.h
> @@ -10,7 +10,7 @@
>  /* XXX: UP variants, fix for SH-4A and SMP.. */
>  #include <asm/futex-irq.h>
>  
> -static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
> +static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
>  {
>  	int op = (encoded_op >> 28) & 7;
>  	int cmp = (encoded_op >> 24) & 15;
> @@ -21,7 +21,7 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
>  	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
>  		oparg = 1 << oparg;
>  
> -	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
> +	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
>  		return -EFAULT;
>  
>  	pagefault_disable();
> @@ -65,12 +65,13 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
>  }
>  
>  static inline int
> -futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
> +futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
> +			      u32 oldval, u32 newval)
>  {
> -	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
> +	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
>  		return -EFAULT;
>  
> -	return atomic_futex_op_cmpxchg_inatomic(uaddr, oldval, newval);
> +	return atomic_futex_op_cmpxchg_inatomic(uval, uaddr, oldval, newval);
>  }
>  
>  #endif /* __KERNEL__ */
> diff --git a/arch/sparc/include/asm/futex_64.h b/arch/sparc/include/asm/futex_64.h
> index 47f9583..444e7be 100644
> --- a/arch/sparc/include/asm/futex_64.h
> +++ b/arch/sparc/include/asm/futex_64.h
> @@ -30,7 +30,7 @@
>  	: "r" (uaddr), "r" (oparg), "i" (-EFAULT)	\
>  	: "memory")
>  
> -static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
> +static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
>  {
>  	int op = (encoded_op >> 28) & 7;
>  	int cmp = (encoded_op >> 24) & 15;
> @@ -38,7 +38,7 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
>  	int cmparg = (encoded_op << 20) >> 20;
>  	int oldval = 0, ret, tem;
>  
> -	if (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(int))))
> +	if (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))))
>  		return -EFAULT;
>  	if (unlikely((((unsigned long) uaddr) & 0x3UL)))
>  		return -EINVAL;
> @@ -85,26 +85,30 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
>  }
>  
>  static inline int
> -futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
> +futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
> +			      u32 oldval, u32 newval)
>  {
> +	int ret = 0;
> +
>  	__asm__ __volatile__(
> -	"\n1:	casa	[%3] %%asi, %2, %0\n"
> +	"\n1:	casa	[%4] %%asi, %3, %1\n"
>  	"2:\n"
>  	"	.section .fixup,#alloc,#execinstr\n"
>  	"	.align	4\n"
>  	"3:	sethi	%%hi(2b), %0\n"
>  	"	jmpl	%0 + %%lo(2b), %%g0\n"
> -	"	 mov	%4, %0\n"
> +	"	mov	%5, %0\n"
>  	"	.previous\n"
>  	"	.section __ex_table,\"a\"\n"
>  	"	.align	4\n"
>  	"	.word	1b, 3b\n"
>  	"	.previous\n"
> -	: "=r" (newval)
> -	: "0" (newval), "r" (oldval), "r" (uaddr), "i" (-EFAULT)
> +	: "+r" (ret), "=r" (newval)
> +	: "1" (newval), "r" (oldval), "r" (uaddr), "i" (-EFAULT)
>  	: "memory");
>  
> -	return newval;
> +	*uval = newval;
> +	return ret;
>  }
>  
>  #endif /* !(_SPARC64_FUTEX_H) */
> diff --git a/arch/tile/include/asm/futex.h b/arch/tile/include/asm/futex.h
> index fe0d10d..d03ec12 100644
> --- a/arch/tile/include/asm/futex.h
> +++ b/arch/tile/include/asm/futex.h
> @@ -29,16 +29,16 @@
>  #include <linux/uaccess.h>
>  #include <linux/errno.h>
>  
> -extern struct __get_user futex_set(int __user *v, int i);
> -extern struct __get_user futex_add(int __user *v, int n);
> -extern struct __get_user futex_or(int __user *v, int n);
> -extern struct __get_user futex_andn(int __user *v, int n);
> -extern struct __get_user futex_cmpxchg(int __user *v, int o, int n);
> +extern struct __get_user futex_set(u32 __user *v, int i);
> +extern struct __get_user futex_add(u32 __user *v, int n);
> +extern struct __get_user futex_or(u32 __user *v, int n);
> +extern struct __get_user futex_andn(u32 __user *v, int n);
> +extern struct __get_user futex_cmpxchg(u32 __user *v, int o, int n);
>  
>  #ifndef __tilegx__
> -extern struct __get_user futex_xor(int __user *v, int n);
> +extern struct __get_user futex_xor(u32 __user *v, int n);
>  #else
> -static inline struct __get_user futex_xor(int __user *uaddr, int n)
> +static inline struct __get_user futex_xor(u32 __user *uaddr, int n)
>  {
>  	struct __get_user asm_ret = __get_user_4(uaddr);
>  	if (!asm_ret.err) {
> @@ -53,7 +53,7 @@ static inline struct __get_user futex_xor(int __user *uaddr, int n)
>  }
>  #endif
>  
> -static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
> +static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
>  {
>  	int op = (encoded_op >> 28) & 7;
>  	int cmp = (encoded_op >> 24) & 15;
> @@ -65,7 +65,7 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
>  	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
>  		oparg = 1 << oparg;
>  
> -	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
> +	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
>  		return -EFAULT;
>  
>  	pagefault_disable();
> @@ -119,16 +119,17 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
>  	return ret;
>  }
>  
> -static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval,
> -						int newval)
> +static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
> +						u32 oldval, u32 newval)
>  {
>  	struct __get_user asm_ret;
>  
> -	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
> +	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
>  		return -EFAULT;
>  
>  	asm_ret = futex_cmpxchg(uaddr, oldval, newval);
> -	return asm_ret.err ? asm_ret.err : asm_ret.val;
> +	*uval = asm_ret.val;
> +	return asm_ret.err;
>  }
>  
>  #ifndef __tilegx__
> diff --git a/arch/x86/include/asm/futex.h b/arch/x86/include/asm/futex.h
> index 1f11ce4..d09bb03 100644
> --- a/arch/x86/include/asm/futex.h
> +++ b/arch/x86/include/asm/futex.h
> @@ -37,7 +37,7 @@
>  		       "+m" (*uaddr), "=&r" (tem)		\
>  		     : "r" (oparg), "i" (-EFAULT), "1" (0))
>  
> -static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
> +static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
>  {
>  	int op = (encoded_op >> 28) & 7;
>  	int cmp = (encoded_op >> 24) & 15;
> @@ -48,7 +48,7 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
>  	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
>  		oparg = 1 << oparg;
>  
> -	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
> +	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
>  		return -EFAULT;
>  
>  #if defined(CONFIG_X86_32) && !defined(CONFIG_X86_BSWAP)
> @@ -109,9 +109,10 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
>  	return ret;
>  }
>  
> -static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval,
> -						int newval)
> +static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
> +						u32 oldval, u32 newval)
>  {
> +	int ret = 0;
>  
>  #if defined(CONFIG_X86_32) && !defined(CONFIG_X86_BSWAP)
>  	/* Real i386 machines have no cmpxchg instruction */
> @@ -119,21 +120,22 @@ static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval,
>  		return -ENOSYS;
>  #endif
>  
> -	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
> +	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
>  		return -EFAULT;
>  
> -	asm volatile("1:\t" LOCK_PREFIX "cmpxchgl %3, %1\n"
> +	asm volatile("1:\t" LOCK_PREFIX "cmpxchgl %4, %2\n"
>  		     "2:\t.section .fixup, \"ax\"\n"
> -		     "3:\tmov     %2, %0\n"
> +		     "3:\tmov     %3, %0\n"
>  		     "\tjmp     2b\n"
>  		     "\t.previous\n"
>  		     _ASM_EXTABLE(1b, 3b)
> -		     : "=a" (oldval), "+m" (*uaddr)
> -		     : "i" (-EFAULT), "r" (newval), "0" (oldval)
> +		     : "+r" (ret), "=a" (oldval), "+m" (*uaddr)
> +		     : "i" (-EFAULT), "r" (newval), "1" (oldval)
>  		     : "memory"
>  	);
>  
> -	return oldval;
> +	*uval = oldval;
> +	return ret;
>  }
>  
>  #endif
> diff --git a/include/asm-generic/futex.h b/include/asm-generic/futex.h
> index 3c2344f..01f227e 100644
> --- a/include/asm-generic/futex.h
> +++ b/include/asm-generic/futex.h
> @@ -6,7 +6,7 @@
>  #include <asm/errno.h>
>  
>  static inline int
> -futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
> +futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
>  {
>  	int op = (encoded_op >> 28) & 7;
>  	int cmp = (encoded_op >> 24) & 15;
> @@ -16,7 +16,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
>  	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
>  		oparg = 1 << oparg;
>  
> -	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
> +	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
>  		return -EFAULT;
>  
>  	pagefault_disable();
> @@ -48,7 +48,8 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
>  }
>  
>  static inline int
> -futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
> +futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
> +			      u32 oldval, u32 newval)
>  {
>  	return -ENOSYS;
>  }
> diff --git a/kernel/futex.c b/kernel/futex.c
> index 3184d3b..53b783f 100644
> --- a/kernel/futex.c
> +++ b/kernel/futex.c
> @@ -381,15 +381,16 @@ static struct futex_q *futex_top_waiter(struct futex_hash_bucket *hb,
>  	return NULL;
>  }
>  
> -static u32 cmpxchg_futex_value_locked(u32 __user *uaddr, u32 uval, u32 newval)
> +static int cmpxchg_futex_value_locked(u32 *curval, u32 __user *uaddr,
> +				      u32 uval, u32 newval)
>  {
> -	u32 curval;
> +	int ret;
>  
>  	pagefault_disable();
> -	curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval);
> +	ret = futex_atomic_cmpxchg_inatomic(curval, uaddr, uval, newval);
>  	pagefault_enable();
>  
> -	return curval;
> +	return ret;
>  }
>  
>  static int get_futex_value_locked(u32 *dest, u32 __user *from)
> @@ -688,9 +689,7 @@ retry:
>  	if (set_waiters)
>  		newval |= FUTEX_WAITERS;
>  
> -	curval = cmpxchg_futex_value_locked(uaddr, 0, newval);
> -
> -	if (unlikely(curval == -EFAULT))
> +	if (unlikely(cmpxchg_futex_value_locked(&curval, uaddr, 0, newval)))
>  		return -EFAULT;
>  
>  	/*
> @@ -728,9 +727,7 @@ retry:
>  		lock_taken = 1;
>  	}
>  
> -	curval = cmpxchg_futex_value_locked(uaddr, uval, newval);
> -
> -	if (unlikely(curval == -EFAULT))
> +	if (unlikely(cmpxchg_futex_value_locked(&curval, uaddr, uval, newval)))
>  		return -EFAULT;
>  	if (unlikely(curval != uval))
>  		goto retry;
> @@ -843,9 +840,7 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this)
>  
>  		newval = FUTEX_WAITERS | task_pid_vnr(new_owner);
>  
> -		curval = cmpxchg_futex_value_locked(uaddr, uval, newval);
> -
> -		if (curval == -EFAULT)
> +		if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval))
>  			ret = -EFAULT;
>  		else if (curval != uval)
>  			ret = -EINVAL;
> @@ -880,10 +875,8 @@ static int unlock_futex_pi(u32 __user *uaddr, u32 uval)
>  	 * There is no waiter, so we unlock the futex. The owner died
>  	 * bit has not to be preserved here. We are the owner:
>  	 */
> -	oldval = cmpxchg_futex_value_locked(uaddr, uval, 0);
> -
> -	if (oldval == -EFAULT)
> -		return oldval;
> +	if (cmpxchg_futex_value_locked(&oldval, uaddr, uval, 0))
> +		return -EFAULT;
>  	if (oldval != uval)
>  		return -EAGAIN;
>  
> @@ -1578,9 +1571,7 @@ retry:
>  	while (1) {
>  		newval = (uval & FUTEX_OWNER_DIED) | newtid;
>  
> -		curval = cmpxchg_futex_value_locked(uaddr, uval, newval);
> -
> -		if (curval == -EFAULT)
> +		if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval))
>  			goto handle_fault;
>  		if (curval == uval)
>  			break;
> @@ -2073,11 +2064,9 @@ retry:
>  	 * again. If it succeeds then we can return without waking
>  	 * anyone else up:
>  	 */
> -	if (!(uval & FUTEX_OWNER_DIED))
> -		uval = cmpxchg_futex_value_locked(uaddr, task_pid_vnr(current), 0);
> -
> -
> -	if (unlikely(uval == -EFAULT))
> +	if (!(uval & FUTEX_OWNER_DIED) &&
> +	    unlikely(cmpxchg_futex_value_locked(&uval, uaddr,
> +						task_pid_vnr(current), 0)))
>  		goto pi_faulted;
>  	/*
>  	 * Rare case: we managed to release the lock atomically,
> @@ -2464,9 +2453,7 @@ retry:
>  		 * userspace.
>  		 */
>  		mval = (uval & FUTEX_WAITERS) | FUTEX_OWNER_DIED;
> -		nval = futex_atomic_cmpxchg_inatomic(uaddr, uval, mval);
> -
> -		if (nval == -EFAULT)
> +		if (futex_atomic_cmpxchg_inatomic(&nval, uaddr, uval, mval))
>  			return -1;
>  
>  		if (nval != uval)
> @@ -2679,8 +2666,7 @@ static int __init futex_init(void)
>  	 * implementation, the non-functional ones will return
>  	 * -ENOSYS.
>  	 */
> -	curval = cmpxchg_futex_value_locked(NULL, 0, 0);
> -	if (curval == -EFAULT)
> +	if (cmpxchg_futex_value_locked(&curval, NULL, 0, 0) == -EFAULT)
>  		futex_cmpxchg_enabled = 1;
>  
>  	for (i = 0; i < ARRAY_SIZE(futex_queues); i++) {
> 
> 
> -- 
> Michel "Walken" Lespinasse
> A program is never fully debugged until the last user dies.
> 

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH] futex: cmpxchg_futex_value_locked API change
  2011-03-09 11:25   ` Michel Lespinasse
  2011-03-09 15:04     ` Thomas Gleixner
@ 2011-03-09 15:08     ` Martin Schwidefsky
  2011-03-09 22:17       ` Michel Lespinasse
  2011-03-09 17:50     ` Darren Hart
  2011-03-10 18:55     ` Thomas Gleixner
  3 siblings, 1 reply; 42+ messages in thread
From: Martin Schwidefsky @ 2011-03-09 15:08 UTC (permalink / raw)
  To: Michel Lespinasse
  Cc: Thomas Gleixner, Darren Hart, Ingo Molnar, Peter Zijlstra,
	Matt Turner, Russell King, David Howells, Tony Luck,
	Michal Simek, Ralf Baechle, James E.J. Bottomley,
	Benjamin Herrenschmidt, Paul Mundt, David S. Miller,
	Chris Metcalf, Andrew Morton, Linus Torvalds, LKML

On Wed, 9 Mar 2011 03:25:50 -0800
Michel Lespinasse <walken@google.com> wrote:

> On Tue, Mar 08, 2011 at 09:17:11PM +0100, Thomas Gleixner wrote:
> > On Sun, 6 Mar 2011, Michel Lespinasse wrote:
> > > The cmpxchg_futex_value_locked API was funny in that it returned either
> > > the original, user-exposed futex value OR an error code such as -EFAULT.
> > > This was confusing at best, and could be a source of livelocks in places
> > > that retry the cmpxchg_futex_value_locked after trying to fix the issue
> > > by running fault_in_user_writeable().
> > > 
> > > This change makes the cmpxchg_futex_value_locked API more similar to the
> > > get_futex_value_locked one, returning an error code and updating the
> > > original value through a reference argument.
> > 
> > Ack.
> > 
> > >  static inline int
> > > -futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
> > > +futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
> > > +			      int oldval, int newval)
> > 
> > Can we please change the arguments to u32 while at it? The futex core
> > code uses u32 all over the place so those inlines should do the same.
> 
> All right. Attaching updated version of the diff. I also fixed the s390
> issue reported by Martin Schwidefsky.

The inline assmeblies look good now but I get this compile error on s390:

  CC      arch/s390/lib/uaccess_pt.o
arch/s390/lib/uaccess_pt.c:373: error: conflicting types for 'futex_atomic_cmpxchg_pt'
arch/s390/lib/uaccess.h:21: note: previous declaration of 'futex_atomic_cmpxchg_pt' was here
arch/s390/lib/uaccess_pt.c:403: warning: initialization from incompatible pointer type
make[1]: *** [arch/s390/lib/uaccess_pt.o] Error 1

The trouble is this part of the patch:

-int futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval)
+int futex_atomic_cmpxchg_pt(int *uval, int __user *uaddr,
+                           int oldval, int newval)

You need to change these "int"s to "u32"s.

-- 
blue skies,
   Martin.

"Reality continues to ruin my life." - Calvin.


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH] futex: cmpxchg_futex_value_locked API change
  2011-03-09 11:25   ` Michel Lespinasse
  2011-03-09 15:04     ` Thomas Gleixner
  2011-03-09 15:08     ` Martin Schwidefsky
@ 2011-03-09 17:50     ` Darren Hart
  2011-03-10 18:55     ` Thomas Gleixner
  3 siblings, 0 replies; 42+ messages in thread
From: Darren Hart @ 2011-03-09 17:50 UTC (permalink / raw)
  To: Michel Lespinasse
  Cc: Thomas Gleixner, Ingo Molnar, Peter Zijlstra, Matt Turner,
	Russell King, David Howells, Tony Luck, Michal Simek,
	Ralf Baechle, James E.J. Bottomley, Benjamin Herrenschmidt,
	Martin Schwidefsky, Paul Mundt, David S. Miller, Chris Metcalf,
	Andrew Morton, Linus Torvalds, LKML

On Wed, Mar 9, 2011 at 3:25 AM, Michel Lespinasse <walken@google.com> wrote:
> On Tue, Mar 08, 2011 at 09:17:11PM +0100, Thomas Gleixner wrote:
>> On Sun, 6 Mar 2011, Michel Lespinasse wrote:
>> > The cmpxchg_futex_value_locked API was funny in that it returned either
>> > the original, user-exposed futex value OR an error code such as -EFAULT.
>> > This was confusing at best, and could be a source of livelocks in places
>> > that retry the cmpxchg_futex_value_locked after trying to fix the issue
>> > by running fault_in_user_writeable().
>> >
>> > This change makes the cmpxchg_futex_value_locked API more similar to the
>> > get_futex_value_locked one, returning an error code and updating the
>> > original value through a reference argument.
>>
>> Ack.
>>
>> >  static inline int
>> > -futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
>> > +futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
>> > +                         int oldval, int newval)
>>
>> Can we please change the arguments to u32 while at it? The futex core
>> code uses u32 all over the place so those inlines should do the same.
>
> All right. Attaching updated version of the diff. I also fixed the s390
> issue reported by Martin Schwidefsky.
>
> What's the proper path to check this in, could you send it towards
> the -next tree so it gets more testing ?
>
> --------------------------------------8<-------------------------------
>
> The cmpxchg_futex_value_locked API was funny in that it returned either
> the original, user-exposed futex value OR an error code such as -EFAULT.
> This was confusing at best, and could be a source of livelocks in places
> that retry the cmpxchg_futex_value_locked after trying to fix the issue
> by running fault_in_user_writeable().
>
> This change makes the cmpxchg_futex_value_locked API more similar to the
> get_futex_value_locked one, returning an error code and updating the
> original value through a reference argument.
>
> Additionally, the futex pointer types have been changed to u32 * in both
> futex_atomic_cmpxchg_inatomic and futex_atomic_op_inuser internal APIs
> as suggested by Thomas Gleixner.
>

Hi Michel, have you run the patches through futextest? Particularly
the functional tests (you can comment out the requeue pi tests as they
are known to be failing atm).

No objections from me, but I'd like to see things like this run
through futextest to help avoid subtle issues.

--
Darren

> Signed-off-by: Michel Lespinasse <walken@google.com>
> Acked-by: Chris Metcalf <cmetcalf@tilera.com>  (for tile)
> Acked-by: Tony Luck <tony.luck@intel.com>  (for ia64)
> Acked-by: Thomas Gleixner <tglx@linutronix.de>
> Tested-by: Michal Simek <monstr@monstr.eu>  (for microblaze)
>
> ---
>  arch/alpha/include/asm/futex.h      |   29 ++++++++++++----------
>  arch/arm/include/asm/futex.h        |   30 ++++++++++++----------
>  arch/frv/include/asm/futex.h        |    5 ++-
>  arch/frv/kernel/futex.c             |   14 +++++-----
>  arch/ia64/include/asm/futex.h       |   15 +++++++----
>  arch/microblaze/include/asm/futex.h |   31 +++++++++++++----------
>  arch/mips/include/asm/futex.h       |   39 ++++++++++++++++-------------
>  arch/parisc/include/asm/futex.h     |   24 +++++++++---------
>  arch/powerpc/include/asm/futex.h    |   27 +++++++++++---------
>  arch/s390/include/asm/futex.h       |   12 ++++----
>  arch/s390/include/asm/uaccess.h     |    4 +-
>  arch/s390/lib/uaccess.h             |    8 +++---
>  arch/s390/lib/uaccess_pt.c          |   17 +++++++-----
>  arch/s390/lib/uaccess_std.c         |    8 ++++--
>  arch/sh/include/asm/futex-irq.h     |   24 +++++++++---------
>  arch/sh/include/asm/futex.h         |   11 ++++----
>  arch/sparc/include/asm/futex_64.h   |   20 +++++++++------
>  arch/tile/include/asm/futex.h       |   27 ++++++++++----------
>  arch/x86/include/asm/futex.h        |   22 +++++++++-------
>  include/asm-generic/futex.h         |    7 +++--
>  kernel/futex.c                      |   46 ++++++++++++----------------------
>  21 files changed, 219 insertions(+), 201 deletions(-)
>
> diff --git a/arch/alpha/include/asm/futex.h b/arch/alpha/include/asm/futex.h
> index 945de22..e8a761a 100644
> --- a/arch/alpha/include/asm/futex.h
> +++ b/arch/alpha/include/asm/futex.h
> @@ -29,7 +29,7 @@
>        :       "r" (uaddr), "r"(oparg)                         \
>        :       "memory")
>
> -static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
> +static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
>  {
>        int op = (encoded_op >> 28) & 7;
>        int cmp = (encoded_op >> 24) & 15;
> @@ -39,7 +39,7 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
>        if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
>                oparg = 1 << oparg;
>
> -       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
> +       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
>                return -EFAULT;
>
>        pagefault_disable();
> @@ -81,21 +81,23 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
>  }
>
>  static inline int
> -futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
> +futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
> +                             u32 oldval, u32 newval)
>  {
> -       int prev, cmp;
> +       int ret = 0, cmp;
> +       u32 prev;
>
> -       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
> +       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
>                return -EFAULT;
>
>        __asm__ __volatile__ (
>                __ASM_SMP_MB
> -       "1:     ldl_l   %0,0(%2)\n"
> -       "       cmpeq   %0,%3,%1\n"
> -       "       beq     %1,3f\n"
> -       "       mov     %4,%1\n"
> -       "2:     stl_c   %1,0(%2)\n"
> -       "       beq     %1,4f\n"
> +       "1:     ldl_l   %1,0(%3)\n"
> +       "       cmpeq   %1,%4,%2\n"
> +       "       beq     %2,3f\n"
> +       "       mov     %5,%2\n"
> +       "2:     stl_c   %2,0(%3)\n"
> +       "       beq     %2,4f\n"
>        "3:     .subsection 2\n"
>        "4:     br      1b\n"
>        "       .previous\n"
> @@ -105,11 +107,12 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
>        "       .long   2b-.\n"
>        "       lda     $31,3b-2b(%0)\n"
>        "       .previous\n"
> -       :       "=&r"(prev), "=&r"(cmp)
> +       :       "+r"(ret), "=&r"(prev), "=&r"(cmp)
>        :       "r"(uaddr), "r"((long)oldval), "r"(newval)
>        :       "memory");
>
> -       return prev;
> +       *uval = prev;
> +       return ret;
>  }
>
>  #endif /* __KERNEL__ */
> diff --git a/arch/arm/include/asm/futex.h b/arch/arm/include/asm/futex.h
> index b33fe70..0e29d8e 100644
> --- a/arch/arm/include/asm/futex.h
> +++ b/arch/arm/include/asm/futex.h
> @@ -35,7 +35,7 @@
>        : "cc", "memory")
>
>  static inline int
> -futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
> +futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
>  {
>        int op = (encoded_op >> 28) & 7;
>        int cmp = (encoded_op >> 24) & 15;
> @@ -46,7 +46,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
>        if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
>                oparg = 1 << oparg;
>
> -       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
> +       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
>                return -EFAULT;
>
>        pagefault_disable();    /* implies preempt_disable() */
> @@ -88,36 +88,38 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
>  }
>
>  static inline int
> -futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
> +futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
> +                             u32 oldval, u32 newval)
>  {
> -       int val;
> +       int ret = 0;
> +       u32 val;
>
> -       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
> +       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
>                return -EFAULT;
>
> -       pagefault_disable();    /* implies preempt_disable() */
> +       /* Note that preemption is disabled by futex_atomic_cmpxchg_inatomic
> +        * call sites. */
>
>        __asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n"
> -       "1:     " T(ldr) "      %0, [%3]\n"
> -       "       teq     %0, %1\n"
> +       "1:     " T(ldr) "      %1, [%4]\n"
> +       "       teq     %1, %2\n"
>        "       it      eq      @ explicit IT needed for the 2b label\n"
> -       "2:     " T(streq) "    %2, [%3]\n"
> +       "2:     " T(streq) "    %3, [%4]\n"
>        "3:\n"
>        "       .pushsection __ex_table,\"a\"\n"
>        "       .align  3\n"
>        "       .long   1b, 4f, 2b, 4f\n"
>        "       .popsection\n"
>        "       .pushsection .fixup,\"ax\"\n"
> -       "4:     mov     %0, %4\n"
> +       "4:     mov     %0, %5\n"
>        "       b       3b\n"
>        "       .popsection"
> -       : "=&r" (val)
> +       : "+r" (ret), "=&r" (val)
>        : "r" (oldval), "r" (newval), "r" (uaddr), "Ir" (-EFAULT)
>        : "cc", "memory");
>
> -       pagefault_enable();     /* subsumes preempt_enable() */
> -
> -       return val;
> +       *uval = val;
> +       return ret;
>  }
>
>  #endif /* !SMP */
> diff --git a/arch/frv/include/asm/futex.h b/arch/frv/include/asm/futex.h
> index 08b3d1d..4bea27f 100644
> --- a/arch/frv/include/asm/futex.h
> +++ b/arch/frv/include/asm/futex.h
> @@ -7,10 +7,11 @@
>  #include <asm/errno.h>
>  #include <asm/uaccess.h>
>
> -extern int futex_atomic_op_inuser(int encoded_op, int __user *uaddr);
> +extern int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr);
>
>  static inline int
> -futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
> +futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
> +                             u32 oldval, u32 newval)
>  {
>        return -ENOSYS;
>  }
> diff --git a/arch/frv/kernel/futex.c b/arch/frv/kernel/futex.c
> index 14f64b0..d155ca9 100644
> --- a/arch/frv/kernel/futex.c
> +++ b/arch/frv/kernel/futex.c
> @@ -18,7 +18,7 @@
>  * the various futex operations; MMU fault checking is ignored under no-MMU
>  * conditions
>  */
> -static inline int atomic_futex_op_xchg_set(int oparg, int __user *uaddr, int *_oldval)
> +static inline int atomic_futex_op_xchg_set(int oparg, u32 __user *uaddr, int *_oldval)
>  {
>        int oldval, ret;
>
> @@ -50,7 +50,7 @@ static inline int atomic_futex_op_xchg_set(int oparg, int __user *uaddr, int *_o
>        return ret;
>  }
>
> -static inline int atomic_futex_op_xchg_add(int oparg, int __user *uaddr, int *_oldval)
> +static inline int atomic_futex_op_xchg_add(int oparg, u32 __user *uaddr, int *_oldval)
>  {
>        int oldval, ret;
>
> @@ -83,7 +83,7 @@ static inline int atomic_futex_op_xchg_add(int oparg, int __user *uaddr, int *_o
>        return ret;
>  }
>
> -static inline int atomic_futex_op_xchg_or(int oparg, int __user *uaddr, int *_oldval)
> +static inline int atomic_futex_op_xchg_or(int oparg, u32 __user *uaddr, int *_oldval)
>  {
>        int oldval, ret;
>
> @@ -116,7 +116,7 @@ static inline int atomic_futex_op_xchg_or(int oparg, int __user *uaddr, int *_ol
>        return ret;
>  }
>
> -static inline int atomic_futex_op_xchg_and(int oparg, int __user *uaddr, int *_oldval)
> +static inline int atomic_futex_op_xchg_and(int oparg, u32 __user *uaddr, int *_oldval)
>  {
>        int oldval, ret;
>
> @@ -149,7 +149,7 @@ static inline int atomic_futex_op_xchg_and(int oparg, int __user *uaddr, int *_o
>        return ret;
>  }
>
> -static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr, int *_oldval)
> +static inline int atomic_futex_op_xchg_xor(int oparg, u32 __user *uaddr, int *_oldval)
>  {
>        int oldval, ret;
>
> @@ -186,7 +186,7 @@ static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr, int *_o
>  /*
>  * do the futex operations
>  */
> -int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
> +int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
>  {
>        int op = (encoded_op >> 28) & 7;
>        int cmp = (encoded_op >> 24) & 15;
> @@ -197,7 +197,7 @@ int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
>        if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
>                oparg = 1 << oparg;
>
> -       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
> +       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
>                return -EFAULT;
>
>        pagefault_disable();
> diff --git a/arch/ia64/include/asm/futex.h b/arch/ia64/include/asm/futex.h
> index c7f0f06..8428525 100644
> --- a/arch/ia64/include/asm/futex.h
> +++ b/arch/ia64/include/asm/futex.h
> @@ -46,7 +46,7 @@ do {                                                                  \
>  } while (0)
>
>  static inline int
> -futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
> +futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
>  {
>        int op = (encoded_op >> 28) & 7;
>        int cmp = (encoded_op >> 24) & 15;
> @@ -56,7 +56,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
>        if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
>                oparg = 1 << oparg;
>
> -       if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
> +       if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
>                return -EFAULT;
>
>        pagefault_disable();
> @@ -100,23 +100,26 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
>  }
>
>  static inline int
> -futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
> +futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
> +                             u32 oldval, u32 newval)
>  {
> -       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
> +       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
>                return -EFAULT;
>
>        {
> -               register unsigned long r8 __asm ("r8");
> +               register unsigned long r8 __asm ("r8") = 0;
> +               unsigned long prev;
>                __asm__ __volatile__(
>                        "       mf;;                                    \n"
>                        "       mov ar.ccv=%3;;                         \n"
>                        "[1:]   cmpxchg4.acq %0=[%1],%2,ar.ccv          \n"
>                        "       .xdata4 \"__ex_table\", 1b-., 2f-.      \n"
>                        "[2:]"
> -                       : "=r" (r8)
> +                       : "=r" (prev)
>                        : "r" (uaddr), "r" (newval),
>                          "rO" ((long) (unsigned) oldval)
>                        : "memory");
> +               *uval = prev;
>                return r8;
>        }
>  }
> diff --git a/arch/microblaze/include/asm/futex.h b/arch/microblaze/include/asm/futex.h
> index ad3fd61..b0526d2 100644
> --- a/arch/microblaze/include/asm/futex.h
> +++ b/arch/microblaze/include/asm/futex.h
> @@ -29,7 +29,7 @@
>  })
>
>  static inline int
> -futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
> +futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
>  {
>        int op = (encoded_op >> 28) & 7;
>        int cmp = (encoded_op >> 24) & 15;
> @@ -39,7 +39,7 @@ futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
>        if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
>                oparg = 1 << oparg;
>
> -       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
> +       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
>                return -EFAULT;
>
>        pagefault_disable();
> @@ -94,31 +94,34 @@ futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
>  }
>
>  static inline int
> -futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
> +futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
> +                             u32 oldval, u32 newval)
>  {
> -       int prev, cmp;
> +       int ret = 0, cmp;
> +       u32 prev;
>
> -       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
> +       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
>                return -EFAULT;
>
> -       __asm__ __volatile__ ("1:       lwx     %0, %2, r0;             \
> -                                       cmp     %1, %0, %3;             \
> -                                       beqi    %1, 3f;                 \
> -                               2:      swx     %4, %2, r0;             \
> -                                       addic   %1, r0, 0;              \
> -                                       bnei    %1, 1b;                 \
> +       __asm__ __volatile__ ("1:       lwx     %1, %3, r0;             \
> +                                       cmp     %2, %1, %4;             \
> +                                       beqi    %2, 3f;                 \
> +                               2:      swx     %5, %3, r0;             \
> +                                       addic   %2, r0, 0;              \
> +                                       bnei    %2, 1b;                 \
>                                3:                                      \
>                                .section .fixup,\"ax\";                 \
>                                4:      brid    3b;                     \
> -                                       addik   %0, r0, %5;             \
> +                                       addik   %0, r0, %6;             \
>                                .previous;                              \
>                                .section __ex_table,\"a\";              \
>                                .word   1b,4b,2b,4b;                    \
>                                .previous;"                             \
> -               : "=&r" (prev), "=&r"(cmp)                              \
> +               : "+r" (ret), "=&r" (prev), "=&r"(cmp)  \
>                : "r" (uaddr), "r" (oldval), "r" (newval), "i" (-EFAULT));
>
> -       return prev;
> +       *uval = prev;
> +       return ret;
>  }
>
>  #endif /* __KERNEL__ */
> diff --git a/arch/mips/include/asm/futex.h b/arch/mips/include/asm/futex.h
> index b9cce90..6ebf173 100644
> --- a/arch/mips/include/asm/futex.h
> +++ b/arch/mips/include/asm/futex.h
> @@ -75,7 +75,7 @@
>  }
>
>  static inline int
> -futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
> +futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
>  {
>        int op = (encoded_op >> 28) & 7;
>        int cmp = (encoded_op >> 24) & 15;
> @@ -85,7 +85,7 @@ futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
>        if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
>                oparg = 1 << oparg;
>
> -       if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
> +       if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
>                return -EFAULT;
>
>        pagefault_disable();
> @@ -132,11 +132,13 @@ futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
>  }
>
>  static inline int
> -futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
> +futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
> +                             u32 oldval, u32 newval)
>  {
> -       int retval;
> +       int ret = 0;
> +       u32 val;
>
> -       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
> +       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
>                return -EFAULT;
>
>        if (cpu_has_llsc && R10000_LLSC_WAR) {
> @@ -145,25 +147,25 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
>                "       .set    push                                    \n"
>                "       .set    noat                                    \n"
>                "       .set    mips3                                   \n"
> -               "1:     ll      %0, %2                                  \n"
> -               "       bne     %0, %z3, 3f                             \n"
> +               "1:     ll      %1, %3                                  \n"
> +               "       bne     %1, %z4, 3f                             \n"
>                "       .set    mips0                                   \n"
> -               "       move    $1, %z4                                 \n"
> +               "       move    $1, %z5                                 \n"
>                "       .set    mips3                                   \n"
> -               "2:     sc      $1, %1                                  \n"
> +               "2:     sc      $1, %2                                  \n"
>                "       beqzl   $1, 1b                                  \n"
>                __WEAK_LLSC_MB
>                "3:                                                     \n"
>                "       .set    pop                                     \n"
>                "       .section .fixup,\"ax\"                          \n"
> -               "4:     li      %0, %5                                  \n"
> +               "4:     li      %0, %6                                  \n"
>                "       j       3b                                      \n"
>                "       .previous                                       \n"
>                "       .section __ex_table,\"a\"                       \n"
>                "       "__UA_ADDR "\t1b, 4b                            \n"
>                "       "__UA_ADDR "\t2b, 4b                            \n"
>                "       .previous                                       \n"
> -               : "=&r" (retval), "=R" (*uaddr)
> +               : "+r" (ret), "=&r" (val), "=R" (*uaddr)
>                : "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT)
>                : "memory");
>        } else if (cpu_has_llsc) {
> @@ -172,31 +174,32 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
>                "       .set    push                                    \n"
>                "       .set    noat                                    \n"
>                "       .set    mips3                                   \n"
> -               "1:     ll      %0, %2                                  \n"
> -               "       bne     %0, %z3, 3f                             \n"
> +               "1:     ll      %1, %3                                  \n"
> +               "       bne     %1, %z4, 3f                             \n"
>                "       .set    mips0                                   \n"
> -               "       move    $1, %z4                                 \n"
> +               "       move    $1, %z5                                 \n"
>                "       .set    mips3                                   \n"
> -               "2:     sc      $1, %1                                  \n"
> +               "2:     sc      $1, %2                                  \n"
>                "       beqz    $1, 1b                                  \n"
>                __WEAK_LLSC_MB
>                "3:                                                     \n"
>                "       .set    pop                                     \n"
>                "       .section .fixup,\"ax\"                          \n"
> -               "4:     li      %0, %5                                  \n"
> +               "4:     li      %0, %6                                  \n"
>                "       j       3b                                      \n"
>                "       .previous                                       \n"
>                "       .section __ex_table,\"a\"                       \n"
>                "       "__UA_ADDR "\t1b, 4b                            \n"
>                "       "__UA_ADDR "\t2b, 4b                            \n"
>                "       .previous                                       \n"
> -               : "=&r" (retval), "=R" (*uaddr)
> +               : "+r" (ret), "=&r" (val), "=R" (*uaddr)
>                : "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT)
>                : "memory");
>        } else
>                return -ENOSYS;
>
> -       return retval;
> +       *uval = val;
> +       return ret;
>  }
>
>  #endif
> diff --git a/arch/parisc/include/asm/futex.h b/arch/parisc/include/asm/futex.h
> index 0c705c3..67a33cc 100644
> --- a/arch/parisc/include/asm/futex.h
> +++ b/arch/parisc/include/asm/futex.h
> @@ -8,7 +8,7 @@
>  #include <asm/errno.h>
>
>  static inline int
> -futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
> +futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
>  {
>        int op = (encoded_op >> 28) & 7;
>        int cmp = (encoded_op >> 24) & 15;
> @@ -18,7 +18,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
>        if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
>                oparg = 1 << oparg;
>
> -       if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
> +       if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
>                return -EFAULT;
>
>        pagefault_disable();
> @@ -51,10 +51,10 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
>
>  /* Non-atomic version */
>  static inline int
> -futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
> +futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
> +                             u32 oldval, u32 newval)
>  {
> -       int err = 0;
> -       int uval;
> +       u32 val;
>
>        /* futex.c wants to do a cmpxchg_inatomic on kernel NULL, which is
>         * our gateway page, and causes no end of trouble...
> @@ -62,15 +62,15 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
>        if (segment_eq(KERNEL_DS, get_fs()) && !uaddr)
>                return -EFAULT;
>
> -       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
> +       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
>                return -EFAULT;
>
> -       err = get_user(uval, uaddr);
> -       if (err) return -EFAULT;
> -       if (uval == oldval)
> -               err = put_user(newval, uaddr);
> -       if (err) return -EFAULT;
> -       return uval;
> +       if (get_user(val, uaddr))
> +               return -EFAULT;
> +       if (val == oldval && put_user(newval, uaddr))
> +               return -EFAULT;
> +       *uval = val;
> +       return 0;
>  }
>
>  #endif /*__KERNEL__*/
> diff --git a/arch/powerpc/include/asm/futex.h b/arch/powerpc/include/asm/futex.h
> index 7c589ef..c94e4a3 100644
> --- a/arch/powerpc/include/asm/futex.h
> +++ b/arch/powerpc/include/asm/futex.h
> @@ -30,7 +30,7 @@
>        : "b" (uaddr), "i" (-EFAULT), "r" (oparg) \
>        : "cr0", "memory")
>
> -static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
> +static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
>  {
>        int op = (encoded_op >> 28) & 7;
>        int cmp = (encoded_op >> 24) & 15;
> @@ -40,7 +40,7 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
>        if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
>                oparg = 1 << oparg;
>
> -       if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
> +       if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
>                return -EFAULT;
>
>        pagefault_disable();
> @@ -82,35 +82,38 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
>  }
>
>  static inline int
> -futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
> +futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
> +                             u32 oldval, u32 newval)
>  {
> -       int prev;
> +       int ret = 0;
> +       u32 prev;
>
> -       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
> +       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
>                return -EFAULT;
>
>         __asm__ __volatile__ (
>         PPC_RELEASE_BARRIER
> -"1:     lwarx   %0,0,%2         # futex_atomic_cmpxchg_inatomic\n\
> -        cmpw    0,%0,%3\n\
> +"1:     lwarx   %1,0,%3         # futex_atomic_cmpxchg_inatomic\n\
> +        cmpw    0,%1,%4\n\
>         bne-    3f\n"
> -        PPC405_ERR77(0,%2)
> -"2:     stwcx.  %4,0,%2\n\
> +        PPC405_ERR77(0,%3)
> +"2:     stwcx.  %5,0,%3\n\
>         bne-    1b\n"
>         PPC_ACQUIRE_BARRIER
>  "3:    .section .fixup,\"ax\"\n\
> -4:     li      %0,%5\n\
> +4:     li      %0,%6\n\
>        b       3b\n\
>        .previous\n\
>        .section __ex_table,\"a\"\n\
>        .align 3\n\
>        " PPC_LONG "1b,4b,2b,4b\n\
>        .previous" \
> -        : "=&r" (prev), "+m" (*uaddr)
> +        : "+r" (ret), "=&r" (prev), "+m" (*uaddr)
>         : "r" (uaddr), "r" (oldval), "r" (newval), "i" (-EFAULT)
>         : "cc", "memory");
>
> -        return prev;
> +       *uval = prev;
> +        return ret;
>  }
>
>  #endif /* __KERNEL__ */
> diff --git a/arch/s390/include/asm/futex.h b/arch/s390/include/asm/futex.h
> index 5c5d02d..81cf36b 100644
> --- a/arch/s390/include/asm/futex.h
> +++ b/arch/s390/include/asm/futex.h
> @@ -7,7 +7,7 @@
>  #include <linux/uaccess.h>
>  #include <asm/errno.h>
>
> -static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
> +static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
>  {
>        int op = (encoded_op >> 28) & 7;
>        int cmp = (encoded_op >> 24) & 15;
> @@ -18,7 +18,7 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
>        if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
>                oparg = 1 << oparg;
>
> -       if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
> +       if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
>                return -EFAULT;
>
>        pagefault_disable();
> @@ -39,13 +39,13 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
>        return ret;
>  }
>
> -static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr,
> -                                               int oldval, int newval)
> +static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
> +                                               u32 oldval, u32 newval)
>  {
> -       if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
> +       if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
>                return -EFAULT;
>
> -       return uaccess.futex_atomic_cmpxchg(uaddr, oldval, newval);
> +       return uaccess.futex_atomic_cmpxchg(uval, uaddr, oldval, newval);
>  }
>
>  #endif /* __KERNEL__ */
> diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h
> index d6b1ed0..2d9ea11f 100644
> --- a/arch/s390/include/asm/uaccess.h
> +++ b/arch/s390/include/asm/uaccess.h
> @@ -83,8 +83,8 @@ struct uaccess_ops {
>        size_t (*clear_user)(size_t, void __user *);
>        size_t (*strnlen_user)(size_t, const char __user *);
>        size_t (*strncpy_from_user)(size_t, const char __user *, char *);
> -       int (*futex_atomic_op)(int op, int __user *, int oparg, int *old);
> -       int (*futex_atomic_cmpxchg)(int __user *, int old, int new);
> +       int (*futex_atomic_op)(int op, u32 __user *, int oparg, int *old);
> +       int (*futex_atomic_cmpxchg)(u32 *, u32 __user *, u32 old, u32 new);
>  };
>
>  extern struct uaccess_ops uaccess;
> diff --git a/arch/s390/lib/uaccess.h b/arch/s390/lib/uaccess.h
> index 126011d..1d2536c 100644
> --- a/arch/s390/lib/uaccess.h
> +++ b/arch/s390/lib/uaccess.h
> @@ -12,12 +12,12 @@ extern size_t copy_from_user_std(size_t, const void __user *, void *);
>  extern size_t copy_to_user_std(size_t, void __user *, const void *);
>  extern size_t strnlen_user_std(size_t, const char __user *);
>  extern size_t strncpy_from_user_std(size_t, const char __user *, char *);
> -extern int futex_atomic_cmpxchg_std(int __user *, int, int);
> -extern int futex_atomic_op_std(int, int __user *, int, int *);
> +extern int futex_atomic_cmpxchg_std(u32 *, u32 __user *, u32, u32);
> +extern int futex_atomic_op_std(int, u32 __user *, int, int *);
>
>  extern size_t copy_from_user_pt(size_t, const void __user *, void *);
>  extern size_t copy_to_user_pt(size_t, void __user *, const void *);
> -extern int futex_atomic_op_pt(int, int __user *, int, int *);
> -extern int futex_atomic_cmpxchg_pt(int __user *, int, int);
> +extern int futex_atomic_op_pt(int, u32 __user *, int, int *);
> +extern int futex_atomic_cmpxchg_pt(u32 *, u32 __user *, u32, u32);
>
>  #endif /* __ARCH_S390_LIB_UACCESS_H */
> diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c
> index 404f2de..afc716a 100644
> --- a/arch/s390/lib/uaccess_pt.c
> +++ b/arch/s390/lib/uaccess_pt.c
> @@ -302,7 +302,7 @@ fault:
>                     : "0" (-EFAULT), "d" (oparg), "a" (uaddr),         \
>                       "m" (*uaddr) : "cc" );
>
> -static int __futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old)
> +static int __futex_atomic_op_pt(int op, u32 __user *uaddr, int oparg, int *old)
>  {
>        int oldval = 0, newval, ret;
>
> @@ -335,7 +335,7 @@ static int __futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old)
>        return ret;
>  }
>
> -int futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old)
> +int futex_atomic_op_pt(int op, u32 __user *uaddr, int oparg, int *old)
>  {
>        int ret;
>
> @@ -354,26 +354,29 @@ int futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old)
>        return ret;
>  }
>
> -static int __futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval)
> +static int __futex_atomic_cmpxchg_pt(u32 *uval, u32 __user *uaddr,
> +                                    u32 oldval, u32 newval)
>  {
>        int ret;
>
>        asm volatile("0: cs   %1,%4,0(%5)\n"
> -                    "1: lr   %0,%1\n"
> +                    "1: la   %0,0\n"
>                     "2:\n"
>                     EX_TABLE(0b,2b) EX_TABLE(1b,2b)
>                     : "=d" (ret), "+d" (oldval), "=m" (*uaddr)
>                     : "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr)
>                     : "cc", "memory" );
> +       *uval = oldval;
>        return ret;
>  }
>
> -int futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval)
> +int futex_atomic_cmpxchg_pt(int *uval, int __user *uaddr,
> +                           int oldval, int newval)
>  {
>        int ret;
>
>        if (segment_eq(get_fs(), KERNEL_DS))
> -               return __futex_atomic_cmpxchg_pt(uaddr, oldval, newval);
> +               return __futex_atomic_cmpxchg_pt(uval, uaddr, oldval, newval);
>        spin_lock(&current->mm->page_table_lock);
>        uaddr = (int __user *) __dat_user_addr((unsigned long) uaddr);
>        if (!uaddr) {
> @@ -382,7 +385,7 @@ int futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval)
>        }
>        get_page(virt_to_page(uaddr));
>        spin_unlock(&current->mm->page_table_lock);
> -       ret = __futex_atomic_cmpxchg_pt(uaddr, oldval, newval);
> +       ret = __futex_atomic_cmpxchg_pt(uval, uaddr, oldval, newval);
>        put_page(virt_to_page(uaddr));
>        return ret;
>  }
> diff --git a/arch/s390/lib/uaccess_std.c b/arch/s390/lib/uaccess_std.c
> index a6c4f7e..bb1a7ee 100644
> --- a/arch/s390/lib/uaccess_std.c
> +++ b/arch/s390/lib/uaccess_std.c
> @@ -255,7 +255,7 @@ size_t strncpy_from_user_std(size_t size, const char __user *src, char *dst)
>                : "0" (-EFAULT), "d" (oparg), "a" (uaddr),              \
>                  "m" (*uaddr) : "cc");
>
> -int futex_atomic_op_std(int op, int __user *uaddr, int oparg, int *old)
> +int futex_atomic_op_std(int op, u32 __user *uaddr, int oparg, int *old)
>  {
>        int oldval = 0, newval, ret;
>
> @@ -287,19 +287,21 @@ int futex_atomic_op_std(int op, int __user *uaddr, int oparg, int *old)
>        return ret;
>  }
>
> -int futex_atomic_cmpxchg_std(int __user *uaddr, int oldval, int newval)
> +int futex_atomic_cmpxchg_std(u32 *uval, u32 __user *uaddr,
> +                            u32 oldval, u32 newval)
>  {
>        int ret;
>
>        asm volatile(
>                "   sacf 256\n"
>                "0: cs   %1,%4,0(%5)\n"
> -               "1: lr   %0,%1\n"
> +               "1: la   %0,0\n"
>                "2: sacf 0\n"
>                EX_TABLE(0b,2b) EX_TABLE(1b,2b)
>                : "=d" (ret), "+d" (oldval), "=m" (*uaddr)
>                : "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr)
>                : "cc", "memory" );
> +       *uval = oldval;
>        return ret;
>  }
>
> diff --git a/arch/sh/include/asm/futex-irq.h b/arch/sh/include/asm/futex-irq.h
> index a9f16a7..6cb9f19 100644
> --- a/arch/sh/include/asm/futex-irq.h
> +++ b/arch/sh/include/asm/futex-irq.h
> @@ -3,7 +3,7 @@
>
>  #include <asm/system.h>
>
> -static inline int atomic_futex_op_xchg_set(int oparg, int __user *uaddr,
> +static inline int atomic_futex_op_xchg_set(int oparg, u32 __user *uaddr,
>                                           int *oldval)
>  {
>        unsigned long flags;
> @@ -20,7 +20,7 @@ static inline int atomic_futex_op_xchg_set(int oparg, int __user *uaddr,
>        return ret;
>  }
>
> -static inline int atomic_futex_op_xchg_add(int oparg, int __user *uaddr,
> +static inline int atomic_futex_op_xchg_add(int oparg, u32 __user *uaddr,
>                                           int *oldval)
>  {
>        unsigned long flags;
> @@ -37,7 +37,7 @@ static inline int atomic_futex_op_xchg_add(int oparg, int __user *uaddr,
>        return ret;
>  }
>
> -static inline int atomic_futex_op_xchg_or(int oparg, int __user *uaddr,
> +static inline int atomic_futex_op_xchg_or(int oparg, u32 __user *uaddr,
>                                          int *oldval)
>  {
>        unsigned long flags;
> @@ -54,7 +54,7 @@ static inline int atomic_futex_op_xchg_or(int oparg, int __user *uaddr,
>        return ret;
>  }
>
> -static inline int atomic_futex_op_xchg_and(int oparg, int __user *uaddr,
> +static inline int atomic_futex_op_xchg_and(int oparg, u32 __user *uaddr,
>                                           int *oldval)
>  {
>        unsigned long flags;
> @@ -71,7 +71,7 @@ static inline int atomic_futex_op_xchg_and(int oparg, int __user *uaddr,
>        return ret;
>  }
>
> -static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr,
> +static inline int atomic_futex_op_xchg_xor(int oparg, u32 __user *uaddr,
>                                           int *oldval)
>  {
>        unsigned long flags;
> @@ -88,11 +88,13 @@ static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr,
>        return ret;
>  }
>
> -static inline int atomic_futex_op_cmpxchg_inatomic(int __user *uaddr,
> -                                                  int oldval, int newval)
> +static inline int atomic_futex_op_cmpxchg_inatomic(u32 *uval,
> +                                                  u32 __user *uaddr,
> +                                                  u32 oldval, u32 newval)
>  {
>        unsigned long flags;
> -       int ret, prev = 0;
> +       int ret;
> +       u32 prev = 0;
>
>        local_irq_save(flags);
>
> @@ -102,10 +104,8 @@ static inline int atomic_futex_op_cmpxchg_inatomic(int __user *uaddr,
>
>        local_irq_restore(flags);
>
> -       if (ret)
> -               return ret;
> -
> -       return prev;
> +       *uval = prev;
> +       return ret;
>  }
>
>  #endif /* __ASM_SH_FUTEX_IRQ_H */
> diff --git a/arch/sh/include/asm/futex.h b/arch/sh/include/asm/futex.h
> index 68256ec..7be39a6 100644
> --- a/arch/sh/include/asm/futex.h
> +++ b/arch/sh/include/asm/futex.h
> @@ -10,7 +10,7 @@
>  /* XXX: UP variants, fix for SH-4A and SMP.. */
>  #include <asm/futex-irq.h>
>
> -static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
> +static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
>  {
>        int op = (encoded_op >> 28) & 7;
>        int cmp = (encoded_op >> 24) & 15;
> @@ -21,7 +21,7 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
>        if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
>                oparg = 1 << oparg;
>
> -       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
> +       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
>                return -EFAULT;
>
>        pagefault_disable();
> @@ -65,12 +65,13 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
>  }
>
>  static inline int
> -futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
> +futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
> +                             u32 oldval, u32 newval)
>  {
> -       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
> +       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
>                return -EFAULT;
>
> -       return atomic_futex_op_cmpxchg_inatomic(uaddr, oldval, newval);
> +       return atomic_futex_op_cmpxchg_inatomic(uval, uaddr, oldval, newval);
>  }
>
>  #endif /* __KERNEL__ */
> diff --git a/arch/sparc/include/asm/futex_64.h b/arch/sparc/include/asm/futex_64.h
> index 47f9583..444e7be 100644
> --- a/arch/sparc/include/asm/futex_64.h
> +++ b/arch/sparc/include/asm/futex_64.h
> @@ -30,7 +30,7 @@
>        : "r" (uaddr), "r" (oparg), "i" (-EFAULT)       \
>        : "memory")
>
> -static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
> +static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
>  {
>        int op = (encoded_op >> 28) & 7;
>        int cmp = (encoded_op >> 24) & 15;
> @@ -38,7 +38,7 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
>        int cmparg = (encoded_op << 20) >> 20;
>        int oldval = 0, ret, tem;
>
> -       if (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(int))))
> +       if (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))))
>                return -EFAULT;
>        if (unlikely((((unsigned long) uaddr) & 0x3UL)))
>                return -EINVAL;
> @@ -85,26 +85,30 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
>  }
>
>  static inline int
> -futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
> +futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
> +                             u32 oldval, u32 newval)
>  {
> +       int ret = 0;
> +
>        __asm__ __volatile__(
> -       "\n1:   casa    [%3] %%asi, %2, %0\n"
> +       "\n1:   casa    [%4] %%asi, %3, %1\n"
>        "2:\n"
>        "       .section .fixup,#alloc,#execinstr\n"
>        "       .align  4\n"
>        "3:     sethi   %%hi(2b), %0\n"
>        "       jmpl    %0 + %%lo(2b), %%g0\n"
> -       "        mov    %4, %0\n"
> +       "       mov     %5, %0\n"
>        "       .previous\n"
>        "       .section __ex_table,\"a\"\n"
>        "       .align  4\n"
>        "       .word   1b, 3b\n"
>        "       .previous\n"
> -       : "=r" (newval)
> -       : "0" (newval), "r" (oldval), "r" (uaddr), "i" (-EFAULT)
> +       : "+r" (ret), "=r" (newval)
> +       : "1" (newval), "r" (oldval), "r" (uaddr), "i" (-EFAULT)
>        : "memory");
>
> -       return newval;
> +       *uval = newval;
> +       return ret;
>  }
>
>  #endif /* !(_SPARC64_FUTEX_H) */
> diff --git a/arch/tile/include/asm/futex.h b/arch/tile/include/asm/futex.h
> index fe0d10d..d03ec12 100644
> --- a/arch/tile/include/asm/futex.h
> +++ b/arch/tile/include/asm/futex.h
> @@ -29,16 +29,16 @@
>  #include <linux/uaccess.h>
>  #include <linux/errno.h>
>
> -extern struct __get_user futex_set(int __user *v, int i);
> -extern struct __get_user futex_add(int __user *v, int n);
> -extern struct __get_user futex_or(int __user *v, int n);
> -extern struct __get_user futex_andn(int __user *v, int n);
> -extern struct __get_user futex_cmpxchg(int __user *v, int o, int n);
> +extern struct __get_user futex_set(u32 __user *v, int i);
> +extern struct __get_user futex_add(u32 __user *v, int n);
> +extern struct __get_user futex_or(u32 __user *v, int n);
> +extern struct __get_user futex_andn(u32 __user *v, int n);
> +extern struct __get_user futex_cmpxchg(u32 __user *v, int o, int n);
>
>  #ifndef __tilegx__
> -extern struct __get_user futex_xor(int __user *v, int n);
> +extern struct __get_user futex_xor(u32 __user *v, int n);
>  #else
> -static inline struct __get_user futex_xor(int __user *uaddr, int n)
> +static inline struct __get_user futex_xor(u32 __user *uaddr, int n)
>  {
>        struct __get_user asm_ret = __get_user_4(uaddr);
>        if (!asm_ret.err) {
> @@ -53,7 +53,7 @@ static inline struct __get_user futex_xor(int __user *uaddr, int n)
>  }
>  #endif
>
> -static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
> +static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
>  {
>        int op = (encoded_op >> 28) & 7;
>        int cmp = (encoded_op >> 24) & 15;
> @@ -65,7 +65,7 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
>        if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
>                oparg = 1 << oparg;
>
> -       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
> +       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
>                return -EFAULT;
>
>        pagefault_disable();
> @@ -119,16 +119,17 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
>        return ret;
>  }
>
> -static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval,
> -                                               int newval)
> +static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
> +                                               u32 oldval, u32 newval)
>  {
>        struct __get_user asm_ret;
>
> -       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
> +       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
>                return -EFAULT;
>
>        asm_ret = futex_cmpxchg(uaddr, oldval, newval);
> -       return asm_ret.err ? asm_ret.err : asm_ret.val;
> +       *uval = asm_ret.val;
> +       return asm_ret.err;
>  }
>
>  #ifndef __tilegx__
> diff --git a/arch/x86/include/asm/futex.h b/arch/x86/include/asm/futex.h
> index 1f11ce4..d09bb03 100644
> --- a/arch/x86/include/asm/futex.h
> +++ b/arch/x86/include/asm/futex.h
> @@ -37,7 +37,7 @@
>                       "+m" (*uaddr), "=&r" (tem)               \
>                     : "r" (oparg), "i" (-EFAULT), "1" (0))
>
> -static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
> +static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
>  {
>        int op = (encoded_op >> 28) & 7;
>        int cmp = (encoded_op >> 24) & 15;
> @@ -48,7 +48,7 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
>        if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
>                oparg = 1 << oparg;
>
> -       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
> +       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
>                return -EFAULT;
>
>  #if defined(CONFIG_X86_32) && !defined(CONFIG_X86_BSWAP)
> @@ -109,9 +109,10 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
>        return ret;
>  }
>
> -static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval,
> -                                               int newval)
> +static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
> +                                               u32 oldval, u32 newval)
>  {
> +       int ret = 0;
>
>  #if defined(CONFIG_X86_32) && !defined(CONFIG_X86_BSWAP)
>        /* Real i386 machines have no cmpxchg instruction */
> @@ -119,21 +120,22 @@ static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval,
>                return -ENOSYS;
>  #endif
>
> -       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
> +       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
>                return -EFAULT;
>
> -       asm volatile("1:\t" LOCK_PREFIX "cmpxchgl %3, %1\n"
> +       asm volatile("1:\t" LOCK_PREFIX "cmpxchgl %4, %2\n"
>                     "2:\t.section .fixup, \"ax\"\n"
> -                    "3:\tmov     %2, %0\n"
> +                    "3:\tmov     %3, %0\n"
>                     "\tjmp     2b\n"
>                     "\t.previous\n"
>                     _ASM_EXTABLE(1b, 3b)
> -                    : "=a" (oldval), "+m" (*uaddr)
> -                    : "i" (-EFAULT), "r" (newval), "0" (oldval)
> +                    : "+r" (ret), "=a" (oldval), "+m" (*uaddr)
> +                    : "i" (-EFAULT), "r" (newval), "1" (oldval)
>                     : "memory"
>        );
>
> -       return oldval;
> +       *uval = oldval;
> +       return ret;
>  }
>
>  #endif
> diff --git a/include/asm-generic/futex.h b/include/asm-generic/futex.h
> index 3c2344f..01f227e 100644
> --- a/include/asm-generic/futex.h
> +++ b/include/asm-generic/futex.h
> @@ -6,7 +6,7 @@
>  #include <asm/errno.h>
>
>  static inline int
> -futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
> +futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
>  {
>        int op = (encoded_op >> 28) & 7;
>        int cmp = (encoded_op >> 24) & 15;
> @@ -16,7 +16,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
>        if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
>                oparg = 1 << oparg;
>
> -       if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
> +       if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
>                return -EFAULT;
>
>        pagefault_disable();
> @@ -48,7 +48,8 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
>  }
>
>  static inline int
> -futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
> +futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
> +                             u32 oldval, u32 newval)
>  {
>        return -ENOSYS;
>  }
> diff --git a/kernel/futex.c b/kernel/futex.c
> index 3184d3b..53b783f 100644
> --- a/kernel/futex.c
> +++ b/kernel/futex.c
> @@ -381,15 +381,16 @@ static struct futex_q *futex_top_waiter(struct futex_hash_bucket *hb,
>        return NULL;
>  }
>
> -static u32 cmpxchg_futex_value_locked(u32 __user *uaddr, u32 uval, u32 newval)
> +static int cmpxchg_futex_value_locked(u32 *curval, u32 __user *uaddr,
> +                                     u32 uval, u32 newval)
>  {
> -       u32 curval;
> +       int ret;
>
>        pagefault_disable();
> -       curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval);
> +       ret = futex_atomic_cmpxchg_inatomic(curval, uaddr, uval, newval);
>        pagefault_enable();
>
> -       return curval;
> +       return ret;
>  }
>
>  static int get_futex_value_locked(u32 *dest, u32 __user *from)
> @@ -688,9 +689,7 @@ retry:
>        if (set_waiters)
>                newval |= FUTEX_WAITERS;
>
> -       curval = cmpxchg_futex_value_locked(uaddr, 0, newval);
> -
> -       if (unlikely(curval == -EFAULT))
> +       if (unlikely(cmpxchg_futex_value_locked(&curval, uaddr, 0, newval)))
>                return -EFAULT;
>
>        /*
> @@ -728,9 +727,7 @@ retry:
>                lock_taken = 1;
>        }
>
> -       curval = cmpxchg_futex_value_locked(uaddr, uval, newval);
> -
> -       if (unlikely(curval == -EFAULT))
> +       if (unlikely(cmpxchg_futex_value_locked(&curval, uaddr, uval, newval)))
>                return -EFAULT;
>        if (unlikely(curval != uval))
>                goto retry;
> @@ -843,9 +840,7 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this)
>
>                newval = FUTEX_WAITERS | task_pid_vnr(new_owner);
>
> -               curval = cmpxchg_futex_value_locked(uaddr, uval, newval);
> -
> -               if (curval == -EFAULT)
> +               if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval))
>                        ret = -EFAULT;
>                else if (curval != uval)
>                        ret = -EINVAL;
> @@ -880,10 +875,8 @@ static int unlock_futex_pi(u32 __user *uaddr, u32 uval)
>         * There is no waiter, so we unlock the futex. The owner died
>         * bit has not to be preserved here. We are the owner:
>         */
> -       oldval = cmpxchg_futex_value_locked(uaddr, uval, 0);
> -
> -       if (oldval == -EFAULT)
> -               return oldval;
> +       if (cmpxchg_futex_value_locked(&oldval, uaddr, uval, 0))
> +               return -EFAULT;
>        if (oldval != uval)
>                return -EAGAIN;
>
> @@ -1578,9 +1571,7 @@ retry:
>        while (1) {
>                newval = (uval & FUTEX_OWNER_DIED) | newtid;
>
> -               curval = cmpxchg_futex_value_locked(uaddr, uval, newval);
> -
> -               if (curval == -EFAULT)
> +               if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval))
>                        goto handle_fault;
>                if (curval == uval)
>                        break;
> @@ -2073,11 +2064,9 @@ retry:
>         * again. If it succeeds then we can return without waking
>         * anyone else up:
>         */
> -       if (!(uval & FUTEX_OWNER_DIED))
> -               uval = cmpxchg_futex_value_locked(uaddr, task_pid_vnr(current), 0);
> -
> -
> -       if (unlikely(uval == -EFAULT))
> +       if (!(uval & FUTEX_OWNER_DIED) &&
> +           unlikely(cmpxchg_futex_value_locked(&uval, uaddr,
> +                                               task_pid_vnr(current), 0)))
>                goto pi_faulted;
>        /*
>         * Rare case: we managed to release the lock atomically,
> @@ -2464,9 +2453,7 @@ retry:
>                 * userspace.
>                 */
>                mval = (uval & FUTEX_WAITERS) | FUTEX_OWNER_DIED;
> -               nval = futex_atomic_cmpxchg_inatomic(uaddr, uval, mval);
> -
> -               if (nval == -EFAULT)
> +               if (futex_atomic_cmpxchg_inatomic(&nval, uaddr, uval, mval))
>                        return -1;
>
>                if (nval != uval)
> @@ -2679,8 +2666,7 @@ static int __init futex_init(void)
>         * implementation, the non-functional ones will return
>         * -ENOSYS.
>         */
> -       curval = cmpxchg_futex_value_locked(NULL, 0, 0);
> -       if (curval == -EFAULT)
> +       if (cmpxchg_futex_value_locked(&curval, NULL, 0, 0) == -EFAULT)
>                futex_cmpxchg_enabled = 1;
>
>        for (i = 0; i < ARRAY_SIZE(futex_queues); i++) {
>
>
> --
> Michel "Walken" Lespinasse
> A program is never fully debugged until the last user dies.
>



-- 
Darren Hart

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH] futex: cmpxchg_futex_value_locked API change
  2011-03-09 15:08     ` Martin Schwidefsky
@ 2011-03-09 22:17       ` Michel Lespinasse
  0 siblings, 0 replies; 42+ messages in thread
From: Michel Lespinasse @ 2011-03-09 22:17 UTC (permalink / raw)
  To: Martin Schwidefsky, Thomas Gleixner
  Cc: Darren Hart, Ingo Molnar, Peter Zijlstra, Matt Turner,
	Russell King, David Howells, Tony Luck, Michal Simek,
	Ralf Baechle, James E.J. Bottomley, Benjamin Herrenschmidt,
	Paul Mundt, David S. Miller, Chris Metcalf, Andrew Morton,
	Linus Torvalds, LKML

On Wed, Mar 09, 2011 at 04:08:39PM +0100, Martin Schwidefsky wrote:
> On Wed, 9 Mar 2011 03:25:50 -0800
> Michel Lespinasse <walken@google.com> wrote:
> > All right. Attaching updated version of the diff. I also fixed the s390
> > issue reported by Martin Schwidefsky.
> 
> The inline assmeblies look good now but I get this compile error on s390:
> 
>   CC      arch/s390/lib/uaccess_pt.o
> arch/s390/lib/uaccess_pt.c:373: error: conflicting types for 'futex_atomic_cmpxchg_pt'
> arch/s390/lib/uaccess.h:21: note: previous declaration of 'futex_atomic_cmpxchg_pt' was here
> arch/s390/lib/uaccess_pt.c:403: warning: initialization from incompatible pointer type
> make[1]: *** [arch/s390/lib/uaccess_pt.o] Error 1

My bad. Somehow I made the change in arch/s390/lib/uaccess_std.c but missed
it in arch/s390/lib/uaccess_pt.c ... Attached patch below goes on top of
the previous changes - Thomas, if you have picked the previous patch,
please squash this one on top of it :)

Signed-off-by: Michel Lespinasse <walken@google.com>

diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c
index afc716a..7483383 100644
--- a/arch/s390/lib/uaccess_pt.c
+++ b/arch/s390/lib/uaccess_pt.c
@@ -370,8 +370,8 @@ static int __futex_atomic_cmpxchg_pt(u32 *uval, u32 __user *uaddr,
 	return ret;
 }
 
-int futex_atomic_cmpxchg_pt(int *uval, int __user *uaddr,
-			    int oldval, int newval)
+int futex_atomic_cmpxchg_pt(u32 *uval, u32 __user *uaddr,
+			    u32 oldval, u32 newval)
 {
 	int ret;
 

-- 
Michel "Walken" Lespinasse
A program is never fully debugged until the last user dies.

^ permalink raw reply related	[flat|nested] 42+ messages in thread

* Re: [PATCH] futex: cmpxchg_futex_value_locked API change
  2011-03-09 11:25   ` Michel Lespinasse
                       ` (2 preceding siblings ...)
  2011-03-09 17:50     ` Darren Hart
@ 2011-03-10 18:55     ` Thomas Gleixner
  2011-03-11  2:16       ` Michel Lespinasse
  3 siblings, 1 reply; 42+ messages in thread
From: Thomas Gleixner @ 2011-03-10 18:55 UTC (permalink / raw)
  To: Michel Lespinasse
  Cc: Darren Hart, Ingo Molnar, Peter Zijlstra, Matt Turner,
	Russell King, David Howells, Tony Luck, Michal Simek,
	Ralf Baechle, James E.J. Bottomley, Benjamin Herrenschmidt,
	Martin Schwidefsky, Paul Mundt, David S. Miller, Chris Metcalf,
	Andrew Morton, Linus Torvalds, LKML

On Wed, 9 Mar 2011, Michel Lespinasse wrote:
> On Tue, Mar 08, 2011 at 09:17:11PM +0100, Thomas Gleixner wrote:

Just looked at it again in detail before picking it up. Can we please
separate the s/int/u32/ changes from the real API change ?

>  
> -	pagefault_disable();	/* implies preempt_disable() */
> +	/* Note that preemption is disabled by futex_atomic_cmpxchg_inatomic
> +	 * call sites. */

That wants to be a separate patch as well.
  
> -int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
> +int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
>  {
>  	int op = (encoded_op >> 28) & 7;
>  	int cmp = (encoded_op >> 24) & 15;
> @@ -197,7 +197,7 @@ int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
>  	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
>  		oparg = 1 << oparg;
>  
> -	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
> +	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
>  		return -EFAULT;
>  
>  	pagefault_disable();

So following the reasoning above, shouldn't that be the same for
futex_atomic_op_inuser() ?

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH] futex: cmpxchg_futex_value_locked API change
  2011-03-10 18:55     ` Thomas Gleixner
@ 2011-03-11  2:16       ` Michel Lespinasse
  2011-03-11  2:47         ` [PATCH 1/3] futex: do not pagefault_disable in futex_atomic_cmpxchg_inatomic() Michel Lespinasse
                           ` (2 more replies)
  0 siblings, 3 replies; 42+ messages in thread
From: Michel Lespinasse @ 2011-03-11  2:16 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Darren Hart, Ingo Molnar, Peter Zijlstra, Matt Turner,
	Russell King, David Howells, Tony Luck, Michal Simek,
	Ralf Baechle, James E.J. Bottomley, Benjamin Herrenschmidt,
	Martin Schwidefsky, Paul Mundt, David S. Miller, Chris Metcalf,
	Andrew Morton, Linus Torvalds, LKML

On Thu, Mar 10, 2011 at 07:55:05PM +0100, Thomas Gleixner wrote:
> On Wed, 9 Mar 2011, Michel Lespinasse wrote:
> > On Tue, Mar 08, 2011 at 09:17:11PM +0100, Thomas Gleixner wrote:
> 
> Just looked at it again in detail before picking it up. Can we please
> separate the s/int/u32/ changes from the real API change ?
> 
> > -	pagefault_disable();	/* implies preempt_disable() */
> > +	/* Note that preemption is disabled by futex_atomic_cmpxchg_inatomic
> > +	 * call sites. */
> 
> That wants to be a separate patch as well.

No problems. That makes it 3 patches, will send as replies to this.

> > -int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
> > +int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
> >  {
> >  	int op = (encoded_op >> 28) & 7;
> >  	int cmp = (encoded_op >> 24) & 15;
> > @@ -197,7 +197,7 @@ int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
> >  	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
> >  		oparg = 1 << oparg;
> >  
> > -	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
> > +	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
> >  		return -EFAULT;
> >  
> >  	pagefault_disable();
> 
> So following the reasoning above, shouldn't that be the same for
> futex_atomic_op_inuser() ?

futex_atomic_op_inuser() is currently called by core futex code with
page faults enabled. I think that's OK - for futex_atomic_cmpxchg_inatomic
I fixed the arm implementation because it was inconsistent with the
other ones, but for futex_atomic_op_inuser() every arch does it
that way.

-- 
Michel "Walken" Lespinasse
A program is never fully debugged until the last user dies.

^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 1/3] futex: do not pagefault_disable in futex_atomic_cmpxchg_inatomic()
  2011-03-11  2:16       ` Michel Lespinasse
@ 2011-03-11  2:47         ` Michel Lespinasse
  2011-03-11 11:31           ` [tip:core/futexes] futex: Remove redundant " tip-bot for Michel Lespinasse
  2011-03-13 22:49           ` [PATCH 1/3] futex: do not " Linus Torvalds
  2011-03-11  2:48         ` [PATCH 2/3] futex: cmpxchg_futex_value_locked API change Michel Lespinasse
  2011-03-11  2:50         ` [PATCH 3/3] futex: fix futex operation types Michel Lespinasse
  2 siblings, 2 replies; 42+ messages in thread
From: Michel Lespinasse @ 2011-03-11  2:47 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Darren Hart, Ingo Molnar, Peter Zijlstra, Matt Turner,
	Russell King, David Howells, Tony Luck, Michal Simek,
	Ralf Baechle, James E.J. Bottomley, Benjamin Herrenschmidt,
	Martin Schwidefsky, Paul Mundt, David S. Miller, Chris Metcalf,
	Andrew Morton, Linus Torvalds, LKML

kernel/futex.c disables page faults before calling
futex_atomic_cmpxchg_inatomic(), so there is no need to do it again
within that function.
    
Signed-off-by: Michel Lespinasse <walken@google.com>

diff --git a/arch/arm/include/asm/futex.h b/arch/arm/include/asm/futex.h
index b33fe70..7133a86 100644
--- a/arch/arm/include/asm/futex.h
+++ b/arch/arm/include/asm/futex.h
@@ -95,7 +95,8 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
 	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
 		return -EFAULT;
 
-	pagefault_disable();	/* implies preempt_disable() */
+	/* Note that preemption is disabled by futex_atomic_cmpxchg_inatomic
+	 * call sites. */
 
 	__asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n"
 	"1:	" T(ldr) "	%0, [%3]\n"
@@ -115,8 +116,6 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
 	: "r" (oldval), "r" (newval), "r" (uaddr), "Ir" (-EFAULT)
 	: "cc", "memory");
 
-	pagefault_enable();	/* subsumes preempt_enable() */
-
 	return val;
 }
 
-- 
Michel "Walken" Lespinasse
A program is never fully debugged until the last user dies.

^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 2/3] futex: cmpxchg_futex_value_locked API change
  2011-03-11  2:16       ` Michel Lespinasse
  2011-03-11  2:47         ` [PATCH 1/3] futex: do not pagefault_disable in futex_atomic_cmpxchg_inatomic() Michel Lespinasse
@ 2011-03-11  2:48         ` Michel Lespinasse
  2011-03-11 11:31           ` [tip:core/futexes] futex: Sanitize cmpxchg_futex_value_locked API tip-bot for Michel Lespinasse
  2012-03-05  0:01             ` Jonathan Nieder
  2011-03-11  2:50         ` [PATCH 3/3] futex: fix futex operation types Michel Lespinasse
  2 siblings, 2 replies; 42+ messages in thread
From: Michel Lespinasse @ 2011-03-11  2:48 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Darren Hart, Ingo Molnar, Peter Zijlstra, Matt Turner,
	Russell King, David Howells, Tony Luck, Michal Simek,
	Ralf Baechle, James E.J. Bottomley, Benjamin Herrenschmidt,
	Martin Schwidefsky, Paul Mundt, David S. Miller, Chris Metcalf,
	Andrew Morton, Linus Torvalds, LKML

The cmpxchg_futex_value_locked API was funny in that it returned either
the original, user-exposed futex value OR an error code such as -EFAULT.
This was confusing at best, and could be a source of livelocks in places
that retry the cmpxchg_futex_value_locked after trying to fix the issue
by running fault_in_user_writeable().
    
This change makes the cmpxchg_futex_value_locked API more similar to the
get_futex_value_locked one, returning an error code and updating the
original value through a reference argument.
    
Signed-off-by: Michel Lespinasse <walken@google.com>
Acked-by: Chris Metcalf <cmetcalf@tilera.com>  [tile]
Acked-by: Tony Luck <tony.luck@intel.com>  [ia64]
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Michal Simek <monstr@monstr.eu>  [microblaze]

diff --git a/arch/alpha/include/asm/futex.h b/arch/alpha/include/asm/futex.h
index 945de22..c4e5c28 100644
--- a/arch/alpha/include/asm/futex.h
+++ b/arch/alpha/include/asm/futex.h
@@ -81,21 +81,22 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
+			      int oldval, int newval)
 {
-	int prev, cmp;
+	int ret = 0, prev, cmp;
 
 	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
 		return -EFAULT;
 
 	__asm__ __volatile__ (
 		__ASM_SMP_MB
-	"1:	ldl_l	%0,0(%2)\n"
-	"	cmpeq	%0,%3,%1\n"
-	"	beq	%1,3f\n"
-	"	mov	%4,%1\n"
-	"2:	stl_c	%1,0(%2)\n"
-	"	beq	%1,4f\n"
+	"1:	ldl_l	%1,0(%3)\n"
+	"	cmpeq	%1,%4,%2\n"
+	"	beq	%2,3f\n"
+	"	mov	%5,%2\n"
+	"2:	stl_c	%2,0(%3)\n"
+	"	beq	%2,4f\n"
 	"3:	.subsection 2\n"
 	"4:	br	1b\n"
 	"	.previous\n"
@@ -105,11 +106,12 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
 	"	.long	2b-.\n"
 	"	lda	$31,3b-2b(%0)\n"
 	"	.previous\n"
-	:	"=&r"(prev), "=&r"(cmp)
+	:	"+r"(ret), "=&r"(prev), "=&r"(cmp)
 	:	"r"(uaddr), "r"((long)oldval), "r"(newval)
 	:	"memory");
 
-	return prev;
+	*uval = prev;
+	return ret;
 }
 
 #endif /* __KERNEL__ */
diff --git a/arch/arm/include/asm/futex.h b/arch/arm/include/asm/futex.h
index 7133a86..d20b78f 100644
--- a/arch/arm/include/asm/futex.h
+++ b/arch/arm/include/asm/futex.h
@@ -88,9 +88,10 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
+			      int oldval, int newval)
 {
-	int val;
+	int ret = 0, val;
 
 	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
 		return -EFAULT;
@@ -99,24 +100,25 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
 	 * call sites. */
 
 	__asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n"
-	"1:	" T(ldr) "	%0, [%3]\n"
-	"	teq	%0, %1\n"
+	"1:	" T(ldr) "	%1, [%4]\n"
+	"	teq	%1, %2\n"
 	"	it	eq	@ explicit IT needed for the 2b label\n"
-	"2:	" T(streq) "	%2, [%3]\n"
+	"2:	" T(streq) "	%3, [%4]\n"
 	"3:\n"
 	"	.pushsection __ex_table,\"a\"\n"
 	"	.align	3\n"
 	"	.long	1b, 4f, 2b, 4f\n"
 	"	.popsection\n"
 	"	.pushsection .fixup,\"ax\"\n"
-	"4:	mov	%0, %4\n"
+	"4:	mov	%0, %5\n"
 	"	b	3b\n"
 	"	.popsection"
-	: "=&r" (val)
+	: "+r" (ret), "=&r" (val)
 	: "r" (oldval), "r" (newval), "r" (uaddr), "Ir" (-EFAULT)
 	: "cc", "memory");
 
-	return val;
+	*uval = val;
+	return ret;
 }
 
 #endif /* !SMP */
diff --git a/arch/frv/include/asm/futex.h b/arch/frv/include/asm/futex.h
index 08b3d1d..0548f8e 100644
--- a/arch/frv/include/asm/futex.h
+++ b/arch/frv/include/asm/futex.h
@@ -10,7 +10,8 @@
 extern int futex_atomic_op_inuser(int encoded_op, int __user *uaddr);
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
+			      int oldval, int newval)
 {
 	return -ENOSYS;
 }
diff --git a/arch/ia64/include/asm/futex.h b/arch/ia64/include/asm/futex.h
index c7f0f06..b072840 100644
--- a/arch/ia64/include/asm/futex.h
+++ b/arch/ia64/include/asm/futex.h
@@ -100,23 +100,26 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
+			      int oldval, int newval)
 {
 	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
 		return -EFAULT;
 
 	{
-		register unsigned long r8 __asm ("r8");
+		register unsigned long r8 __asm ("r8") = 0;
+		unsigned long prev;
 		__asm__ __volatile__(
 			"	mf;;					\n"
 			"	mov ar.ccv=%3;;				\n"
 			"[1:]	cmpxchg4.acq %0=[%1],%2,ar.ccv		\n"
 			"	.xdata4 \"__ex_table\", 1b-., 2f-.	\n"
 			"[2:]"
-			: "=r" (r8)
+			: "=r" (prev)
 			: "r" (uaddr), "r" (newval),
 			  "rO" ((long) (unsigned) oldval)
 			: "memory");
+		*uval = prev;
 		return r8;
 	}
 }
diff --git a/arch/microblaze/include/asm/futex.h b/arch/microblaze/include/asm/futex.h
index ad3fd61..fa019ed 100644
--- a/arch/microblaze/include/asm/futex.h
+++ b/arch/microblaze/include/asm/futex.h
@@ -94,31 +94,33 @@ futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
+			      int oldval, int newval)
 {
-	int prev, cmp;
+	int ret = 0, prev, cmp;
 
 	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
 		return -EFAULT;
 
-	__asm__ __volatile__ ("1:	lwx	%0, %2, r0;		\
-					cmp	%1, %0, %3;		\
-					beqi	%1, 3f;			\
-				2:	swx	%4, %2, r0;		\
-					addic	%1, r0, 0;		\
-					bnei	%1, 1b;			\
+	__asm__ __volatile__ ("1:	lwx	%1, %3, r0;		\
+					cmp	%2, %1, %4;		\
+					beqi	%2, 3f;			\
+				2:	swx	%5, %3, r0;		\
+					addic	%2, r0, 0;		\
+					bnei	%2, 1b;			\
 				3:					\
 				.section .fixup,\"ax\";			\
 				4:	brid	3b;			\
-					addik	%0, r0, %5;		\
+					addik	%0, r0, %6;		\
 				.previous;				\
 				.section __ex_table,\"a\";		\
 				.word	1b,4b,2b,4b;			\
 				.previous;"				\
-		: "=&r" (prev), "=&r"(cmp)				\
+		: "+r" (ret), "=&r" (prev), "=&r"(cmp)	\
 		: "r" (uaddr), "r" (oldval), "r" (newval), "i" (-EFAULT));
 
-	return prev;
+	*uval = prev;
+	return ret;
 }
 
 #endif /* __KERNEL__ */
diff --git a/arch/mips/include/asm/futex.h b/arch/mips/include/asm/futex.h
index b9cce90..692a24b 100644
--- a/arch/mips/include/asm/futex.h
+++ b/arch/mips/include/asm/futex.h
@@ -132,9 +132,10 @@ futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
+			      int oldval, int newval)
 {
-	int retval;
+	int ret = 0, val;
 
 	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
 		return -EFAULT;
@@ -145,25 +146,25 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
 		"	.set	push					\n"
 		"	.set	noat					\n"
 		"	.set	mips3					\n"
-		"1:	ll	%0, %2					\n"
-		"	bne	%0, %z3, 3f				\n"
+		"1:	ll	%1, %3					\n"
+		"	bne	%1, %z4, 3f				\n"
 		"	.set	mips0					\n"
-		"	move	$1, %z4					\n"
+		"	move	$1, %z5					\n"
 		"	.set	mips3					\n"
-		"2:	sc	$1, %1					\n"
+		"2:	sc	$1, %2					\n"
 		"	beqzl	$1, 1b					\n"
 		__WEAK_LLSC_MB
 		"3:							\n"
 		"	.set	pop					\n"
 		"	.section .fixup,\"ax\"				\n"
-		"4:	li	%0, %5					\n"
+		"4:	li	%0, %6					\n"
 		"	j	3b					\n"
 		"	.previous					\n"
 		"	.section __ex_table,\"a\"			\n"
 		"	"__UA_ADDR "\t1b, 4b				\n"
 		"	"__UA_ADDR "\t2b, 4b				\n"
 		"	.previous					\n"
-		: "=&r" (retval), "=R" (*uaddr)
+		: "+r" (ret), "=&r" (val), "=R" (*uaddr)
 		: "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT)
 		: "memory");
 	} else if (cpu_has_llsc) {
@@ -172,31 +173,32 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
 		"	.set	push					\n"
 		"	.set	noat					\n"
 		"	.set	mips3					\n"
-		"1:	ll	%0, %2					\n"
-		"	bne	%0, %z3, 3f				\n"
+		"1:	ll	%1, %3					\n"
+		"	bne	%1, %z4, 3f				\n"
 		"	.set	mips0					\n"
-		"	move	$1, %z4					\n"
+		"	move	$1, %z5					\n"
 		"	.set	mips3					\n"
-		"2:	sc	$1, %1					\n"
+		"2:	sc	$1, %2					\n"
 		"	beqz	$1, 1b					\n"
 		__WEAK_LLSC_MB
 		"3:							\n"
 		"	.set	pop					\n"
 		"	.section .fixup,\"ax\"				\n"
-		"4:	li	%0, %5					\n"
+		"4:	li	%0, %6					\n"
 		"	j	3b					\n"
 		"	.previous					\n"
 		"	.section __ex_table,\"a\"			\n"
 		"	"__UA_ADDR "\t1b, 4b				\n"
 		"	"__UA_ADDR "\t2b, 4b				\n"
 		"	.previous					\n"
-		: "=&r" (retval), "=R" (*uaddr)
+		: "+r" (ret), "=&r" (val), "=R" (*uaddr)
 		: "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT)
 		: "memory");
 	} else
 		return -ENOSYS;
 
-	return retval;
+	*uval = val;
+	return ret;
 }
 
 #endif
diff --git a/arch/parisc/include/asm/futex.h b/arch/parisc/include/asm/futex.h
index 0c705c3..4c6d867 100644
--- a/arch/parisc/include/asm/futex.h
+++ b/arch/parisc/include/asm/futex.h
@@ -51,10 +51,10 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 
 /* Non-atomic version */
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
+			      int oldval, int newval)
 {
-	int err = 0;
-	int uval;
+	int val;
 
 	/* futex.c wants to do a cmpxchg_inatomic on kernel NULL, which is
 	 * our gateway page, and causes no end of trouble...
@@ -65,12 +65,12 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
 	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
 		return -EFAULT;
 
-	err = get_user(uval, uaddr);
-	if (err) return -EFAULT;
-	if (uval == oldval)
-		err = put_user(newval, uaddr);
-	if (err) return -EFAULT;
-	return uval;
+	if (get_user(val, uaddr))
+		return -EFAULT;
+	if (val == oldval && put_user(newval, uaddr))
+		return -EFAULT;
+	*uval = val;
+	return 0;
 }
 
 #endif /*__KERNEL__*/
diff --git a/arch/powerpc/include/asm/futex.h b/arch/powerpc/include/asm/futex.h
index 7c589ef..631e8da 100644
--- a/arch/powerpc/include/asm/futex.h
+++ b/arch/powerpc/include/asm/futex.h
@@ -82,35 +82,37 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
+			      int oldval, int newval)
 {
-	int prev;
+	int ret = 0, prev;
 
 	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
 		return -EFAULT;
 
         __asm__ __volatile__ (
         PPC_RELEASE_BARRIER
-"1:     lwarx   %0,0,%2         # futex_atomic_cmpxchg_inatomic\n\
-        cmpw    0,%0,%3\n\
+"1:     lwarx   %1,0,%3         # futex_atomic_cmpxchg_inatomic\n\
+        cmpw    0,%1,%4\n\
         bne-    3f\n"
-        PPC405_ERR77(0,%2)
-"2:     stwcx.  %4,0,%2\n\
+        PPC405_ERR77(0,%3)
+"2:     stwcx.  %5,0,%3\n\
         bne-    1b\n"
         PPC_ACQUIRE_BARRIER
 "3:	.section .fixup,\"ax\"\n\
-4:	li	%0,%5\n\
+4:	li	%0,%6\n\
 	b	3b\n\
 	.previous\n\
 	.section __ex_table,\"a\"\n\
 	.align 3\n\
 	" PPC_LONG "1b,4b,2b,4b\n\
 	.previous" \
-        : "=&r" (prev), "+m" (*uaddr)
+        : "+r" (ret), "=&r" (prev), "+m" (*uaddr)
         : "r" (uaddr), "r" (oldval), "r" (newval), "i" (-EFAULT)
         : "cc", "memory");
 
-        return prev;
+	*uval = prev;
+        return ret;
 }
 
 #endif /* __KERNEL__ */
diff --git a/arch/s390/include/asm/futex.h b/arch/s390/include/asm/futex.h
index 5c5d02d..27ac515 100644
--- a/arch/s390/include/asm/futex.h
+++ b/arch/s390/include/asm/futex.h
@@ -39,13 +39,13 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 	return ret;
 }
 
-static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr,
+static inline int futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
 						int oldval, int newval)
 {
 	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
 		return -EFAULT;
 
-	return uaccess.futex_atomic_cmpxchg(uaddr, oldval, newval);
+	return uaccess.futex_atomic_cmpxchg(uval, uaddr, oldval, newval);
 }
 
 #endif /* __KERNEL__ */
diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h
index d6b1ed0..549adf6 100644
--- a/arch/s390/include/asm/uaccess.h
+++ b/arch/s390/include/asm/uaccess.h
@@ -84,7 +84,7 @@ struct uaccess_ops {
 	size_t (*strnlen_user)(size_t, const char __user *);
 	size_t (*strncpy_from_user)(size_t, const char __user *, char *);
 	int (*futex_atomic_op)(int op, int __user *, int oparg, int *old);
-	int (*futex_atomic_cmpxchg)(int __user *, int old, int new);
+	int (*futex_atomic_cmpxchg)(int *, int __user *, int old, int new);
 };
 
 extern struct uaccess_ops uaccess;
diff --git a/arch/s390/lib/uaccess.h b/arch/s390/lib/uaccess.h
index 126011d..89a8067 100644
--- a/arch/s390/lib/uaccess.h
+++ b/arch/s390/lib/uaccess.h
@@ -12,12 +12,12 @@ extern size_t copy_from_user_std(size_t, const void __user *, void *);
 extern size_t copy_to_user_std(size_t, void __user *, const void *);
 extern size_t strnlen_user_std(size_t, const char __user *);
 extern size_t strncpy_from_user_std(size_t, const char __user *, char *);
-extern int futex_atomic_cmpxchg_std(int __user *, int, int);
+extern int futex_atomic_cmpxchg_std(int *, int __user *, int, int);
 extern int futex_atomic_op_std(int, int __user *, int, int *);
 
 extern size_t copy_from_user_pt(size_t, const void __user *, void *);
 extern size_t copy_to_user_pt(size_t, void __user *, const void *);
 extern int futex_atomic_op_pt(int, int __user *, int, int *);
-extern int futex_atomic_cmpxchg_pt(int __user *, int, int);
+extern int futex_atomic_cmpxchg_pt(int *, int __user *, int, int);
 
 #endif /* __ARCH_S390_LIB_UACCESS_H */
diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c
index 404f2de..b3cebcd 100644
--- a/arch/s390/lib/uaccess_pt.c
+++ b/arch/s390/lib/uaccess_pt.c
@@ -354,26 +354,29 @@ int futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old)
 	return ret;
 }
 
-static int __futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval)
+static int __futex_atomic_cmpxchg_pt(int *uval, int __user *uaddr,
+				     int oldval, int newval)
 {
 	int ret;
 
 	asm volatile("0: cs   %1,%4,0(%5)\n"
-		     "1: lr   %0,%1\n"
+		     "1: la   %0,0\n"
 		     "2:\n"
 		     EX_TABLE(0b,2b) EX_TABLE(1b,2b)
 		     : "=d" (ret), "+d" (oldval), "=m" (*uaddr)
 		     : "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr)
 		     : "cc", "memory" );
+	*uval = oldval;
 	return ret;
 }
 
-int futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval)
+int futex_atomic_cmpxchg_pt(int *uval, int __user *uaddr,
+			    int oldval, int newval)
 {
 	int ret;
 
 	if (segment_eq(get_fs(), KERNEL_DS))
-		return __futex_atomic_cmpxchg_pt(uaddr, oldval, newval);
+		return __futex_atomic_cmpxchg_pt(uval, uaddr, oldval, newval);
 	spin_lock(&current->mm->page_table_lock);
 	uaddr = (int __user *) __dat_user_addr((unsigned long) uaddr);
 	if (!uaddr) {
@@ -382,7 +385,7 @@ int futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval)
 	}
 	get_page(virt_to_page(uaddr));
 	spin_unlock(&current->mm->page_table_lock);
-	ret = __futex_atomic_cmpxchg_pt(uaddr, oldval, newval);
+	ret = __futex_atomic_cmpxchg_pt(uval, uaddr, oldval, newval);
 	put_page(virt_to_page(uaddr));
 	return ret;
 }
diff --git a/arch/s390/lib/uaccess_std.c b/arch/s390/lib/uaccess_std.c
index a6c4f7e..1d6643c 100644
--- a/arch/s390/lib/uaccess_std.c
+++ b/arch/s390/lib/uaccess_std.c
@@ -287,19 +287,21 @@ int futex_atomic_op_std(int op, int __user *uaddr, int oparg, int *old)
 	return ret;
 }
 
-int futex_atomic_cmpxchg_std(int __user *uaddr, int oldval, int newval)
+int futex_atomic_cmpxchg_std(int *uval, int __user *uaddr,
+			     int oldval, int newval)
 {
 	int ret;
 
 	asm volatile(
 		"   sacf 256\n"
 		"0: cs   %1,%4,0(%5)\n"
-		"1: lr   %0,%1\n"
+		"1: la   %0,0\n"
 		"2: sacf 0\n"
 		EX_TABLE(0b,2b) EX_TABLE(1b,2b)
 		: "=d" (ret), "+d" (oldval), "=m" (*uaddr)
 		: "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr)
 		: "cc", "memory" );
+	*uval = oldval;
 	return ret;
 }
 
diff --git a/arch/sh/include/asm/futex-irq.h b/arch/sh/include/asm/futex-irq.h
index a9f16a7..7b701cb 100644
--- a/arch/sh/include/asm/futex-irq.h
+++ b/arch/sh/include/asm/futex-irq.h
@@ -88,7 +88,8 @@ static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr,
 	return ret;
 }
 
-static inline int atomic_futex_op_cmpxchg_inatomic(int __user *uaddr,
+static inline int atomic_futex_op_cmpxchg_inatomic(int *uval,
+						   int __user *uaddr,
 						   int oldval, int newval)
 {
 	unsigned long flags;
@@ -102,10 +103,8 @@ static inline int atomic_futex_op_cmpxchg_inatomic(int __user *uaddr,
 
 	local_irq_restore(flags);
 
-	if (ret)
-		return ret;
-
-	return prev;
+	*uval = prev;
+	return ret;
 }
 
 #endif /* __ASM_SH_FUTEX_IRQ_H */
diff --git a/arch/sh/include/asm/futex.h b/arch/sh/include/asm/futex.h
index 68256ec..a8a5125 100644
--- a/arch/sh/include/asm/futex.h
+++ b/arch/sh/include/asm/futex.h
@@ -65,12 +65,13 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
+			      int oldval, int newval)
 {
 	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
 		return -EFAULT;
 
-	return atomic_futex_op_cmpxchg_inatomic(uaddr, oldval, newval);
+	return atomic_futex_op_cmpxchg_inatomic(uval, uaddr, oldval, newval);
 }
 
 #endif /* __KERNEL__ */
diff --git a/arch/sparc/include/asm/futex_64.h b/arch/sparc/include/asm/futex_64.h
index 47f9583..e086220 100644
--- a/arch/sparc/include/asm/futex_64.h
+++ b/arch/sparc/include/asm/futex_64.h
@@ -85,26 +85,30 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
+			      int oldval, int newval)
 {
+	int ret = 0;
+
 	__asm__ __volatile__(
-	"\n1:	casa	[%3] %%asi, %2, %0\n"
+	"\n1:	casa	[%4] %%asi, %3, %1\n"
 	"2:\n"
 	"	.section .fixup,#alloc,#execinstr\n"
 	"	.align	4\n"
 	"3:	sethi	%%hi(2b), %0\n"
 	"	jmpl	%0 + %%lo(2b), %%g0\n"
-	"	 mov	%4, %0\n"
+	"	mov	%5, %0\n"
 	"	.previous\n"
 	"	.section __ex_table,\"a\"\n"
 	"	.align	4\n"
 	"	.word	1b, 3b\n"
 	"	.previous\n"
-	: "=r" (newval)
-	: "0" (newval), "r" (oldval), "r" (uaddr), "i" (-EFAULT)
+	: "+r" (ret), "=r" (newval)
+	: "1" (newval), "r" (oldval), "r" (uaddr), "i" (-EFAULT)
 	: "memory");
 
-	return newval;
+	*uval = newval;
+	return ret;
 }
 
 #endif /* !(_SPARC64_FUTEX_H) */
diff --git a/arch/tile/include/asm/futex.h b/arch/tile/include/asm/futex.h
index fe0d10d..664b20a 100644
--- a/arch/tile/include/asm/futex.h
+++ b/arch/tile/include/asm/futex.h
@@ -119,8 +119,8 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 	return ret;
 }
 
-static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval,
-						int newval)
+static inline int futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
+						int oldval, int newval)
 {
 	struct __get_user asm_ret;
 
@@ -128,7 +128,8 @@ static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval,
 		return -EFAULT;
 
 	asm_ret = futex_cmpxchg(uaddr, oldval, newval);
-	return asm_ret.err ? asm_ret.err : asm_ret.val;
+	*uval = asm_ret.val;
+	return asm_ret.err;
 }
 
 #ifndef __tilegx__
diff --git a/arch/x86/include/asm/futex.h b/arch/x86/include/asm/futex.h
index 1f11ce4..884c0b5 100644
--- a/arch/x86/include/asm/futex.h
+++ b/arch/x86/include/asm/futex.h
@@ -109,9 +109,10 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 	return ret;
 }
 
-static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval,
-						int newval)
+static inline int futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
+						int oldval, int newval)
 {
+	int ret = 0;
 
 #if defined(CONFIG_X86_32) && !defined(CONFIG_X86_BSWAP)
 	/* Real i386 machines have no cmpxchg instruction */
@@ -122,18 +123,19 @@ static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval,
 	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
 		return -EFAULT;
 
-	asm volatile("1:\t" LOCK_PREFIX "cmpxchgl %3, %1\n"
+	asm volatile("1:\t" LOCK_PREFIX "cmpxchgl %4, %2\n"
 		     "2:\t.section .fixup, \"ax\"\n"
-		     "3:\tmov     %2, %0\n"
+		     "3:\tmov     %3, %0\n"
 		     "\tjmp     2b\n"
 		     "\t.previous\n"
 		     _ASM_EXTABLE(1b, 3b)
-		     : "=a" (oldval), "+m" (*uaddr)
-		     : "i" (-EFAULT), "r" (newval), "0" (oldval)
+		     : "+r" (ret), "=a" (oldval), "+m" (*uaddr)
+		     : "i" (-EFAULT), "r" (newval), "1" (oldval)
 		     : "memory"
 	);
 
-	return oldval;
+	*uval = oldval;
+	return ret;
 }
 
 #endif
diff --git a/include/asm-generic/futex.h b/include/asm-generic/futex.h
index 3c2344f..132bf52 100644
--- a/include/asm-generic/futex.h
+++ b/include/asm-generic/futex.h
@@ -48,7 +48,8 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
+			      int oldval, int newval)
 {
 	return -ENOSYS;
 }
diff --git a/kernel/futex.c b/kernel/futex.c
index 3184d3b..53b783f 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -381,15 +381,16 @@ static struct futex_q *futex_top_waiter(struct futex_hash_bucket *hb,
 	return NULL;
 }
 
-static u32 cmpxchg_futex_value_locked(u32 __user *uaddr, u32 uval, u32 newval)
+static int cmpxchg_futex_value_locked(u32 *curval, u32 __user *uaddr,
+				      u32 uval, u32 newval)
 {
-	u32 curval;
+	int ret;
 
 	pagefault_disable();
-	curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval);
+	ret = futex_atomic_cmpxchg_inatomic(curval, uaddr, uval, newval);
 	pagefault_enable();
 
-	return curval;
+	return ret;
 }
 
 static int get_futex_value_locked(u32 *dest, u32 __user *from)
@@ -688,9 +689,7 @@ retry:
 	if (set_waiters)
 		newval |= FUTEX_WAITERS;
 
-	curval = cmpxchg_futex_value_locked(uaddr, 0, newval);
-
-	if (unlikely(curval == -EFAULT))
+	if (unlikely(cmpxchg_futex_value_locked(&curval, uaddr, 0, newval)))
 		return -EFAULT;
 
 	/*
@@ -728,9 +727,7 @@ retry:
 		lock_taken = 1;
 	}
 
-	curval = cmpxchg_futex_value_locked(uaddr, uval, newval);
-
-	if (unlikely(curval == -EFAULT))
+	if (unlikely(cmpxchg_futex_value_locked(&curval, uaddr, uval, newval)))
 		return -EFAULT;
 	if (unlikely(curval != uval))
 		goto retry;
@@ -843,9 +840,7 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this)
 
 		newval = FUTEX_WAITERS | task_pid_vnr(new_owner);
 
-		curval = cmpxchg_futex_value_locked(uaddr, uval, newval);
-
-		if (curval == -EFAULT)
+		if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval))
 			ret = -EFAULT;
 		else if (curval != uval)
 			ret = -EINVAL;
@@ -880,10 +875,8 @@ static int unlock_futex_pi(u32 __user *uaddr, u32 uval)
 	 * There is no waiter, so we unlock the futex. The owner died
 	 * bit has not to be preserved here. We are the owner:
 	 */
-	oldval = cmpxchg_futex_value_locked(uaddr, uval, 0);
-
-	if (oldval == -EFAULT)
-		return oldval;
+	if (cmpxchg_futex_value_locked(&oldval, uaddr, uval, 0))
+		return -EFAULT;
 	if (oldval != uval)
 		return -EAGAIN;
 
@@ -1578,9 +1571,7 @@ retry:
 	while (1) {
 		newval = (uval & FUTEX_OWNER_DIED) | newtid;
 
-		curval = cmpxchg_futex_value_locked(uaddr, uval, newval);
-
-		if (curval == -EFAULT)
+		if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval))
 			goto handle_fault;
 		if (curval == uval)
 			break;
@@ -2073,11 +2064,9 @@ retry:
 	 * again. If it succeeds then we can return without waking
 	 * anyone else up:
 	 */
-	if (!(uval & FUTEX_OWNER_DIED))
-		uval = cmpxchg_futex_value_locked(uaddr, task_pid_vnr(current), 0);
-
-
-	if (unlikely(uval == -EFAULT))
+	if (!(uval & FUTEX_OWNER_DIED) &&
+	    unlikely(cmpxchg_futex_value_locked(&uval, uaddr,
+						task_pid_vnr(current), 0)))
 		goto pi_faulted;
 	/*
 	 * Rare case: we managed to release the lock atomically,
@@ -2464,9 +2453,7 @@ retry:
 		 * userspace.
 		 */
 		mval = (uval & FUTEX_WAITERS) | FUTEX_OWNER_DIED;
-		nval = futex_atomic_cmpxchg_inatomic(uaddr, uval, mval);
-
-		if (nval == -EFAULT)
+		if (futex_atomic_cmpxchg_inatomic(&nval, uaddr, uval, mval))
 			return -1;
 
 		if (nval != uval)
@@ -2679,8 +2666,7 @@ static int __init futex_init(void)
 	 * implementation, the non-functional ones will return
 	 * -ENOSYS.
 	 */
-	curval = cmpxchg_futex_value_locked(NULL, 0, 0);
-	if (curval == -EFAULT)
+	if (cmpxchg_futex_value_locked(&curval, NULL, 0, 0) == -EFAULT)
 		futex_cmpxchg_enabled = 1;
 
 	for (i = 0; i < ARRAY_SIZE(futex_queues); i++) {
-- 
Michel "Walken" Lespinasse
A program is never fully debugged until the last user dies.

^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 3/3] futex: fix futex operation types
  2011-03-11  2:16       ` Michel Lespinasse
  2011-03-11  2:47         ` [PATCH 1/3] futex: do not pagefault_disable in futex_atomic_cmpxchg_inatomic() Michel Lespinasse
  2011-03-11  2:48         ` [PATCH 2/3] futex: cmpxchg_futex_value_locked API change Michel Lespinasse
@ 2011-03-11  2:50         ` Michel Lespinasse
  2011-03-11 11:32           ` [tip:core/futexes] futex: Sanitize futex ops argument types tip-bot for Michel Lespinasse
  2 siblings, 1 reply; 42+ messages in thread
From: Michel Lespinasse @ 2011-03-11  2:50 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Darren Hart, Ingo Molnar, Peter Zijlstra, Matt Turner,
	Russell King, David Howells, Tony Luck, Michal Simek,
	Ralf Baechle, James E.J. Bottomley, Benjamin Herrenschmidt,
	Martin Schwidefsky, Paul Mundt, David S. Miller, Chris Metcalf,
	Andrew Morton, Linus Torvalds, LKML

Fix futex_atomic_op_inuser and futex_atomic_cmpxchg_inatomic
prototypes to use u32 types for the futex.
    
Signed-off-by: Michel Lespinasse <walken@google.com>

diff --git a/arch/alpha/include/asm/futex.h b/arch/alpha/include/asm/futex.h
index c4e5c28..e8a761a 100644
--- a/arch/alpha/include/asm/futex.h
+++ b/arch/alpha/include/asm/futex.h
@@ -29,7 +29,7 @@
 	:	"r" (uaddr), "r"(oparg)				\
 	:	"memory")
 
-static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -39,7 +39,7 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -81,12 +81,13 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
-			      int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
-	int ret = 0, prev, cmp;
+	int ret = 0, cmp;
+	u32 prev;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	__asm__ __volatile__ (
diff --git a/arch/arm/include/asm/futex.h b/arch/arm/include/asm/futex.h
index d20b78f..0e29d8e 100644
--- a/arch/arm/include/asm/futex.h
+++ b/arch/arm/include/asm/futex.h
@@ -35,7 +35,7 @@
 	: "cc", "memory")
 
 static inline int
-futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -46,7 +46,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();	/* implies preempt_disable() */
@@ -88,12 +88,13 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
-			      int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
-	int ret = 0, val;
+	int ret = 0;
+	u32 val;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	/* Note that preemption is disabled by futex_atomic_cmpxchg_inatomic
diff --git a/arch/frv/include/asm/futex.h b/arch/frv/include/asm/futex.h
index 0548f8e..4bea27f 100644
--- a/arch/frv/include/asm/futex.h
+++ b/arch/frv/include/asm/futex.h
@@ -7,11 +7,11 @@
 #include <asm/errno.h>
 #include <asm/uaccess.h>
 
-extern int futex_atomic_op_inuser(int encoded_op, int __user *uaddr);
+extern int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr);
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
-			      int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
 	return -ENOSYS;
 }
diff --git a/arch/frv/kernel/futex.c b/arch/frv/kernel/futex.c
index 14f64b0..d155ca9 100644
--- a/arch/frv/kernel/futex.c
+++ b/arch/frv/kernel/futex.c
@@ -18,7 +18,7 @@
  * the various futex operations; MMU fault checking is ignored under no-MMU
  * conditions
  */
-static inline int atomic_futex_op_xchg_set(int oparg, int __user *uaddr, int *_oldval)
+static inline int atomic_futex_op_xchg_set(int oparg, u32 __user *uaddr, int *_oldval)
 {
 	int oldval, ret;
 
@@ -50,7 +50,7 @@ static inline int atomic_futex_op_xchg_set(int oparg, int __user *uaddr, int *_o
 	return ret;
 }
 
-static inline int atomic_futex_op_xchg_add(int oparg, int __user *uaddr, int *_oldval)
+static inline int atomic_futex_op_xchg_add(int oparg, u32 __user *uaddr, int *_oldval)
 {
 	int oldval, ret;
 
@@ -83,7 +83,7 @@ static inline int atomic_futex_op_xchg_add(int oparg, int __user *uaddr, int *_o
 	return ret;
 }
 
-static inline int atomic_futex_op_xchg_or(int oparg, int __user *uaddr, int *_oldval)
+static inline int atomic_futex_op_xchg_or(int oparg, u32 __user *uaddr, int *_oldval)
 {
 	int oldval, ret;
 
@@ -116,7 +116,7 @@ static inline int atomic_futex_op_xchg_or(int oparg, int __user *uaddr, int *_ol
 	return ret;
 }
 
-static inline int atomic_futex_op_xchg_and(int oparg, int __user *uaddr, int *_oldval)
+static inline int atomic_futex_op_xchg_and(int oparg, u32 __user *uaddr, int *_oldval)
 {
 	int oldval, ret;
 
@@ -149,7 +149,7 @@ static inline int atomic_futex_op_xchg_and(int oparg, int __user *uaddr, int *_o
 	return ret;
 }
 
-static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr, int *_oldval)
+static inline int atomic_futex_op_xchg_xor(int oparg, u32 __user *uaddr, int *_oldval)
 {
 	int oldval, ret;
 
@@ -186,7 +186,7 @@ static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr, int *_o
 /*
  * do the futex operations
  */
-int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -197,7 +197,7 @@ int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
diff --git a/arch/ia64/include/asm/futex.h b/arch/ia64/include/asm/futex.h
index b072840..8428525 100644
--- a/arch/ia64/include/asm/futex.h
+++ b/arch/ia64/include/asm/futex.h
@@ -46,7 +46,7 @@ do {									\
 } while (0)
 
 static inline int
-futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -56,7 +56,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -100,10 +100,10 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
-			      int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	{
diff --git a/arch/microblaze/include/asm/futex.h b/arch/microblaze/include/asm/futex.h
index fa019ed..b0526d2 100644
--- a/arch/microblaze/include/asm/futex.h
+++ b/arch/microblaze/include/asm/futex.h
@@ -29,7 +29,7 @@
 })
 
 static inline int
-futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -39,7 +39,7 @@ futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -94,12 +94,13 @@ futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
-			      int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
-	int ret = 0, prev, cmp;
+	int ret = 0, cmp;
+	u32 prev;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	__asm__ __volatile__ ("1:	lwx	%1, %3, r0;		\
diff --git a/arch/mips/include/asm/futex.h b/arch/mips/include/asm/futex.h
index 692a24b..6ebf173 100644
--- a/arch/mips/include/asm/futex.h
+++ b/arch/mips/include/asm/futex.h
@@ -75,7 +75,7 @@
 }
 
 static inline int
-futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -85,7 +85,7 @@ futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -132,12 +132,13 @@ futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
-			      int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
-	int ret = 0, val;
+	int ret = 0;
+	u32 val;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	if (cpu_has_llsc && R10000_LLSC_WAR) {
diff --git a/arch/parisc/include/asm/futex.h b/arch/parisc/include/asm/futex.h
index 4c6d867..67a33cc 100644
--- a/arch/parisc/include/asm/futex.h
+++ b/arch/parisc/include/asm/futex.h
@@ -8,7 +8,7 @@
 #include <asm/errno.h>
 
 static inline int
-futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -18,7 +18,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -51,10 +51,10 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 
 /* Non-atomic version */
 static inline int
-futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
-			      int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
-	int val;
+	u32 val;
 
 	/* futex.c wants to do a cmpxchg_inatomic on kernel NULL, which is
 	 * our gateway page, and causes no end of trouble...
@@ -62,7 +62,7 @@ futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
 	if (segment_eq(KERNEL_DS, get_fs()) && !uaddr)
 		return -EFAULT;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	if (get_user(val, uaddr))
diff --git a/arch/powerpc/include/asm/futex.h b/arch/powerpc/include/asm/futex.h
index 631e8da..c94e4a3 100644
--- a/arch/powerpc/include/asm/futex.h
+++ b/arch/powerpc/include/asm/futex.h
@@ -30,7 +30,7 @@
 	: "b" (uaddr), "i" (-EFAULT), "r" (oparg) \
 	: "cr0", "memory")
 
-static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -40,7 +40,7 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -82,12 +82,13 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
-			      int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
-	int ret = 0, prev;
+	int ret = 0;
+	u32 prev;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
         __asm__ __volatile__ (
diff --git a/arch/s390/include/asm/futex.h b/arch/s390/include/asm/futex.h
index 27ac515..81cf36b 100644
--- a/arch/s390/include/asm/futex.h
+++ b/arch/s390/include/asm/futex.h
@@ -7,7 +7,7 @@
 #include <linux/uaccess.h>
 #include <asm/errno.h>
 
-static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -18,7 +18,7 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -39,10 +39,10 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 	return ret;
 }
 
-static inline int futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
-						int oldval, int newval)
+static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+						u32 oldval, u32 newval)
 {
-	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	return uaccess.futex_atomic_cmpxchg(uval, uaddr, oldval, newval);
diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h
index 549adf6..2d9ea11f 100644
--- a/arch/s390/include/asm/uaccess.h
+++ b/arch/s390/include/asm/uaccess.h
@@ -83,8 +83,8 @@ struct uaccess_ops {
 	size_t (*clear_user)(size_t, void __user *);
 	size_t (*strnlen_user)(size_t, const char __user *);
 	size_t (*strncpy_from_user)(size_t, const char __user *, char *);
-	int (*futex_atomic_op)(int op, int __user *, int oparg, int *old);
-	int (*futex_atomic_cmpxchg)(int *, int __user *, int old, int new);
+	int (*futex_atomic_op)(int op, u32 __user *, int oparg, int *old);
+	int (*futex_atomic_cmpxchg)(u32 *, u32 __user *, u32 old, u32 new);
 };
 
 extern struct uaccess_ops uaccess;
diff --git a/arch/s390/lib/uaccess.h b/arch/s390/lib/uaccess.h
index 89a8067..1d2536c 100644
--- a/arch/s390/lib/uaccess.h
+++ b/arch/s390/lib/uaccess.h
@@ -12,12 +12,12 @@ extern size_t copy_from_user_std(size_t, const void __user *, void *);
 extern size_t copy_to_user_std(size_t, void __user *, const void *);
 extern size_t strnlen_user_std(size_t, const char __user *);
 extern size_t strncpy_from_user_std(size_t, const char __user *, char *);
-extern int futex_atomic_cmpxchg_std(int *, int __user *, int, int);
-extern int futex_atomic_op_std(int, int __user *, int, int *);
+extern int futex_atomic_cmpxchg_std(u32 *, u32 __user *, u32, u32);
+extern int futex_atomic_op_std(int, u32 __user *, int, int *);
 
 extern size_t copy_from_user_pt(size_t, const void __user *, void *);
 extern size_t copy_to_user_pt(size_t, void __user *, const void *);
-extern int futex_atomic_op_pt(int, int __user *, int, int *);
-extern int futex_atomic_cmpxchg_pt(int *, int __user *, int, int);
+extern int futex_atomic_op_pt(int, u32 __user *, int, int *);
+extern int futex_atomic_cmpxchg_pt(u32 *, u32 __user *, u32, u32);
 
 #endif /* __ARCH_S390_LIB_UACCESS_H */
diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c
index b3cebcd..7483383 100644
--- a/arch/s390/lib/uaccess_pt.c
+++ b/arch/s390/lib/uaccess_pt.c
@@ -302,7 +302,7 @@ fault:
 		     : "0" (-EFAULT), "d" (oparg), "a" (uaddr),		\
 		       "m" (*uaddr) : "cc" );
 
-static int __futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old)
+static int __futex_atomic_op_pt(int op, u32 __user *uaddr, int oparg, int *old)
 {
 	int oldval = 0, newval, ret;
 
@@ -335,7 +335,7 @@ static int __futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old)
 	return ret;
 }
 
-int futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old)
+int futex_atomic_op_pt(int op, u32 __user *uaddr, int oparg, int *old)
 {
 	int ret;
 
@@ -354,8 +354,8 @@ int futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old)
 	return ret;
 }
 
-static int __futex_atomic_cmpxchg_pt(int *uval, int __user *uaddr,
-				     int oldval, int newval)
+static int __futex_atomic_cmpxchg_pt(u32 *uval, u32 __user *uaddr,
+				     u32 oldval, u32 newval)
 {
 	int ret;
 
@@ -370,8 +370,8 @@ static int __futex_atomic_cmpxchg_pt(int *uval, int __user *uaddr,
 	return ret;
 }
 
-int futex_atomic_cmpxchg_pt(int *uval, int __user *uaddr,
-			    int oldval, int newval)
+int futex_atomic_cmpxchg_pt(u32 *uval, u32 __user *uaddr,
+			    u32 oldval, u32 newval)
 {
 	int ret;
 
diff --git a/arch/s390/lib/uaccess_std.c b/arch/s390/lib/uaccess_std.c
index 1d6643c..bb1a7ee 100644
--- a/arch/s390/lib/uaccess_std.c
+++ b/arch/s390/lib/uaccess_std.c
@@ -255,7 +255,7 @@ size_t strncpy_from_user_std(size_t size, const char __user *src, char *dst)
 		: "0" (-EFAULT), "d" (oparg), "a" (uaddr),		\
 		  "m" (*uaddr) : "cc");
 
-int futex_atomic_op_std(int op, int __user *uaddr, int oparg, int *old)
+int futex_atomic_op_std(int op, u32 __user *uaddr, int oparg, int *old)
 {
 	int oldval = 0, newval, ret;
 
@@ -287,8 +287,8 @@ int futex_atomic_op_std(int op, int __user *uaddr, int oparg, int *old)
 	return ret;
 }
 
-int futex_atomic_cmpxchg_std(int *uval, int __user *uaddr,
-			     int oldval, int newval)
+int futex_atomic_cmpxchg_std(u32 *uval, u32 __user *uaddr,
+			     u32 oldval, u32 newval)
 {
 	int ret;
 
diff --git a/arch/sh/include/asm/futex-irq.h b/arch/sh/include/asm/futex-irq.h
index 7b701cb..6cb9f19 100644
--- a/arch/sh/include/asm/futex-irq.h
+++ b/arch/sh/include/asm/futex-irq.h
@@ -3,7 +3,7 @@
 
 #include <asm/system.h>
 
-static inline int atomic_futex_op_xchg_set(int oparg, int __user *uaddr,
+static inline int atomic_futex_op_xchg_set(int oparg, u32 __user *uaddr,
 					   int *oldval)
 {
 	unsigned long flags;
@@ -20,7 +20,7 @@ static inline int atomic_futex_op_xchg_set(int oparg, int __user *uaddr,
 	return ret;
 }
 
-static inline int atomic_futex_op_xchg_add(int oparg, int __user *uaddr,
+static inline int atomic_futex_op_xchg_add(int oparg, u32 __user *uaddr,
 					   int *oldval)
 {
 	unsigned long flags;
@@ -37,7 +37,7 @@ static inline int atomic_futex_op_xchg_add(int oparg, int __user *uaddr,
 	return ret;
 }
 
-static inline int atomic_futex_op_xchg_or(int oparg, int __user *uaddr,
+static inline int atomic_futex_op_xchg_or(int oparg, u32 __user *uaddr,
 					  int *oldval)
 {
 	unsigned long flags;
@@ -54,7 +54,7 @@ static inline int atomic_futex_op_xchg_or(int oparg, int __user *uaddr,
 	return ret;
 }
 
-static inline int atomic_futex_op_xchg_and(int oparg, int __user *uaddr,
+static inline int atomic_futex_op_xchg_and(int oparg, u32 __user *uaddr,
 					   int *oldval)
 {
 	unsigned long flags;
@@ -71,7 +71,7 @@ static inline int atomic_futex_op_xchg_and(int oparg, int __user *uaddr,
 	return ret;
 }
 
-static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr,
+static inline int atomic_futex_op_xchg_xor(int oparg, u32 __user *uaddr,
 					   int *oldval)
 {
 	unsigned long flags;
@@ -88,12 +88,13 @@ static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr,
 	return ret;
 }
 
-static inline int atomic_futex_op_cmpxchg_inatomic(int *uval,
-						   int __user *uaddr,
-						   int oldval, int newval)
+static inline int atomic_futex_op_cmpxchg_inatomic(u32 *uval,
+						   u32 __user *uaddr,
+						   u32 oldval, u32 newval)
 {
 	unsigned long flags;
-	int ret, prev = 0;
+	int ret;
+	u32 prev = 0;
 
 	local_irq_save(flags);
 
diff --git a/arch/sh/include/asm/futex.h b/arch/sh/include/asm/futex.h
index a8a5125..7be39a6 100644
--- a/arch/sh/include/asm/futex.h
+++ b/arch/sh/include/asm/futex.h
@@ -10,7 +10,7 @@
 /* XXX: UP variants, fix for SH-4A and SMP.. */
 #include <asm/futex-irq.h>
 
-static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -21,7 +21,7 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -65,10 +65,10 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
-			      int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	return atomic_futex_op_cmpxchg_inatomic(uval, uaddr, oldval, newval);
diff --git a/arch/sparc/include/asm/futex_64.h b/arch/sparc/include/asm/futex_64.h
index e086220..444e7be 100644
--- a/arch/sparc/include/asm/futex_64.h
+++ b/arch/sparc/include/asm/futex_64.h
@@ -30,7 +30,7 @@
 	: "r" (uaddr), "r" (oparg), "i" (-EFAULT)	\
 	: "memory")
 
-static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -38,7 +38,7 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 	int cmparg = (encoded_op << 20) >> 20;
 	int oldval = 0, ret, tem;
 
-	if (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(int))))
+	if (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))))
 		return -EFAULT;
 	if (unlikely((((unsigned long) uaddr) & 0x3UL)))
 		return -EINVAL;
@@ -85,8 +85,8 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
-			      int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
 	int ret = 0;
 
diff --git a/arch/tile/include/asm/futex.h b/arch/tile/include/asm/futex.h
index 664b20a..d03ec12 100644
--- a/arch/tile/include/asm/futex.h
+++ b/arch/tile/include/asm/futex.h
@@ -29,16 +29,16 @@
 #include <linux/uaccess.h>
 #include <linux/errno.h>
 
-extern struct __get_user futex_set(int __user *v, int i);
-extern struct __get_user futex_add(int __user *v, int n);
-extern struct __get_user futex_or(int __user *v, int n);
-extern struct __get_user futex_andn(int __user *v, int n);
-extern struct __get_user futex_cmpxchg(int __user *v, int o, int n);
+extern struct __get_user futex_set(u32 __user *v, int i);
+extern struct __get_user futex_add(u32 __user *v, int n);
+extern struct __get_user futex_or(u32 __user *v, int n);
+extern struct __get_user futex_andn(u32 __user *v, int n);
+extern struct __get_user futex_cmpxchg(u32 __user *v, int o, int n);
 
 #ifndef __tilegx__
-extern struct __get_user futex_xor(int __user *v, int n);
+extern struct __get_user futex_xor(u32 __user *v, int n);
 #else
-static inline struct __get_user futex_xor(int __user *uaddr, int n)
+static inline struct __get_user futex_xor(u32 __user *uaddr, int n)
 {
 	struct __get_user asm_ret = __get_user_4(uaddr);
 	if (!asm_ret.err) {
@@ -53,7 +53,7 @@ static inline struct __get_user futex_xor(int __user *uaddr, int n)
 }
 #endif
 
-static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -65,7 +65,7 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -119,12 +119,12 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 	return ret;
 }
 
-static inline int futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
-						int oldval, int newval)
+static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+						u32 oldval, u32 newval)
 {
 	struct __get_user asm_ret;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	asm_ret = futex_cmpxchg(uaddr, oldval, newval);
diff --git a/arch/x86/include/asm/futex.h b/arch/x86/include/asm/futex.h
index 884c0b5..d09bb03 100644
--- a/arch/x86/include/asm/futex.h
+++ b/arch/x86/include/asm/futex.h
@@ -37,7 +37,7 @@
 		       "+m" (*uaddr), "=&r" (tem)		\
 		     : "r" (oparg), "i" (-EFAULT), "1" (0))
 
-static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -48,7 +48,7 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 #if defined(CONFIG_X86_32) && !defined(CONFIG_X86_BSWAP)
@@ -109,8 +109,8 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 	return ret;
 }
 
-static inline int futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
-						int oldval, int newval)
+static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+						u32 oldval, u32 newval)
 {
 	int ret = 0;
 
@@ -120,7 +120,7 @@ static inline int futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
 		return -ENOSYS;
 #endif
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	asm volatile("1:\t" LOCK_PREFIX "cmpxchgl %4, %2\n"
diff --git a/include/asm-generic/futex.h b/include/asm-generic/futex.h
index 132bf52..01f227e 100644
--- a/include/asm-generic/futex.h
+++ b/include/asm-generic/futex.h
@@ -6,7 +6,7 @@
 #include <asm/errno.h>
 
 static inline int
-futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -16,7 +16,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -48,8 +48,8 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
-			      int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
 	return -ENOSYS;
 }
-- 
Michel "Walken" Lespinasse
A program is never fully debugged until the last user dies.

^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [tip:core/futexes] futex: Remove redundant pagefault_disable in futex_atomic_cmpxchg_inatomic()
  2011-03-11  2:47         ` [PATCH 1/3] futex: do not pagefault_disable in futex_atomic_cmpxchg_inatomic() Michel Lespinasse
@ 2011-03-11 11:31           ` tip-bot for Michel Lespinasse
  2011-03-13 22:49           ` [PATCH 1/3] futex: do not " Linus Torvalds
  1 sibling, 0 replies; 42+ messages in thread
From: tip-bot for Michel Lespinasse @ 2011-03-11 11:31 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: mingo, torvalds, schwidefsky, peterz, cmetcalf, tony.luck, ralf,
	monstr, linux, tglx, linux-kernel, hpa, darren, lethal, davem,
	dhowells, benh, mattst88, jejb, walken

Commit-ID:  522d7decc0370070448a8c28982c8dfd8970489e
Gitweb:     http://git.kernel.org/tip/522d7decc0370070448a8c28982c8dfd8970489e
Author:     Michel Lespinasse <walken@google.com>
AuthorDate: Thu, 10 Mar 2011 18:47:31 -0800
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Fri, 11 Mar 2011 12:23:08 +0100

futex: Remove redundant pagefault_disable in futex_atomic_cmpxchg_inatomic()

kernel/futex.c disables page faults before calling
futex_atomic_cmpxchg_inatomic(), so there is no need to do it again
within that function.
    
Signed-off-by: Michel Lespinasse <walken@google.com>
Cc: Darren Hart <darren@dvhart.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Matt Turner <mattst88@gmail.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: David Howells <dhowells@redhat.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Michal Simek <monstr@monstr.eu>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: "James E.J. Bottomley" <jejb@parisc-linux.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Paul Mundt <lethal@linux-sh.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Chris Metcalf <cmetcalf@tilera.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
LKML-Reference: <20110311024731.GB26122@google.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

---
 arch/arm/include/asm/futex.h |    5 ++---
 1 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/arch/arm/include/asm/futex.h b/arch/arm/include/asm/futex.h
index b33fe70..7133a86 100644
--- a/arch/arm/include/asm/futex.h
+++ b/arch/arm/include/asm/futex.h
@@ -95,7 +95,8 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
 	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
 		return -EFAULT;
 
-	pagefault_disable();	/* implies preempt_disable() */
+	/* Note that preemption is disabled by futex_atomic_cmpxchg_inatomic
+	 * call sites. */
 
 	__asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n"
 	"1:	" T(ldr) "	%0, [%3]\n"
@@ -115,8 +116,6 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
 	: "r" (oldval), "r" (newval), "r" (uaddr), "Ir" (-EFAULT)
 	: "cc", "memory");
 
-	pagefault_enable();	/* subsumes preempt_enable() */
-
 	return val;
 }
 

^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [tip:core/futexes] futex: Sanitize cmpxchg_futex_value_locked API
  2011-03-11  2:48         ` [PATCH 2/3] futex: cmpxchg_futex_value_locked API change Michel Lespinasse
@ 2011-03-11 11:31           ` tip-bot for Michel Lespinasse
  2012-03-05  0:01             ` Jonathan Nieder
  1 sibling, 0 replies; 42+ messages in thread
From: tip-bot for Michel Lespinasse @ 2011-03-11 11:31 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: mingo, torvalds, schwidefsky, peterz, linux, ralf, tglx, hpa,
	linux-kernel, darren, lethal, davem, benh, mattst88, jejb,
	walken

Commit-ID:  37a9d912b24f96a0591773e6e6c3642991ae5a70
Gitweb:     http://git.kernel.org/tip/37a9d912b24f96a0591773e6e6c3642991ae5a70
Author:     Michel Lespinasse <walken@google.com>
AuthorDate: Thu, 10 Mar 2011 18:48:51 -0800
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Fri, 11 Mar 2011 12:23:08 +0100

futex: Sanitize cmpxchg_futex_value_locked API

The cmpxchg_futex_value_locked API was funny in that it returned either
the original, user-exposed futex value OR an error code such as -EFAULT.
This was confusing at best, and could be a source of livelocks in places
that retry the cmpxchg_futex_value_locked after trying to fix the issue
by running fault_in_user_writeable().
    
This change makes the cmpxchg_futex_value_locked API more similar to the
get_futex_value_locked one, returning an error code and updating the
original value through a reference argument.
    
Signed-off-by: Michel Lespinasse <walken@google.com>
Acked-by: Chris Metcalf <cmetcalf@tilera.com>  [tile]
Acked-by: Tony Luck <tony.luck@intel.com>  [ia64]
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Michal Simek <monstr@monstr.eu>  [microblaze]
Acked-by: David Howells <dhowells@redhat.com> [frv]
Cc: Darren Hart <darren@dvhart.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Matt Turner <mattst88@gmail.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: "James E.J. Bottomley" <jejb@parisc-linux.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Paul Mundt <lethal@linux-sh.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
LKML-Reference: <20110311024851.GC26122@google.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

---
 arch/alpha/include/asm/futex.h      |   22 +++++++++-------
 arch/arm/include/asm/futex.h        |   18 +++++++------
 arch/frv/include/asm/futex.h        |    3 +-
 arch/ia64/include/asm/futex.h       |    9 ++++--
 arch/microblaze/include/asm/futex.h |   24 ++++++++++--------
 arch/mips/include/asm/futex.h       |   32 +++++++++++++-----------
 arch/parisc/include/asm/futex.h     |   18 +++++++-------
 arch/powerpc/include/asm/futex.h    |   20 ++++++++-------
 arch/s390/include/asm/futex.h       |    4 +-
 arch/s390/include/asm/uaccess.h     |    2 +-
 arch/s390/lib/uaccess.h             |    4 +-
 arch/s390/lib/uaccess_pt.c          |   13 ++++++----
 arch/s390/lib/uaccess_std.c         |    6 +++-
 arch/sh/include/asm/futex-irq.h     |    9 +++----
 arch/sh/include/asm/futex.h         |    5 ++-
 arch/sparc/include/asm/futex_64.h   |   16 +++++++----
 arch/tile/include/asm/futex.h       |    7 +++--
 arch/x86/include/asm/futex.h        |   16 +++++++-----
 include/asm-generic/futex.h         |    3 +-
 kernel/futex.c                      |   45 +++++++++++-----------------------
 20 files changed, 144 insertions(+), 132 deletions(-)

diff --git a/arch/alpha/include/asm/futex.h b/arch/alpha/include/asm/futex.h
index 945de22..c4e5c28 100644
--- a/arch/alpha/include/asm/futex.h
+++ b/arch/alpha/include/asm/futex.h
@@ -81,21 +81,22 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
+			      int oldval, int newval)
 {
-	int prev, cmp;
+	int ret = 0, prev, cmp;
 
 	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
 		return -EFAULT;
 
 	__asm__ __volatile__ (
 		__ASM_SMP_MB
-	"1:	ldl_l	%0,0(%2)\n"
-	"	cmpeq	%0,%3,%1\n"
-	"	beq	%1,3f\n"
-	"	mov	%4,%1\n"
-	"2:	stl_c	%1,0(%2)\n"
-	"	beq	%1,4f\n"
+	"1:	ldl_l	%1,0(%3)\n"
+	"	cmpeq	%1,%4,%2\n"
+	"	beq	%2,3f\n"
+	"	mov	%5,%2\n"
+	"2:	stl_c	%2,0(%3)\n"
+	"	beq	%2,4f\n"
 	"3:	.subsection 2\n"
 	"4:	br	1b\n"
 	"	.previous\n"
@@ -105,11 +106,12 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
 	"	.long	2b-.\n"
 	"	lda	$31,3b-2b(%0)\n"
 	"	.previous\n"
-	:	"=&r"(prev), "=&r"(cmp)
+	:	"+r"(ret), "=&r"(prev), "=&r"(cmp)
 	:	"r"(uaddr), "r"((long)oldval), "r"(newval)
 	:	"memory");
 
-	return prev;
+	*uval = prev;
+	return ret;
 }
 
 #endif /* __KERNEL__ */
diff --git a/arch/arm/include/asm/futex.h b/arch/arm/include/asm/futex.h
index 7133a86..d20b78f 100644
--- a/arch/arm/include/asm/futex.h
+++ b/arch/arm/include/asm/futex.h
@@ -88,9 +88,10 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
+			      int oldval, int newval)
 {
-	int val;
+	int ret = 0, val;
 
 	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
 		return -EFAULT;
@@ -99,24 +100,25 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
 	 * call sites. */
 
 	__asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n"
-	"1:	" T(ldr) "	%0, [%3]\n"
-	"	teq	%0, %1\n"
+	"1:	" T(ldr) "	%1, [%4]\n"
+	"	teq	%1, %2\n"
 	"	it	eq	@ explicit IT needed for the 2b label\n"
-	"2:	" T(streq) "	%2, [%3]\n"
+	"2:	" T(streq) "	%3, [%4]\n"
 	"3:\n"
 	"	.pushsection __ex_table,\"a\"\n"
 	"	.align	3\n"
 	"	.long	1b, 4f, 2b, 4f\n"
 	"	.popsection\n"
 	"	.pushsection .fixup,\"ax\"\n"
-	"4:	mov	%0, %4\n"
+	"4:	mov	%0, %5\n"
 	"	b	3b\n"
 	"	.popsection"
-	: "=&r" (val)
+	: "+r" (ret), "=&r" (val)
 	: "r" (oldval), "r" (newval), "r" (uaddr), "Ir" (-EFAULT)
 	: "cc", "memory");
 
-	return val;
+	*uval = val;
+	return ret;
 }
 
 #endif /* !SMP */
diff --git a/arch/frv/include/asm/futex.h b/arch/frv/include/asm/futex.h
index 08b3d1d..0548f8e 100644
--- a/arch/frv/include/asm/futex.h
+++ b/arch/frv/include/asm/futex.h
@@ -10,7 +10,8 @@
 extern int futex_atomic_op_inuser(int encoded_op, int __user *uaddr);
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
+			      int oldval, int newval)
 {
 	return -ENOSYS;
 }
diff --git a/arch/ia64/include/asm/futex.h b/arch/ia64/include/asm/futex.h
index c7f0f06..b072840 100644
--- a/arch/ia64/include/asm/futex.h
+++ b/arch/ia64/include/asm/futex.h
@@ -100,23 +100,26 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
+			      int oldval, int newval)
 {
 	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
 		return -EFAULT;
 
 	{
-		register unsigned long r8 __asm ("r8");
+		register unsigned long r8 __asm ("r8") = 0;
+		unsigned long prev;
 		__asm__ __volatile__(
 			"	mf;;					\n"
 			"	mov ar.ccv=%3;;				\n"
 			"[1:]	cmpxchg4.acq %0=[%1],%2,ar.ccv		\n"
 			"	.xdata4 \"__ex_table\", 1b-., 2f-.	\n"
 			"[2:]"
-			: "=r" (r8)
+			: "=r" (prev)
 			: "r" (uaddr), "r" (newval),
 			  "rO" ((long) (unsigned) oldval)
 			: "memory");
+		*uval = prev;
 		return r8;
 	}
 }
diff --git a/arch/microblaze/include/asm/futex.h b/arch/microblaze/include/asm/futex.h
index ad3fd61..fa019ed 100644
--- a/arch/microblaze/include/asm/futex.h
+++ b/arch/microblaze/include/asm/futex.h
@@ -94,31 +94,33 @@ futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
+			      int oldval, int newval)
 {
-	int prev, cmp;
+	int ret = 0, prev, cmp;
 
 	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
 		return -EFAULT;
 
-	__asm__ __volatile__ ("1:	lwx	%0, %2, r0;		\
-					cmp	%1, %0, %3;		\
-					beqi	%1, 3f;			\
-				2:	swx	%4, %2, r0;		\
-					addic	%1, r0, 0;		\
-					bnei	%1, 1b;			\
+	__asm__ __volatile__ ("1:	lwx	%1, %3, r0;		\
+					cmp	%2, %1, %4;		\
+					beqi	%2, 3f;			\
+				2:	swx	%5, %3, r0;		\
+					addic	%2, r0, 0;		\
+					bnei	%2, 1b;			\
 				3:					\
 				.section .fixup,\"ax\";			\
 				4:	brid	3b;			\
-					addik	%0, r0, %5;		\
+					addik	%0, r0, %6;		\
 				.previous;				\
 				.section __ex_table,\"a\";		\
 				.word	1b,4b,2b,4b;			\
 				.previous;"				\
-		: "=&r" (prev), "=&r"(cmp)				\
+		: "+r" (ret), "=&r" (prev), "=&r"(cmp)	\
 		: "r" (uaddr), "r" (oldval), "r" (newval), "i" (-EFAULT));
 
-	return prev;
+	*uval = prev;
+	return ret;
 }
 
 #endif /* __KERNEL__ */
diff --git a/arch/mips/include/asm/futex.h b/arch/mips/include/asm/futex.h
index b9cce90..692a24b 100644
--- a/arch/mips/include/asm/futex.h
+++ b/arch/mips/include/asm/futex.h
@@ -132,9 +132,10 @@ futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
+			      int oldval, int newval)
 {
-	int retval;
+	int ret = 0, val;
 
 	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
 		return -EFAULT;
@@ -145,25 +146,25 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
 		"	.set	push					\n"
 		"	.set	noat					\n"
 		"	.set	mips3					\n"
-		"1:	ll	%0, %2					\n"
-		"	bne	%0, %z3, 3f				\n"
+		"1:	ll	%1, %3					\n"
+		"	bne	%1, %z4, 3f				\n"
 		"	.set	mips0					\n"
-		"	move	$1, %z4					\n"
+		"	move	$1, %z5					\n"
 		"	.set	mips3					\n"
-		"2:	sc	$1, %1					\n"
+		"2:	sc	$1, %2					\n"
 		"	beqzl	$1, 1b					\n"
 		__WEAK_LLSC_MB
 		"3:							\n"
 		"	.set	pop					\n"
 		"	.section .fixup,\"ax\"				\n"
-		"4:	li	%0, %5					\n"
+		"4:	li	%0, %6					\n"
 		"	j	3b					\n"
 		"	.previous					\n"
 		"	.section __ex_table,\"a\"			\n"
 		"	"__UA_ADDR "\t1b, 4b				\n"
 		"	"__UA_ADDR "\t2b, 4b				\n"
 		"	.previous					\n"
-		: "=&r" (retval), "=R" (*uaddr)
+		: "+r" (ret), "=&r" (val), "=R" (*uaddr)
 		: "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT)
 		: "memory");
 	} else if (cpu_has_llsc) {
@@ -172,31 +173,32 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
 		"	.set	push					\n"
 		"	.set	noat					\n"
 		"	.set	mips3					\n"
-		"1:	ll	%0, %2					\n"
-		"	bne	%0, %z3, 3f				\n"
+		"1:	ll	%1, %3					\n"
+		"	bne	%1, %z4, 3f				\n"
 		"	.set	mips0					\n"
-		"	move	$1, %z4					\n"
+		"	move	$1, %z5					\n"
 		"	.set	mips3					\n"
-		"2:	sc	$1, %1					\n"
+		"2:	sc	$1, %2					\n"
 		"	beqz	$1, 1b					\n"
 		__WEAK_LLSC_MB
 		"3:							\n"
 		"	.set	pop					\n"
 		"	.section .fixup,\"ax\"				\n"
-		"4:	li	%0, %5					\n"
+		"4:	li	%0, %6					\n"
 		"	j	3b					\n"
 		"	.previous					\n"
 		"	.section __ex_table,\"a\"			\n"
 		"	"__UA_ADDR "\t1b, 4b				\n"
 		"	"__UA_ADDR "\t2b, 4b				\n"
 		"	.previous					\n"
-		: "=&r" (retval), "=R" (*uaddr)
+		: "+r" (ret), "=&r" (val), "=R" (*uaddr)
 		: "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT)
 		: "memory");
 	} else
 		return -ENOSYS;
 
-	return retval;
+	*uval = val;
+	return ret;
 }
 
 #endif
diff --git a/arch/parisc/include/asm/futex.h b/arch/parisc/include/asm/futex.h
index 0c705c3..4c6d867 100644
--- a/arch/parisc/include/asm/futex.h
+++ b/arch/parisc/include/asm/futex.h
@@ -51,10 +51,10 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 
 /* Non-atomic version */
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
+			      int oldval, int newval)
 {
-	int err = 0;
-	int uval;
+	int val;
 
 	/* futex.c wants to do a cmpxchg_inatomic on kernel NULL, which is
 	 * our gateway page, and causes no end of trouble...
@@ -65,12 +65,12 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
 	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
 		return -EFAULT;
 
-	err = get_user(uval, uaddr);
-	if (err) return -EFAULT;
-	if (uval == oldval)
-		err = put_user(newval, uaddr);
-	if (err) return -EFAULT;
-	return uval;
+	if (get_user(val, uaddr))
+		return -EFAULT;
+	if (val == oldval && put_user(newval, uaddr))
+		return -EFAULT;
+	*uval = val;
+	return 0;
 }
 
 #endif /*__KERNEL__*/
diff --git a/arch/powerpc/include/asm/futex.h b/arch/powerpc/include/asm/futex.h
index 7c589ef..631e8da 100644
--- a/arch/powerpc/include/asm/futex.h
+++ b/arch/powerpc/include/asm/futex.h
@@ -82,35 +82,37 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
+			      int oldval, int newval)
 {
-	int prev;
+	int ret = 0, prev;
 
 	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
 		return -EFAULT;
 
         __asm__ __volatile__ (
         PPC_RELEASE_BARRIER
-"1:     lwarx   %0,0,%2         # futex_atomic_cmpxchg_inatomic\n\
-        cmpw    0,%0,%3\n\
+"1:     lwarx   %1,0,%3         # futex_atomic_cmpxchg_inatomic\n\
+        cmpw    0,%1,%4\n\
         bne-    3f\n"
-        PPC405_ERR77(0,%2)
-"2:     stwcx.  %4,0,%2\n\
+        PPC405_ERR77(0,%3)
+"2:     stwcx.  %5,0,%3\n\
         bne-    1b\n"
         PPC_ACQUIRE_BARRIER
 "3:	.section .fixup,\"ax\"\n\
-4:	li	%0,%5\n\
+4:	li	%0,%6\n\
 	b	3b\n\
 	.previous\n\
 	.section __ex_table,\"a\"\n\
 	.align 3\n\
 	" PPC_LONG "1b,4b,2b,4b\n\
 	.previous" \
-        : "=&r" (prev), "+m" (*uaddr)
+        : "+r" (ret), "=&r" (prev), "+m" (*uaddr)
         : "r" (uaddr), "r" (oldval), "r" (newval), "i" (-EFAULT)
         : "cc", "memory");
 
-        return prev;
+	*uval = prev;
+        return ret;
 }
 
 #endif /* __KERNEL__ */
diff --git a/arch/s390/include/asm/futex.h b/arch/s390/include/asm/futex.h
index 5c5d02d..27ac515 100644
--- a/arch/s390/include/asm/futex.h
+++ b/arch/s390/include/asm/futex.h
@@ -39,13 +39,13 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 	return ret;
 }
 
-static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr,
+static inline int futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
 						int oldval, int newval)
 {
 	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
 		return -EFAULT;
 
-	return uaccess.futex_atomic_cmpxchg(uaddr, oldval, newval);
+	return uaccess.futex_atomic_cmpxchg(uval, uaddr, oldval, newval);
 }
 
 #endif /* __KERNEL__ */
diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h
index d6b1ed0..549adf6 100644
--- a/arch/s390/include/asm/uaccess.h
+++ b/arch/s390/include/asm/uaccess.h
@@ -84,7 +84,7 @@ struct uaccess_ops {
 	size_t (*strnlen_user)(size_t, const char __user *);
 	size_t (*strncpy_from_user)(size_t, const char __user *, char *);
 	int (*futex_atomic_op)(int op, int __user *, int oparg, int *old);
-	int (*futex_atomic_cmpxchg)(int __user *, int old, int new);
+	int (*futex_atomic_cmpxchg)(int *, int __user *, int old, int new);
 };
 
 extern struct uaccess_ops uaccess;
diff --git a/arch/s390/lib/uaccess.h b/arch/s390/lib/uaccess.h
index 126011d..89a8067 100644
--- a/arch/s390/lib/uaccess.h
+++ b/arch/s390/lib/uaccess.h
@@ -12,12 +12,12 @@ extern size_t copy_from_user_std(size_t, const void __user *, void *);
 extern size_t copy_to_user_std(size_t, void __user *, const void *);
 extern size_t strnlen_user_std(size_t, const char __user *);
 extern size_t strncpy_from_user_std(size_t, const char __user *, char *);
-extern int futex_atomic_cmpxchg_std(int __user *, int, int);
+extern int futex_atomic_cmpxchg_std(int *, int __user *, int, int);
 extern int futex_atomic_op_std(int, int __user *, int, int *);
 
 extern size_t copy_from_user_pt(size_t, const void __user *, void *);
 extern size_t copy_to_user_pt(size_t, void __user *, const void *);
 extern int futex_atomic_op_pt(int, int __user *, int, int *);
-extern int futex_atomic_cmpxchg_pt(int __user *, int, int);
+extern int futex_atomic_cmpxchg_pt(int *, int __user *, int, int);
 
 #endif /* __ARCH_S390_LIB_UACCESS_H */
diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c
index 404f2de..b3cebcd 100644
--- a/arch/s390/lib/uaccess_pt.c
+++ b/arch/s390/lib/uaccess_pt.c
@@ -354,26 +354,29 @@ int futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old)
 	return ret;
 }
 
-static int __futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval)
+static int __futex_atomic_cmpxchg_pt(int *uval, int __user *uaddr,
+				     int oldval, int newval)
 {
 	int ret;
 
 	asm volatile("0: cs   %1,%4,0(%5)\n"
-		     "1: lr   %0,%1\n"
+		     "1: la   %0,0\n"
 		     "2:\n"
 		     EX_TABLE(0b,2b) EX_TABLE(1b,2b)
 		     : "=d" (ret), "+d" (oldval), "=m" (*uaddr)
 		     : "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr)
 		     : "cc", "memory" );
+	*uval = oldval;
 	return ret;
 }
 
-int futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval)
+int futex_atomic_cmpxchg_pt(int *uval, int __user *uaddr,
+			    int oldval, int newval)
 {
 	int ret;
 
 	if (segment_eq(get_fs(), KERNEL_DS))
-		return __futex_atomic_cmpxchg_pt(uaddr, oldval, newval);
+		return __futex_atomic_cmpxchg_pt(uval, uaddr, oldval, newval);
 	spin_lock(&current->mm->page_table_lock);
 	uaddr = (int __user *) __dat_user_addr((unsigned long) uaddr);
 	if (!uaddr) {
@@ -382,7 +385,7 @@ int futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval)
 	}
 	get_page(virt_to_page(uaddr));
 	spin_unlock(&current->mm->page_table_lock);
-	ret = __futex_atomic_cmpxchg_pt(uaddr, oldval, newval);
+	ret = __futex_atomic_cmpxchg_pt(uval, uaddr, oldval, newval);
 	put_page(virt_to_page(uaddr));
 	return ret;
 }
diff --git a/arch/s390/lib/uaccess_std.c b/arch/s390/lib/uaccess_std.c
index a6c4f7e..1d6643c 100644
--- a/arch/s390/lib/uaccess_std.c
+++ b/arch/s390/lib/uaccess_std.c
@@ -287,19 +287,21 @@ int futex_atomic_op_std(int op, int __user *uaddr, int oparg, int *old)
 	return ret;
 }
 
-int futex_atomic_cmpxchg_std(int __user *uaddr, int oldval, int newval)
+int futex_atomic_cmpxchg_std(int *uval, int __user *uaddr,
+			     int oldval, int newval)
 {
 	int ret;
 
 	asm volatile(
 		"   sacf 256\n"
 		"0: cs   %1,%4,0(%5)\n"
-		"1: lr   %0,%1\n"
+		"1: la   %0,0\n"
 		"2: sacf 0\n"
 		EX_TABLE(0b,2b) EX_TABLE(1b,2b)
 		: "=d" (ret), "+d" (oldval), "=m" (*uaddr)
 		: "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr)
 		: "cc", "memory" );
+	*uval = oldval;
 	return ret;
 }
 
diff --git a/arch/sh/include/asm/futex-irq.h b/arch/sh/include/asm/futex-irq.h
index a9f16a7..7b701cb 100644
--- a/arch/sh/include/asm/futex-irq.h
+++ b/arch/sh/include/asm/futex-irq.h
@@ -88,7 +88,8 @@ static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr,
 	return ret;
 }
 
-static inline int atomic_futex_op_cmpxchg_inatomic(int __user *uaddr,
+static inline int atomic_futex_op_cmpxchg_inatomic(int *uval,
+						   int __user *uaddr,
 						   int oldval, int newval)
 {
 	unsigned long flags;
@@ -102,10 +103,8 @@ static inline int atomic_futex_op_cmpxchg_inatomic(int __user *uaddr,
 
 	local_irq_restore(flags);
 
-	if (ret)
-		return ret;
-
-	return prev;
+	*uval = prev;
+	return ret;
 }
 
 #endif /* __ASM_SH_FUTEX_IRQ_H */
diff --git a/arch/sh/include/asm/futex.h b/arch/sh/include/asm/futex.h
index 68256ec..a8a5125 100644
--- a/arch/sh/include/asm/futex.h
+++ b/arch/sh/include/asm/futex.h
@@ -65,12 +65,13 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
+			      int oldval, int newval)
 {
 	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
 		return -EFAULT;
 
-	return atomic_futex_op_cmpxchg_inatomic(uaddr, oldval, newval);
+	return atomic_futex_op_cmpxchg_inatomic(uval, uaddr, oldval, newval);
 }
 
 #endif /* __KERNEL__ */
diff --git a/arch/sparc/include/asm/futex_64.h b/arch/sparc/include/asm/futex_64.h
index 47f9583..e086220 100644
--- a/arch/sparc/include/asm/futex_64.h
+++ b/arch/sparc/include/asm/futex_64.h
@@ -85,26 +85,30 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
+			      int oldval, int newval)
 {
+	int ret = 0;
+
 	__asm__ __volatile__(
-	"\n1:	casa	[%3] %%asi, %2, %0\n"
+	"\n1:	casa	[%4] %%asi, %3, %1\n"
 	"2:\n"
 	"	.section .fixup,#alloc,#execinstr\n"
 	"	.align	4\n"
 	"3:	sethi	%%hi(2b), %0\n"
 	"	jmpl	%0 + %%lo(2b), %%g0\n"
-	"	 mov	%4, %0\n"
+	"	mov	%5, %0\n"
 	"	.previous\n"
 	"	.section __ex_table,\"a\"\n"
 	"	.align	4\n"
 	"	.word	1b, 3b\n"
 	"	.previous\n"
-	: "=r" (newval)
-	: "0" (newval), "r" (oldval), "r" (uaddr), "i" (-EFAULT)
+	: "+r" (ret), "=r" (newval)
+	: "1" (newval), "r" (oldval), "r" (uaddr), "i" (-EFAULT)
 	: "memory");
 
-	return newval;
+	*uval = newval;
+	return ret;
 }
 
 #endif /* !(_SPARC64_FUTEX_H) */
diff --git a/arch/tile/include/asm/futex.h b/arch/tile/include/asm/futex.h
index fe0d10d..664b20a 100644
--- a/arch/tile/include/asm/futex.h
+++ b/arch/tile/include/asm/futex.h
@@ -119,8 +119,8 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 	return ret;
 }
 
-static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval,
-						int newval)
+static inline int futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
+						int oldval, int newval)
 {
 	struct __get_user asm_ret;
 
@@ -128,7 +128,8 @@ static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval,
 		return -EFAULT;
 
 	asm_ret = futex_cmpxchg(uaddr, oldval, newval);
-	return asm_ret.err ? asm_ret.err : asm_ret.val;
+	*uval = asm_ret.val;
+	return asm_ret.err;
 }
 
 #ifndef __tilegx__
diff --git a/arch/x86/include/asm/futex.h b/arch/x86/include/asm/futex.h
index 1f11ce4..884c0b5 100644
--- a/arch/x86/include/asm/futex.h
+++ b/arch/x86/include/asm/futex.h
@@ -109,9 +109,10 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 	return ret;
 }
 
-static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval,
-						int newval)
+static inline int futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
+						int oldval, int newval)
 {
+	int ret = 0;
 
 #if defined(CONFIG_X86_32) && !defined(CONFIG_X86_BSWAP)
 	/* Real i386 machines have no cmpxchg instruction */
@@ -122,18 +123,19 @@ static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval,
 	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
 		return -EFAULT;
 
-	asm volatile("1:\t" LOCK_PREFIX "cmpxchgl %3, %1\n"
+	asm volatile("1:\t" LOCK_PREFIX "cmpxchgl %4, %2\n"
 		     "2:\t.section .fixup, \"ax\"\n"
-		     "3:\tmov     %2, %0\n"
+		     "3:\tmov     %3, %0\n"
 		     "\tjmp     2b\n"
 		     "\t.previous\n"
 		     _ASM_EXTABLE(1b, 3b)
-		     : "=a" (oldval), "+m" (*uaddr)
-		     : "i" (-EFAULT), "r" (newval), "0" (oldval)
+		     : "+r" (ret), "=a" (oldval), "+m" (*uaddr)
+		     : "i" (-EFAULT), "r" (newval), "1" (oldval)
 		     : "memory"
 	);
 
-	return oldval;
+	*uval = oldval;
+	return ret;
 }
 
 #endif
diff --git a/include/asm-generic/futex.h b/include/asm-generic/futex.h
index 3c2344f..132bf52 100644
--- a/include/asm-generic/futex.h
+++ b/include/asm-generic/futex.h
@@ -48,7 +48,8 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
+			      int oldval, int newval)
 {
 	return -ENOSYS;
 }
diff --git a/kernel/futex.c b/kernel/futex.c
index 7738154..237f14b 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -381,15 +381,16 @@ static struct futex_q *futex_top_waiter(struct futex_hash_bucket *hb,
 	return NULL;
 }
 
-static u32 cmpxchg_futex_value_locked(u32 __user *uaddr, u32 uval, u32 newval)
+static int cmpxchg_futex_value_locked(u32 *curval, u32 __user *uaddr,
+				      u32 uval, u32 newval)
 {
-	u32 curval;
+	int ret;
 
 	pagefault_disable();
-	curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval);
+	ret = futex_atomic_cmpxchg_inatomic(curval, uaddr, uval, newval);
 	pagefault_enable();
 
-	return curval;
+	return ret;
 }
 
 static int get_futex_value_locked(u32 *dest, u32 __user *from)
@@ -688,9 +689,7 @@ retry:
 	if (set_waiters)
 		newval |= FUTEX_WAITERS;
 
-	curval = cmpxchg_futex_value_locked(uaddr, 0, newval);
-
-	if (unlikely(curval == -EFAULT))
+	if (unlikely(cmpxchg_futex_value_locked(&curval, uaddr, 0, newval)))
 		return -EFAULT;
 
 	/*
@@ -728,9 +727,7 @@ retry:
 		lock_taken = 1;
 	}
 
-	curval = cmpxchg_futex_value_locked(uaddr, uval, newval);
-
-	if (unlikely(curval == -EFAULT))
+	if (unlikely(cmpxchg_futex_value_locked(&curval, uaddr, uval, newval)))
 		return -EFAULT;
 	if (unlikely(curval != uval))
 		goto retry;
@@ -843,9 +840,7 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this)
 
 		newval = FUTEX_WAITERS | task_pid_vnr(new_owner);
 
-		curval = cmpxchg_futex_value_locked(uaddr, uval, newval);
-
-		if (curval == -EFAULT)
+		if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval))
 			ret = -EFAULT;
 		else if (curval != uval)
 			ret = -EINVAL;
@@ -880,10 +875,8 @@ static int unlock_futex_pi(u32 __user *uaddr, u32 uval)
 	 * There is no waiter, so we unlock the futex. The owner died
 	 * bit has not to be preserved here. We are the owner:
 	 */
-	oldval = cmpxchg_futex_value_locked(uaddr, uval, 0);
-
-	if (oldval == -EFAULT)
-		return oldval;
+	if (cmpxchg_futex_value_locked(&oldval, uaddr, uval, 0))
+		return -EFAULT;
 	if (oldval != uval)
 		return -EAGAIN;
 
@@ -1578,9 +1571,7 @@ retry:
 	while (1) {
 		newval = (uval & FUTEX_OWNER_DIED) | newtid;
 
-		curval = cmpxchg_futex_value_locked(uaddr, uval, newval);
-
-		if (curval == -EFAULT)
+		if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval))
 			goto handle_fault;
 		if (curval == uval)
 			break;
@@ -2073,11 +2064,8 @@ retry:
 	 * again. If it succeeds then we can return without waking
 	 * anyone else up:
 	 */
-	if (!(uval & FUTEX_OWNER_DIED))
-		uval = cmpxchg_futex_value_locked(uaddr, vpid, 0);
-
-
-	if (unlikely(uval == -EFAULT))
+	if (!(uval & FUTEX_OWNER_DIED) &&
+	    cmpxchg_futex_value_locked(&uval, uaddr, vpid, 0))
 		goto pi_faulted;
 	/*
 	 * Rare case: we managed to release the lock atomically,
@@ -2464,9 +2452,7 @@ retry:
 		 * userspace.
 		 */
 		mval = (uval & FUTEX_WAITERS) | FUTEX_OWNER_DIED;
-		nval = futex_atomic_cmpxchg_inatomic(uaddr, uval, mval);
-
-		if (nval == -EFAULT)
+		if (futex_atomic_cmpxchg_inatomic(&nval, uaddr, uval, mval))
 			return -1;
 
 		if (nval != uval)
@@ -2679,8 +2665,7 @@ static int __init futex_init(void)
 	 * implementation, the non-functional ones will return
 	 * -ENOSYS.
 	 */
-	curval = cmpxchg_futex_value_locked(NULL, 0, 0);
-	if (curval == -EFAULT)
+	if (cmpxchg_futex_value_locked(&curval, NULL, 0, 0) == -EFAULT)
 		futex_cmpxchg_enabled = 1;
 
 	for (i = 0; i < ARRAY_SIZE(futex_queues); i++) {

^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [tip:core/futexes] futex: Sanitize futex ops argument types
  2011-03-11  2:50         ` [PATCH 3/3] futex: fix futex operation types Michel Lespinasse
@ 2011-03-11 11:32           ` tip-bot for Michel Lespinasse
  0 siblings, 0 replies; 42+ messages in thread
From: tip-bot for Michel Lespinasse @ 2011-03-11 11:32 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: mingo, torvalds, schwidefsky, peterz, cmetcalf, tony.luck, ralf,
	monstr, linux, tglx, linux-kernel, hpa, darren, lethal, davem,
	dhowells, benh, mattst88, jejb, walken

Commit-ID:  8d7718aa082aaf30a0b4989e1f04858952f941bc
Gitweb:     http://git.kernel.org/tip/8d7718aa082aaf30a0b4989e1f04858952f941bc
Author:     Michel Lespinasse <walken@google.com>
AuthorDate: Thu, 10 Mar 2011 18:50:58 -0800
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Fri, 11 Mar 2011 12:23:31 +0100

futex: Sanitize futex ops argument types

Change futex_atomic_op_inuser and futex_atomic_cmpxchg_inatomic
prototypes to use u32 types for the futex as this is the data type the
futex core code uses all over the place.

Signed-off-by: Michel Lespinasse <walken@google.com>
Cc: Darren Hart <darren@dvhart.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Matt Turner <mattst88@gmail.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: David Howells <dhowells@redhat.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Michal Simek <monstr@monstr.eu>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: "James E.J. Bottomley" <jejb@parisc-linux.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Paul Mundt <lethal@linux-sh.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Chris Metcalf <cmetcalf@tilera.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
LKML-Reference: <20110311025058.GD26122@google.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 arch/alpha/include/asm/futex.h      |   13 +++++++------
 arch/arm/include/asm/futex.h        |   13 +++++++------
 arch/frv/include/asm/futex.h        |    6 +++---
 arch/frv/kernel/futex.c             |   14 +++++++-------
 arch/ia64/include/asm/futex.h       |   10 +++++-----
 arch/microblaze/include/asm/futex.h |   13 +++++++------
 arch/mips/include/asm/futex.h       |   13 +++++++------
 arch/parisc/include/asm/futex.h     |   12 ++++++------
 arch/powerpc/include/asm/futex.h    |   13 +++++++------
 arch/s390/include/asm/futex.h       |   10 +++++-----
 arch/s390/include/asm/uaccess.h     |    4 ++--
 arch/s390/lib/uaccess.h             |    8 ++++----
 arch/s390/lib/uaccess_pt.c          |   12 ++++++------
 arch/s390/lib/uaccess_std.c         |    6 +++---
 arch/sh/include/asm/futex-irq.h     |   19 ++++++++++---------
 arch/sh/include/asm/futex.h         |   10 +++++-----
 arch/sparc/include/asm/futex_64.h   |    8 ++++----
 arch/tile/include/asm/futex.h       |   24 ++++++++++++------------
 arch/x86/include/asm/futex.h        |   10 +++++-----
 include/asm-generic/futex.h         |    8 ++++----
 20 files changed, 116 insertions(+), 110 deletions(-)

diff --git a/arch/alpha/include/asm/futex.h b/arch/alpha/include/asm/futex.h
index c4e5c28..e8a761a 100644
--- a/arch/alpha/include/asm/futex.h
+++ b/arch/alpha/include/asm/futex.h
@@ -29,7 +29,7 @@
 	:	"r" (uaddr), "r"(oparg)				\
 	:	"memory")
 
-static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -39,7 +39,7 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -81,12 +81,13 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
-			      int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
-	int ret = 0, prev, cmp;
+	int ret = 0, cmp;
+	u32 prev;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	__asm__ __volatile__ (
diff --git a/arch/arm/include/asm/futex.h b/arch/arm/include/asm/futex.h
index d20b78f..0e29d8e 100644
--- a/arch/arm/include/asm/futex.h
+++ b/arch/arm/include/asm/futex.h
@@ -35,7 +35,7 @@
 	: "cc", "memory")
 
 static inline int
-futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -46,7 +46,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();	/* implies preempt_disable() */
@@ -88,12 +88,13 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
-			      int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
-	int ret = 0, val;
+	int ret = 0;
+	u32 val;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	/* Note that preemption is disabled by futex_atomic_cmpxchg_inatomic
diff --git a/arch/frv/include/asm/futex.h b/arch/frv/include/asm/futex.h
index 0548f8e..4bea27f 100644
--- a/arch/frv/include/asm/futex.h
+++ b/arch/frv/include/asm/futex.h
@@ -7,11 +7,11 @@
 #include <asm/errno.h>
 #include <asm/uaccess.h>
 
-extern int futex_atomic_op_inuser(int encoded_op, int __user *uaddr);
+extern int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr);
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
-			      int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
 	return -ENOSYS;
 }
diff --git a/arch/frv/kernel/futex.c b/arch/frv/kernel/futex.c
index 14f64b0..d155ca9 100644
--- a/arch/frv/kernel/futex.c
+++ b/arch/frv/kernel/futex.c
@@ -18,7 +18,7 @@
  * the various futex operations; MMU fault checking is ignored under no-MMU
  * conditions
  */
-static inline int atomic_futex_op_xchg_set(int oparg, int __user *uaddr, int *_oldval)
+static inline int atomic_futex_op_xchg_set(int oparg, u32 __user *uaddr, int *_oldval)
 {
 	int oldval, ret;
 
@@ -50,7 +50,7 @@ static inline int atomic_futex_op_xchg_set(int oparg, int __user *uaddr, int *_o
 	return ret;
 }
 
-static inline int atomic_futex_op_xchg_add(int oparg, int __user *uaddr, int *_oldval)
+static inline int atomic_futex_op_xchg_add(int oparg, u32 __user *uaddr, int *_oldval)
 {
 	int oldval, ret;
 
@@ -83,7 +83,7 @@ static inline int atomic_futex_op_xchg_add(int oparg, int __user *uaddr, int *_o
 	return ret;
 }
 
-static inline int atomic_futex_op_xchg_or(int oparg, int __user *uaddr, int *_oldval)
+static inline int atomic_futex_op_xchg_or(int oparg, u32 __user *uaddr, int *_oldval)
 {
 	int oldval, ret;
 
@@ -116,7 +116,7 @@ static inline int atomic_futex_op_xchg_or(int oparg, int __user *uaddr, int *_ol
 	return ret;
 }
 
-static inline int atomic_futex_op_xchg_and(int oparg, int __user *uaddr, int *_oldval)
+static inline int atomic_futex_op_xchg_and(int oparg, u32 __user *uaddr, int *_oldval)
 {
 	int oldval, ret;
 
@@ -149,7 +149,7 @@ static inline int atomic_futex_op_xchg_and(int oparg, int __user *uaddr, int *_o
 	return ret;
 }
 
-static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr, int *_oldval)
+static inline int atomic_futex_op_xchg_xor(int oparg, u32 __user *uaddr, int *_oldval)
 {
 	int oldval, ret;
 
@@ -186,7 +186,7 @@ static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr, int *_o
 /*
  * do the futex operations
  */
-int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -197,7 +197,7 @@ int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
diff --git a/arch/ia64/include/asm/futex.h b/arch/ia64/include/asm/futex.h
index b072840..8428525 100644
--- a/arch/ia64/include/asm/futex.h
+++ b/arch/ia64/include/asm/futex.h
@@ -46,7 +46,7 @@ do {									\
 } while (0)
 
 static inline int
-futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -56,7 +56,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -100,10 +100,10 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
-			      int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	{
diff --git a/arch/microblaze/include/asm/futex.h b/arch/microblaze/include/asm/futex.h
index fa019ed..b0526d2 100644
--- a/arch/microblaze/include/asm/futex.h
+++ b/arch/microblaze/include/asm/futex.h
@@ -29,7 +29,7 @@
 })
 
 static inline int
-futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -39,7 +39,7 @@ futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -94,12 +94,13 @@ futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
-			      int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
-	int ret = 0, prev, cmp;
+	int ret = 0, cmp;
+	u32 prev;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	__asm__ __volatile__ ("1:	lwx	%1, %3, r0;		\
diff --git a/arch/mips/include/asm/futex.h b/arch/mips/include/asm/futex.h
index 692a24b..6ebf173 100644
--- a/arch/mips/include/asm/futex.h
+++ b/arch/mips/include/asm/futex.h
@@ -75,7 +75,7 @@
 }
 
 static inline int
-futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -85,7 +85,7 @@ futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -132,12 +132,13 @@ futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
-			      int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
-	int ret = 0, val;
+	int ret = 0;
+	u32 val;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	if (cpu_has_llsc && R10000_LLSC_WAR) {
diff --git a/arch/parisc/include/asm/futex.h b/arch/parisc/include/asm/futex.h
index 4c6d867..67a33cc 100644
--- a/arch/parisc/include/asm/futex.h
+++ b/arch/parisc/include/asm/futex.h
@@ -8,7 +8,7 @@
 #include <asm/errno.h>
 
 static inline int
-futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -18,7 +18,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -51,10 +51,10 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 
 /* Non-atomic version */
 static inline int
-futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
-			      int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
-	int val;
+	u32 val;
 
 	/* futex.c wants to do a cmpxchg_inatomic on kernel NULL, which is
 	 * our gateway page, and causes no end of trouble...
@@ -62,7 +62,7 @@ futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
 	if (segment_eq(KERNEL_DS, get_fs()) && !uaddr)
 		return -EFAULT;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	if (get_user(val, uaddr))
diff --git a/arch/powerpc/include/asm/futex.h b/arch/powerpc/include/asm/futex.h
index 631e8da..c94e4a3 100644
--- a/arch/powerpc/include/asm/futex.h
+++ b/arch/powerpc/include/asm/futex.h
@@ -30,7 +30,7 @@
 	: "b" (uaddr), "i" (-EFAULT), "r" (oparg) \
 	: "cr0", "memory")
 
-static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -40,7 +40,7 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -82,12 +82,13 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
-			      int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
-	int ret = 0, prev;
+	int ret = 0;
+	u32 prev;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
         __asm__ __volatile__ (
diff --git a/arch/s390/include/asm/futex.h b/arch/s390/include/asm/futex.h
index 27ac515..81cf36b 100644
--- a/arch/s390/include/asm/futex.h
+++ b/arch/s390/include/asm/futex.h
@@ -7,7 +7,7 @@
 #include <linux/uaccess.h>
 #include <asm/errno.h>
 
-static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -18,7 +18,7 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -39,10 +39,10 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 	return ret;
 }
 
-static inline int futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
-						int oldval, int newval)
+static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+						u32 oldval, u32 newval)
 {
-	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	return uaccess.futex_atomic_cmpxchg(uval, uaddr, oldval, newval);
diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h
index 549adf6..2d9ea11f 100644
--- a/arch/s390/include/asm/uaccess.h
+++ b/arch/s390/include/asm/uaccess.h
@@ -83,8 +83,8 @@ struct uaccess_ops {
 	size_t (*clear_user)(size_t, void __user *);
 	size_t (*strnlen_user)(size_t, const char __user *);
 	size_t (*strncpy_from_user)(size_t, const char __user *, char *);
-	int (*futex_atomic_op)(int op, int __user *, int oparg, int *old);
-	int (*futex_atomic_cmpxchg)(int *, int __user *, int old, int new);
+	int (*futex_atomic_op)(int op, u32 __user *, int oparg, int *old);
+	int (*futex_atomic_cmpxchg)(u32 *, u32 __user *, u32 old, u32 new);
 };
 
 extern struct uaccess_ops uaccess;
diff --git a/arch/s390/lib/uaccess.h b/arch/s390/lib/uaccess.h
index 89a8067..1d2536c 100644
--- a/arch/s390/lib/uaccess.h
+++ b/arch/s390/lib/uaccess.h
@@ -12,12 +12,12 @@ extern size_t copy_from_user_std(size_t, const void __user *, void *);
 extern size_t copy_to_user_std(size_t, void __user *, const void *);
 extern size_t strnlen_user_std(size_t, const char __user *);
 extern size_t strncpy_from_user_std(size_t, const char __user *, char *);
-extern int futex_atomic_cmpxchg_std(int *, int __user *, int, int);
-extern int futex_atomic_op_std(int, int __user *, int, int *);
+extern int futex_atomic_cmpxchg_std(u32 *, u32 __user *, u32, u32);
+extern int futex_atomic_op_std(int, u32 __user *, int, int *);
 
 extern size_t copy_from_user_pt(size_t, const void __user *, void *);
 extern size_t copy_to_user_pt(size_t, void __user *, const void *);
-extern int futex_atomic_op_pt(int, int __user *, int, int *);
-extern int futex_atomic_cmpxchg_pt(int *, int __user *, int, int);
+extern int futex_atomic_op_pt(int, u32 __user *, int, int *);
+extern int futex_atomic_cmpxchg_pt(u32 *, u32 __user *, u32, u32);
 
 #endif /* __ARCH_S390_LIB_UACCESS_H */
diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c
index b3cebcd..7483383 100644
--- a/arch/s390/lib/uaccess_pt.c
+++ b/arch/s390/lib/uaccess_pt.c
@@ -302,7 +302,7 @@ fault:
 		     : "0" (-EFAULT), "d" (oparg), "a" (uaddr),		\
 		       "m" (*uaddr) : "cc" );
 
-static int __futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old)
+static int __futex_atomic_op_pt(int op, u32 __user *uaddr, int oparg, int *old)
 {
 	int oldval = 0, newval, ret;
 
@@ -335,7 +335,7 @@ static int __futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old)
 	return ret;
 }
 
-int futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old)
+int futex_atomic_op_pt(int op, u32 __user *uaddr, int oparg, int *old)
 {
 	int ret;
 
@@ -354,8 +354,8 @@ int futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old)
 	return ret;
 }
 
-static int __futex_atomic_cmpxchg_pt(int *uval, int __user *uaddr,
-				     int oldval, int newval)
+static int __futex_atomic_cmpxchg_pt(u32 *uval, u32 __user *uaddr,
+				     u32 oldval, u32 newval)
 {
 	int ret;
 
@@ -370,8 +370,8 @@ static int __futex_atomic_cmpxchg_pt(int *uval, int __user *uaddr,
 	return ret;
 }
 
-int futex_atomic_cmpxchg_pt(int *uval, int __user *uaddr,
-			    int oldval, int newval)
+int futex_atomic_cmpxchg_pt(u32 *uval, u32 __user *uaddr,
+			    u32 oldval, u32 newval)
 {
 	int ret;
 
diff --git a/arch/s390/lib/uaccess_std.c b/arch/s390/lib/uaccess_std.c
index 1d6643c..bb1a7ee 100644
--- a/arch/s390/lib/uaccess_std.c
+++ b/arch/s390/lib/uaccess_std.c
@@ -255,7 +255,7 @@ size_t strncpy_from_user_std(size_t size, const char __user *src, char *dst)
 		: "0" (-EFAULT), "d" (oparg), "a" (uaddr),		\
 		  "m" (*uaddr) : "cc");
 
-int futex_atomic_op_std(int op, int __user *uaddr, int oparg, int *old)
+int futex_atomic_op_std(int op, u32 __user *uaddr, int oparg, int *old)
 {
 	int oldval = 0, newval, ret;
 
@@ -287,8 +287,8 @@ int futex_atomic_op_std(int op, int __user *uaddr, int oparg, int *old)
 	return ret;
 }
 
-int futex_atomic_cmpxchg_std(int *uval, int __user *uaddr,
-			     int oldval, int newval)
+int futex_atomic_cmpxchg_std(u32 *uval, u32 __user *uaddr,
+			     u32 oldval, u32 newval)
 {
 	int ret;
 
diff --git a/arch/sh/include/asm/futex-irq.h b/arch/sh/include/asm/futex-irq.h
index 7b701cb..6cb9f19 100644
--- a/arch/sh/include/asm/futex-irq.h
+++ b/arch/sh/include/asm/futex-irq.h
@@ -3,7 +3,7 @@
 
 #include <asm/system.h>
 
-static inline int atomic_futex_op_xchg_set(int oparg, int __user *uaddr,
+static inline int atomic_futex_op_xchg_set(int oparg, u32 __user *uaddr,
 					   int *oldval)
 {
 	unsigned long flags;
@@ -20,7 +20,7 @@ static inline int atomic_futex_op_xchg_set(int oparg, int __user *uaddr,
 	return ret;
 }
 
-static inline int atomic_futex_op_xchg_add(int oparg, int __user *uaddr,
+static inline int atomic_futex_op_xchg_add(int oparg, u32 __user *uaddr,
 					   int *oldval)
 {
 	unsigned long flags;
@@ -37,7 +37,7 @@ static inline int atomic_futex_op_xchg_add(int oparg, int __user *uaddr,
 	return ret;
 }
 
-static inline int atomic_futex_op_xchg_or(int oparg, int __user *uaddr,
+static inline int atomic_futex_op_xchg_or(int oparg, u32 __user *uaddr,
 					  int *oldval)
 {
 	unsigned long flags;
@@ -54,7 +54,7 @@ static inline int atomic_futex_op_xchg_or(int oparg, int __user *uaddr,
 	return ret;
 }
 
-static inline int atomic_futex_op_xchg_and(int oparg, int __user *uaddr,
+static inline int atomic_futex_op_xchg_and(int oparg, u32 __user *uaddr,
 					   int *oldval)
 {
 	unsigned long flags;
@@ -71,7 +71,7 @@ static inline int atomic_futex_op_xchg_and(int oparg, int __user *uaddr,
 	return ret;
 }
 
-static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr,
+static inline int atomic_futex_op_xchg_xor(int oparg, u32 __user *uaddr,
 					   int *oldval)
 {
 	unsigned long flags;
@@ -88,12 +88,13 @@ static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr,
 	return ret;
 }
 
-static inline int atomic_futex_op_cmpxchg_inatomic(int *uval,
-						   int __user *uaddr,
-						   int oldval, int newval)
+static inline int atomic_futex_op_cmpxchg_inatomic(u32 *uval,
+						   u32 __user *uaddr,
+						   u32 oldval, u32 newval)
 {
 	unsigned long flags;
-	int ret, prev = 0;
+	int ret;
+	u32 prev = 0;
 
 	local_irq_save(flags);
 
diff --git a/arch/sh/include/asm/futex.h b/arch/sh/include/asm/futex.h
index a8a5125..7be39a6 100644
--- a/arch/sh/include/asm/futex.h
+++ b/arch/sh/include/asm/futex.h
@@ -10,7 +10,7 @@
 /* XXX: UP variants, fix for SH-4A and SMP.. */
 #include <asm/futex-irq.h>
 
-static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -21,7 +21,7 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -65,10 +65,10 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
-			      int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	return atomic_futex_op_cmpxchg_inatomic(uval, uaddr, oldval, newval);
diff --git a/arch/sparc/include/asm/futex_64.h b/arch/sparc/include/asm/futex_64.h
index e086220..444e7be 100644
--- a/arch/sparc/include/asm/futex_64.h
+++ b/arch/sparc/include/asm/futex_64.h
@@ -30,7 +30,7 @@
 	: "r" (uaddr), "r" (oparg), "i" (-EFAULT)	\
 	: "memory")
 
-static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -38,7 +38,7 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 	int cmparg = (encoded_op << 20) >> 20;
 	int oldval = 0, ret, tem;
 
-	if (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(int))))
+	if (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))))
 		return -EFAULT;
 	if (unlikely((((unsigned long) uaddr) & 0x3UL)))
 		return -EINVAL;
@@ -85,8 +85,8 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
-			      int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
 	int ret = 0;
 
diff --git a/arch/tile/include/asm/futex.h b/arch/tile/include/asm/futex.h
index 664b20a..d03ec12 100644
--- a/arch/tile/include/asm/futex.h
+++ b/arch/tile/include/asm/futex.h
@@ -29,16 +29,16 @@
 #include <linux/uaccess.h>
 #include <linux/errno.h>
 
-extern struct __get_user futex_set(int __user *v, int i);
-extern struct __get_user futex_add(int __user *v, int n);
-extern struct __get_user futex_or(int __user *v, int n);
-extern struct __get_user futex_andn(int __user *v, int n);
-extern struct __get_user futex_cmpxchg(int __user *v, int o, int n);
+extern struct __get_user futex_set(u32 __user *v, int i);
+extern struct __get_user futex_add(u32 __user *v, int n);
+extern struct __get_user futex_or(u32 __user *v, int n);
+extern struct __get_user futex_andn(u32 __user *v, int n);
+extern struct __get_user futex_cmpxchg(u32 __user *v, int o, int n);
 
 #ifndef __tilegx__
-extern struct __get_user futex_xor(int __user *v, int n);
+extern struct __get_user futex_xor(u32 __user *v, int n);
 #else
-static inline struct __get_user futex_xor(int __user *uaddr, int n)
+static inline struct __get_user futex_xor(u32 __user *uaddr, int n)
 {
 	struct __get_user asm_ret = __get_user_4(uaddr);
 	if (!asm_ret.err) {
@@ -53,7 +53,7 @@ static inline struct __get_user futex_xor(int __user *uaddr, int n)
 }
 #endif
 
-static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -65,7 +65,7 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -119,12 +119,12 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 	return ret;
 }
 
-static inline int futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
-						int oldval, int newval)
+static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+						u32 oldval, u32 newval)
 {
 	struct __get_user asm_ret;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	asm_ret = futex_cmpxchg(uaddr, oldval, newval);
diff --git a/arch/x86/include/asm/futex.h b/arch/x86/include/asm/futex.h
index 884c0b5..d09bb03 100644
--- a/arch/x86/include/asm/futex.h
+++ b/arch/x86/include/asm/futex.h
@@ -37,7 +37,7 @@
 		       "+m" (*uaddr), "=&r" (tem)		\
 		     : "r" (oparg), "i" (-EFAULT), "1" (0))
 
-static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -48,7 +48,7 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 #if defined(CONFIG_X86_32) && !defined(CONFIG_X86_BSWAP)
@@ -109,8 +109,8 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 	return ret;
 }
 
-static inline int futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
-						int oldval, int newval)
+static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+						u32 oldval, u32 newval)
 {
 	int ret = 0;
 
@@ -120,7 +120,7 @@ static inline int futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
 		return -ENOSYS;
 #endif
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	asm volatile("1:\t" LOCK_PREFIX "cmpxchgl %4, %2\n"
diff --git a/include/asm-generic/futex.h b/include/asm-generic/futex.h
index 132bf52..01f227e 100644
--- a/include/asm-generic/futex.h
+++ b/include/asm-generic/futex.h
@@ -6,7 +6,7 @@
 #include <asm/errno.h>
 
 static inline int
-futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -16,7 +16,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -48,8 +48,8 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
-			      int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
 	return -ENOSYS;
 }

^ permalink raw reply related	[flat|nested] 42+ messages in thread

* Re: [PATCH 1/3] futex: do not pagefault_disable in futex_atomic_cmpxchg_inatomic()
  2011-03-11  2:47         ` [PATCH 1/3] futex: do not pagefault_disable in futex_atomic_cmpxchg_inatomic() Michel Lespinasse
  2011-03-11 11:31           ` [tip:core/futexes] futex: Remove redundant " tip-bot for Michel Lespinasse
@ 2011-03-13 22:49           ` Linus Torvalds
  2011-03-14  0:55             ` Darren Hart
                               ` (2 more replies)
  1 sibling, 3 replies; 42+ messages in thread
From: Linus Torvalds @ 2011-03-13 22:49 UTC (permalink / raw)
  To: Michel Lespinasse
  Cc: Thomas Gleixner, Darren Hart, Ingo Molnar, Peter Zijlstra,
	Matt Turner, Russell King, David Howells, Tony Luck,
	Michal Simek, Ralf Baechle, James E.J. Bottomley,
	Benjamin Herrenschmidt, Martin Schwidefsky, Paul Mundt,
	David S. Miller, Chris Metcalf, Andrew Morton, LKML

On Thu, Mar 10, 2011 at 6:47 PM, Michel Lespinasse <walken@google.com> wrote:
> kernel/futex.c disables page faults before calling
> futex_atomic_cmpxchg_inatomic(), so there is no need to do it again
> within that function.

This seems totally bogus.

Even the comment is crap.

Sure, the callers may disable preemption, but that has NOTHING to do
with "pagefault_disable()". Th epagefault_[en/dis]able functions will
touch the preempt count EVEN IF PREEMPTION ISN'T EVEN ENABLED!

So what the f*ck does that "Note that preemption is disabled.." crap even mean?

The thing is made even worse by the fact that as far as I can tell,
the comment simply isn't true at all (even if you were to ignore the
fundamental confusion about preemption vs the pagefault
disable/enable). Not all callers of futex_atomic_cmpxchg_inatomic() do
anything of the sort, whether it's preemptibility _or_ the proper
pagefault_disable/enable(). Just look at the exit_robust_list() ->
handle_futex_death(), for example.

This kind of patch is the kind that personally makes me want to put
you on a spam-list. Misleading commit messages with bogus and
fundamentally incorrect added comments in the code. WTF?

Did I miss some patch that changed that, or is this really as horribly
bad as I think it is? I see it already made it into -tip.

                              Linus

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 1/3] futex: do not pagefault_disable in futex_atomic_cmpxchg_inatomic()
  2011-03-13 22:49           ` [PATCH 1/3] futex: do not " Linus Torvalds
@ 2011-03-14  0:55             ` Darren Hart
  2011-03-14  1:15               ` Darren Hart
  2011-03-14  9:13               ` Peter Zijlstra
  2011-03-14  9:13             ` Thomas Gleixner
  2011-03-14  9:15             ` [PATCH 1/3] futex: do not pagefault_disable " Michel Lespinasse
  2 siblings, 2 replies; 42+ messages in thread
From: Darren Hart @ 2011-03-14  0:55 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Michel Lespinasse, Thomas Gleixner, Ingo Molnar, Peter Zijlstra,
	Matt Turner, Russell King, David Howells, Tony Luck,
	Michal Simek, Ralf Baechle, James E.J. Bottomley,
	Benjamin Herrenschmidt, Martin Schwidefsky, Paul Mundt,
	David S. Miller, Chris Metcalf, Andrew Morton, LKML

I have to apologize. These landed right as I was leaving for OSTS and
I didn't have time to review them properly.  I wondered about the
preempt vs pagefault disable and wondered how exit_robust_list() was
covered in Michel's comments (perhaps somewhere higher up the call
chain). I leaned on the review of others when I should have raised the
questions even if I didn't have the time to dig into them myself.
Linus shouldn't have had to raise those questions, I'll do better at
this in the future.

I noticed that my name is the only one in futex.c with an email
address in the header - that email address is no longer valid, and it
delayed the patches getting to my inbox - I will submit a patch to fix
that. I should catch them sooner now, regardless, with improved LKML
filters.

Thanks,

Darren Hart


On Sun, Mar 13, 2011 at 3:49 PM, Linus Torvalds
<torvalds@linux-foundation.org> wrote:
> On Thu, Mar 10, 2011 at 6:47 PM, Michel Lespinasse <walken@google.com> wrote:
>> kernel/futex.c disables page faults before calling
>> futex_atomic_cmpxchg_inatomic(), so there is no need to do it again
>> within that function.
>
> This seems totally bogus.
>
> Even the comment is crap.
>
> Sure, the callers may disable preemption, but that has NOTHING to do
> with "pagefault_disable()". Th epagefault_[en/dis]able functions will
> touch the preempt count EVEN IF PREEMPTION ISN'T EVEN ENABLED!
>
> So what the f*ck does that "Note that preemption is disabled.." crap even mean?
>
> The thing is made even worse by the fact that as far as I can tell,
> the comment simply isn't true at all (even if you were to ignore the
> fundamental confusion about preemption vs the pagefault
> disable/enable). Not all callers of futex_atomic_cmpxchg_inatomic() do
> anything of the sort, whether it's preemptibility _or_ the proper
> pagefault_disable/enable(). Just look at the exit_robust_list() ->
> handle_futex_death(), for example.
>
> This kind of patch is the kind that personally makes me want to put
> you on a spam-list. Misleading commit messages with bogus and
> fundamentally incorrect added comments in the code. WTF?
>
> Did I miss some patch that changed that, or is this really as horribly
> bad as I think it is? I see it already made it into -tip.
>
>                              Linus
>



-- 
Darren Hart

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 1/3] futex: do not pagefault_disable in futex_atomic_cmpxchg_inatomic()
  2011-03-14  0:55             ` Darren Hart
@ 2011-03-14  1:15               ` Darren Hart
  2011-03-14  9:13               ` Peter Zijlstra
  1 sibling, 0 replies; 42+ messages in thread
From: Darren Hart @ 2011-03-14  1:15 UTC (permalink / raw)
  To: Darren Hart
  Cc: Linus Torvalds, Michel Lespinasse, Thomas Gleixner, Ingo Molnar,
	Peter Zijlstra, Matt Turner, Russell King, David Howells,
	Tony Luck, Michal Simek, Ralf Baechle, James E.J. Bottomley,
	Benjamin Herrenschmidt, Martin Schwidefsky, Paul Mundt,
	David S. Miller, Chris Metcalf, Andrew Morton, LKML

On 03/13/2011 05:55 PM, Darren Hart wrote:
> I have to apologize. These landed right as I was leaving for OSTS and
> I didn't have time to review them properly.  I wondered about the
> preempt vs pagefault disable and wondered how exit_robust_list() was
> covered in Michel's comments (perhaps somewhere higher up the call
> chain). I leaned on the review of others when I should have raised the
> questions even if I didn't have the time to dig into them myself.
> Linus shouldn't have had to raise those questions, I'll do better at
> this in the future.
>
> I noticed that my name is the only one in futex.c with an email
> address in the header

Scratch that, the others are just on the Copyright line instead of the 
feature line. What is the policy for updating email addresses in source 
files? With git, I suppose they are no longer particularly useful. 
Should I remove a bad address, or just learn from it and not include it 
in future work?

Thanks,

-- 
Darren Hart
Intel Open Source Technology Center
Yocto Project - Linux Kernel

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 1/3] futex: do not pagefault_disable in futex_atomic_cmpxchg_inatomic()
  2011-03-14  0:55             ` Darren Hart
  2011-03-14  1:15               ` Darren Hart
@ 2011-03-14  9:13               ` Peter Zijlstra
  1 sibling, 0 replies; 42+ messages in thread
From: Peter Zijlstra @ 2011-03-14  9:13 UTC (permalink / raw)
  To: Darren Hart
  Cc: Linus Torvalds, Michel Lespinasse, Thomas Gleixner, Ingo Molnar,
	Matt Turner, Russell King, David Howells, Tony Luck,
	Michal Simek, Ralf Baechle, James E.J. Bottomley,
	Benjamin Herrenschmidt, Martin Schwidefsky, Paul Mundt,
	David S. Miller, Chris Metcalf, Andrew Morton, LKML

On Sun, 2011-03-13 at 17:55 -0700, Darren Hart wrote:
> I wondered about the preempt vs pagefault disable 

In current mainline they happen to be the same, but for -rt they're not.

Its also conceptually different, with preempt disable we dis-allow any
scheduling, which thus also precludes most fault handlers.

Disabling pagefault can be done without also disabling preemption (as is
done in -rt) and simply means that we'll never try to handle the fault
and fallback to the exception table or give up and segfault the kernel.

Its not dis-similar to the whole rcu_read_lock() vs preempt_disable()
stuff, for a while one implied the other.

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 1/3] futex: do not pagefault_disable in futex_atomic_cmpxchg_inatomic()
  2011-03-13 22:49           ` [PATCH 1/3] futex: do not " Linus Torvalds
  2011-03-14  0:55             ` Darren Hart
@ 2011-03-14  9:13             ` Thomas Gleixner
  2011-03-14 13:56               ` Thomas Gleixner
  2011-03-14  9:15             ` [PATCH 1/3] futex: do not pagefault_disable " Michel Lespinasse
  2 siblings, 1 reply; 42+ messages in thread
From: Thomas Gleixner @ 2011-03-14  9:13 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Michel Lespinasse, Darren Hart, Ingo Molnar, Peter Zijlstra,
	Matt Turner, Russell King, David Howells, Tony Luck,
	Michal Simek, Ralf Baechle, James E.J. Bottomley,
	Benjamin Herrenschmidt, Martin Schwidefsky, Paul Mundt,
	David S. Miller, Chris Metcalf, Andrew Morton, LKML

On Sun, 13 Mar 2011, Linus Torvalds wrote:
> On Thu, Mar 10, 2011 at 6:47 PM, Michel Lespinasse <walken@google.com> wrote:
> > kernel/futex.c disables page faults before calling
> > futex_atomic_cmpxchg_inatomic(), so there is no need to do it again
> > within that function.
> 
> This seems totally bogus.
> 
> Even the comment is crap.
> 
> Sure, the callers may disable preemption, but that has NOTHING to do
> with "pagefault_disable()". Th epagefault_[en/dis]able functions will
> touch the preempt count EVEN IF PREEMPTION ISN'T EVEN ENABLED!
> 
> So what the f*ck does that "Note that preemption is disabled.." crap even mean?
> 
> The thing is made even worse by the fact that as far as I can tell,
> the comment simply isn't true at all (even if you were to ignore the
> fundamental confusion about preemption vs the pagefault
> disable/enable). Not all callers of futex_atomic_cmpxchg_inatomic() do
> anything of the sort, whether it's preemptibility _or_ the proper
> pagefault_disable/enable(). Just look at the exit_robust_list() ->
> handle_futex_death(), for example.
> 
> This kind of patch is the kind that personally makes me want to put
> you on a spam-list. Misleading commit messages with bogus and
> fundamentally incorrect added comments in the code. WTF?
> 
> Did I miss some patch that changed that, or is this really as horribly
> bad as I think it is? I see it already made it into -tip.

That's my fault. 

I really checked the call sites of futex_atomic_cmpxchg_inatomic() and
totally failed to see the one in handle_futex_death() which does not
use the helper function cmpxchg_futex_value_locked(). That helper
function is safe and does the right thing:

	pagefault_disable();
	curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval);
	pagefault_enable();

So, that means we have all call sites covered except one, which needs
to be fixed _AND_ also pushed into stable as all arch implementations
except ARM rely on the caller doing the pagefault_disable().

And I missed the bogus comment as well. Sigh.

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 1/3] futex: do not pagefault_disable in futex_atomic_cmpxchg_inatomic()
  2011-03-13 22:49           ` [PATCH 1/3] futex: do not " Linus Torvalds
  2011-03-14  0:55             ` Darren Hart
  2011-03-14  9:13             ` Thomas Gleixner
@ 2011-03-14  9:15             ` Michel Lespinasse
  2 siblings, 0 replies; 42+ messages in thread
From: Michel Lespinasse @ 2011-03-14  9:15 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Thomas Gleixner, Darren Hart, Ingo Molnar, Peter Zijlstra,
	Matt Turner, Russell King, David Howells, Tony Luck,
	Michal Simek, Ralf Baechle, James E.J. Bottomley,
	Benjamin Herrenschmidt, Martin Schwidefsky, Paul Mundt,
	David S. Miller, Chris Metcalf, Andrew Morton, LKML

On Sun, Mar 13, 2011 at 3:49 PM, Linus Torvalds
<torvalds@linux-foundation.org> wrote:
> On Thu, Mar 10, 2011 at 6:47 PM, Michel Lespinasse <walken@google.com> wrote:
>> kernel/futex.c disables page faults before calling
>> futex_atomic_cmpxchg_inatomic(), so there is no need to do it again
>> within that function.
>
> This seems totally bogus.
>
> Even the comment is crap.
>
> Sure, the callers may disable preemption, but that has NOTHING to do
> with "pagefault_disable()". Th epagefault_[en/dis]able functions will
> touch the preempt count EVEN IF PREEMPTION ISN'T EVEN ENABLED!

I understand pagefault_disable() and preempt_disable() are different
concepts, but their implementations have a lot in common...

> So what the f*ck does that "Note that preemption is disabled.." crap even mean?

I was thinking that if cmpxchg_futex_value_locked() already raised the
preempt count, it seemed redundant to do it again (and then decrement
it back) in a nested way within futex_atomic_cmpxchg_inatomic on arm.

> The thing is made even worse by the fact that as far as I can tell,
> the comment simply isn't true at all (even if you were to ignore the
> fundamental confusion about preemption vs the pagefault
> disable/enable). Not all callers of futex_atomic_cmpxchg_inatomic() do
> anything of the sort, whether it's preemptibility _or_ the proper
> pagefault_disable/enable(). Just look at the exit_robust_list() ->
> handle_futex_death(), for example.

You got me there - clearly I f*cked up. What really irks me is that I
have a retrospectively bogus memory of actually looking at that call
site and seeing a pagefault_disable there... But as is now obvious,
it's never been there :/

-- 
Michel "Walken" Lespinasse
A program is never fully debugged until the last user dies.

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 1/3] futex: do not pagefault_disable in futex_atomic_cmpxchg_inatomic()
  2011-03-14  9:13             ` Thomas Gleixner
@ 2011-03-14 13:56               ` Thomas Gleixner
  2011-03-14 20:07                 ` Darren Hart
                                   ` (2 more replies)
  0 siblings, 3 replies; 42+ messages in thread
From: Thomas Gleixner @ 2011-03-14 13:56 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Michel Lespinasse, Darren Hart, Ingo Molnar, Peter Zijlstra,
	Matt Turner, Russell King, David Howells, Tony Luck,
	Michal Simek, Ralf Baechle, James E.J. Bottomley,
	Benjamin Herrenschmidt, Martin Schwidefsky, Paul Mundt,
	David S. Miller, Chris Metcalf, Andrew Morton, LKML

On Mon, 14 Mar 2011, Thomas Gleixner wrote:
> On Sun, 13 Mar 2011, Linus Torvalds wrote:
> > On Thu, Mar 10, 2011 at 6:47 PM, Michel Lespinasse <walken@google.com> wrote:
> That's my fault. 
> 
> I really checked the call sites of futex_atomic_cmpxchg_inatomic() and
> totally failed to see the one in handle_futex_death() which does not
> use the helper function cmpxchg_futex_value_locked(). That helper
> function is safe and does the right thing:
> 
> 	pagefault_disable();
> 	curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval);
> 	pagefault_enable();
> 
> So, that means we have all call sites covered except one, which needs
> to be fixed _AND_ also pushed into stable as all arch implementations
> except ARM rely on the caller doing the pagefault_disable().

After applying some coffee to my brain, I noticed that the ability to
fault in handle_futex_death() is desired. The get_user() before that
call covers the case where the futex is paged out, but it does not
handle the case where the futex is in a non writeable mapping. That
lacks a big fat comment at least.

So the removal of the pagefault_disable() in ARM is correct, just the
changelog and the comment there sucks. Sorry for not catching it.

Thinking more about it. Adding a comment is to handle_futex_death() is
good, but changing the code to make it entirely clear what is going on
is even better.

-------->
Subject: futex: Deobfuscate handle_futex_death()
From: Thomas Gleixner <tglx@linutronix.de>
Date: Mon, 14 Mar 2011 10:34:35 +0100

handle_futex_death() uses futex_atomic_cmpxchg_inatomic() without
disabling page faults. That's ok, but totally non obvious.

We don't hold locks so we actually can and want to fault here, because
the get_user() before futex_atomic_cmpxchg_inatomic() does not
guarantee a R/W mapping.

We could just add a big fat comment to explain this, but actually
changing the code so that the functionality is entirely clear is
better.

Use the helper function which disables page faults around the
futex_atomic_cmpxchg_inatomic() and handle a fault with a call to
fault_in_user_writeable() as all other places in the futex code do as
well.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 kernel/futex.c |   17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)

Index: linux-2.6-tip/kernel/futex.c
===================================================================
--- linux-2.6-tip.orig/kernel/futex.c
+++ linux-2.6-tip/kernel/futex.c
@@ -2458,9 +2458,20 @@ retry:
 		 * userspace.
 		 */
 		mval = (uval & FUTEX_WAITERS) | FUTEX_OWNER_DIED;
-		if (futex_atomic_cmpxchg_inatomic(&nval, uaddr, uval, mval))
-			return -1;
-
+		/*
+		 * We are not holding a lock here, but we want to have
+		 * the pagefault_disable/enable() protection because
+		 * we want to handle the fault gracefully. If the
+		 * access fails we try to fault in the futex with R/W
+		 * verification via get_user_pages. get_user() above
+		 * does not guarantee R/W access. If that fails we
+		 * give up and leave the futex locked.
+		 */
+		if (cmpxchg_futex_value_locked(&nval, uaddr, uval, mval)) {
+			if (fault_in_user_writeable(uaddr))
+				return -1;
+			goto retry;
+		}
 		if (nval != uval)
 			goto retry;
 

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 1/3] futex: do not pagefault_disable in futex_atomic_cmpxchg_inatomic()
  2011-03-14 13:56               ` Thomas Gleixner
@ 2011-03-14 20:07                 ` Darren Hart
  2011-03-14 20:15                 ` [tip:core/futexes] futex: Deobfuscate handle_futex_death() tip-bot for Thomas Gleixner
  2011-03-14 20:16                 ` [tip:core/futexes] arm: Remove bogus comment in futex_atomic_cmpxchg_inatomic() tip-bot for Thomas Gleixner
  2 siblings, 0 replies; 42+ messages in thread
From: Darren Hart @ 2011-03-14 20:07 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Linus Torvalds, Michel Lespinasse, Darren Hart, Ingo Molnar,
	Peter Zijlstra, Matt Turner, Russell King, David Howells,
	Tony Luck, Michal Simek, Ralf Baechle, James E.J. Bottomley,
	Benjamin Herrenschmidt, Martin Schwidefsky, Paul Mundt,
	David S. Miller, Chris Metcalf, Andrew Morton, LKML

On 03/14/2011 06:56 AM, Thomas Gleixner wrote:
> On Mon, 14 Mar 2011, Thomas Gleixner wrote:
>> On Sun, 13 Mar 2011, Linus Torvalds wrote:
>>> On Thu, Mar 10, 2011 at 6:47 PM, Michel Lespinasse<walken@google.com>  wrote:
>> That's my fault.
>>
>> I really checked the call sites of futex_atomic_cmpxchg_inatomic() and
>> totally failed to see the one in handle_futex_death() which does not
>> use the helper function cmpxchg_futex_value_locked(). That helper
>> function is safe and does the right thing:
>>
>> 	pagefault_disable();
>> 	curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval);
>> 	pagefault_enable();
>>
>> So, that means we have all call sites covered except one, which needs
>> to be fixed _AND_ also pushed into stable as all arch implementations
>> except ARM rely on the caller doing the pagefault_disable().
>
> After applying some coffee to my brain, I noticed that the ability to
> fault in handle_futex_death() is desired. The get_user() before that
> call covers the case where the futex is paged out, but it does not
> handle the case where the futex is in a non writeable mapping. That
> lacks a big fat comment at least.
>
> So the removal of the pagefault_disable() in ARM is correct, just the
> changelog and the comment there sucks. Sorry for not catching it.
>
> Thinking more about it. Adding a comment is to handle_futex_death() is
> good, but changing the code to make it entirely clear what is going on
> is even better.
>
> -------->
> Subject: futex: Deobfuscate handle_futex_death()
> From: Thomas Gleixner<tglx@linutronix.de>
> Date: Mon, 14 Mar 2011 10:34:35 +0100
>
> handle_futex_death() uses futex_atomic_cmpxchg_inatomic() without
> disabling page faults. That's ok, but totally non obvious.
>
> We don't hold locks so we actually can and want to fault here, because
> the get_user() before futex_atomic_cmpxchg_inatomic() does not
> guarantee a R/W mapping.
>
> We could just add a big fat comment to explain this, but actually
> changing the code so that the functionality is entirely clear is
> better.
>
> Use the helper function which disables page faults around the
> futex_atomic_cmpxchg_inatomic() and handle a fault with a call to
> fault_in_user_writeable() as all other places in the futex code do as
> well.
>
> Signed-off-by: Thomas Gleixner<tglx@linutronix.de>

Acked-by: Darren Hart <dvhart@linux.intel.com>

> ---
>   kernel/futex.c |   17 ++++++++++++++---
>   1 file changed, 14 insertions(+), 3 deletions(-)
>
> Index: linux-2.6-tip/kernel/futex.c
> ===================================================================
> --- linux-2.6-tip.orig/kernel/futex.c
> +++ linux-2.6-tip/kernel/futex.c
> @@ -2458,9 +2458,20 @@ retry:
>   		 * userspace.
>   		 */
>   		mval = (uval&  FUTEX_WAITERS) | FUTEX_OWNER_DIED;
> -		if (futex_atomic_cmpxchg_inatomic(&nval, uaddr, uval, mval))
> -			return -1;
> -
> +		/*
> +		 * We are not holding a lock here, but we want to have
> +		 * the pagefault_disable/enable() protection because
> +		 * we want to handle the fault gracefully. If the
> +		 * access fails we try to fault in the futex with R/W
> +		 * verification via get_user_pages. get_user() above
> +		 * does not guarantee R/W access. If that fails we
> +		 * give up and leave the futex locked.
> +		 */
> +		if (cmpxchg_futex_value_locked(&nval, uaddr, uval, mval)) {
> +			if (fault_in_user_writeable(uaddr))
> +				return -1;
> +			goto retry;
> +		}
>   		if (nval != uval)
>   			goto retry;
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/


-- 
Darren Hart
Intel Open Source Technology Center
Yocto Project - Linux Kernel

^ permalink raw reply	[flat|nested] 42+ messages in thread

* [tip:core/futexes] futex: Deobfuscate handle_futex_death()
  2011-03-14 13:56               ` Thomas Gleixner
  2011-03-14 20:07                 ` Darren Hart
@ 2011-03-14 20:15                 ` tip-bot for Thomas Gleixner
  2011-03-14 20:16                 ` [tip:core/futexes] arm: Remove bogus comment in futex_atomic_cmpxchg_inatomic() tip-bot for Thomas Gleixner
  2 siblings, 0 replies; 42+ messages in thread
From: tip-bot for Thomas Gleixner @ 2011-03-14 20:15 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: mingo, torvalds, schwidefsky, peterz, cmetcalf, tony.luck, ralf,
	monstr, linux, tglx, linux-kernel, hpa, darren, lethal, davem,
	dhowells, benh, mattst88, jejb, walken

Commit-ID:  6e0aa9f8a8190e0879a29bd67aa606b51734a122
Gitweb:     http://git.kernel.org/tip/6e0aa9f8a8190e0879a29bd67aa606b51734a122
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Mon, 14 Mar 2011 10:34:35 +0100
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Mon, 14 Mar 2011 21:08:47 +0100

futex: Deobfuscate handle_futex_death()

handle_futex_death() uses futex_atomic_cmpxchg_inatomic() without
disabling page faults. That's ok, but totally non obvious.

We don't hold locks so we actually can and want to fault here, because
the get_user() before futex_atomic_cmpxchg_inatomic() does not
guarantee a R/W mapping.

We could just add a big fat comment to explain this, but actually
changing the code so that the functionality is entirely clear is
better.

Use the helper function which disables page faults around the
futex_atomic_cmpxchg_inatomic() and handle a fault with a call to
fault_in_user_writeable() as all other places in the futex code do as
well.

Pointed-out-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Darren Hart <darren@dvhart.com>
Cc: Michel Lespinasse <walken@google.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Matt Turner <mattst88@gmail.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: David Howells <dhowells@redhat.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Michal Simek <monstr@monstr.eu>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: "James E.J. Bottomley" <jejb@parisc-linux.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Paul Mundt <lethal@linux-sh.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Chris Metcalf <cmetcalf@tilera.com>
LKML-Reference: <alpine.LFD.2.00.1103141126590.2787@localhost6.localdomain6>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 kernel/futex.c |   17 ++++++++++++++---
 1 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/kernel/futex.c b/kernel/futex.c
index c6bef6e..e9251d9 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -2458,9 +2458,20 @@ retry:
 		 * userspace.
 		 */
 		mval = (uval & FUTEX_WAITERS) | FUTEX_OWNER_DIED;
-		if (futex_atomic_cmpxchg_inatomic(&nval, uaddr, uval, mval))
-			return -1;
-
+		/*
+		 * We are not holding a lock here, but we want to have
+		 * the pagefault_disable/enable() protection because
+		 * we want to handle the fault gracefully. If the
+		 * access fails we try to fault in the futex with R/W
+		 * verification via get_user_pages. get_user() above
+		 * does not guarantee R/W access. If that fails we
+		 * give up and leave the futex locked.
+		 */
+		if (cmpxchg_futex_value_locked(&nval, uaddr, uval, mval)) {
+			if (fault_in_user_writeable(uaddr))
+				return -1;
+			goto retry;
+		}
 		if (nval != uval)
 			goto retry;
 

^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [tip:core/futexes] arm: Remove bogus comment in futex_atomic_cmpxchg_inatomic()
  2011-03-14 13:56               ` Thomas Gleixner
  2011-03-14 20:07                 ` Darren Hart
  2011-03-14 20:15                 ` [tip:core/futexes] futex: Deobfuscate handle_futex_death() tip-bot for Thomas Gleixner
@ 2011-03-14 20:16                 ` tip-bot for Thomas Gleixner
  2 siblings, 0 replies; 42+ messages in thread
From: tip-bot for Thomas Gleixner @ 2011-03-14 20:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, hpa, mingo, torvalds, darren, tglx, walken

Commit-ID:  07d5ecae2940ddd77746e2fb597dcf57d3c2e277
Gitweb:     http://git.kernel.org/tip/07d5ecae2940ddd77746e2fb597dcf57d3c2e277
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Mon, 14 Mar 2011 20:00:30 +0100
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Mon, 14 Mar 2011 21:10:26 +0100

arm: Remove bogus comment in futex_atomic_cmpxchg_inatomic()

commit 522d7dec(futex: Remove redundant pagefault_disable in
futex_atomic_cmpxchg_inatomic()) added a bogus comment.

/* Note that preemption is disabled by futex_atomic_cmpxchg_inatomic
 * call sites. */

Bogus in two aspects:

1) pagefault_disable != preempt_disable even if the mechanism we use
   is the same

2) we have a call site which deliberately does not disable pagefaults
   as it wants the possible fault to be handled - though that has been
   changed for consistency reasons now.

Sigh. I really should have seen that when committing the above. :(

Catched-by-and-rightfully-ranted-at-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
LKML-Reference: <alpine.LFD.2.00.1103141126590.2787@localhost6.localdomain6>
Cc: Michel Lespinasse <walken@google.com>
Cc: Darren Hart <darren@dvhart.com>
---
 arch/arm/include/asm/futex.h |    3 ---
 1 files changed, 0 insertions(+), 3 deletions(-)

diff --git a/arch/arm/include/asm/futex.h b/arch/arm/include/asm/futex.h
index 0e29d8e..199a6b6 100644
--- a/arch/arm/include/asm/futex.h
+++ b/arch/arm/include/asm/futex.h
@@ -97,9 +97,6 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
 	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
-	/* Note that preemption is disabled by futex_atomic_cmpxchg_inatomic
-	 * call sites. */
-
 	__asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n"
 	"1:	" T(ldr) "	%1, [%4]\n"
 	"	teq	%1, %2\n"

^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [regression] Re: [PATCH 2/3] futex: Sanitize cmpxchg_futex_value_locked API
  2011-03-11  2:48         ` [PATCH 2/3] futex: cmpxchg_futex_value_locked API change Michel Lespinasse
@ 2012-03-05  0:01             ` Jonathan Nieder
  2012-03-05  0:01             ` Jonathan Nieder
  1 sibling, 0 replies; 42+ messages in thread
From: Jonathan Nieder @ 2012-03-05  0:01 UTC (permalink / raw)
  To: linux-ia64
  Cc: Michel Lespinasse, Tony Luck, Émeric Maschino,
	Patrick Baggett, Jakub Jelinek, linux-kernel

(reset cc list)
Hi,

Michel Lespinasse wrote:

> This change makes the cmpxchg_futex_value_locked API more similar to the
> get_futex_value_locked one, returning an error code and updating the
> original value through a reference argument.
[...]
> Acked-by: Tony Luck <tony.luck@intel.com>  [ia64]

Émeric Maschino (cc-ed) is experiencing random crashes, X restarts,
and so on on Itanium.  Bisects to this patch[1].

Patrick Baggett, investigating, wrote[2]:

> It doesn't look like the return value (r8) is actually being set beyond
> initialized to 0. If there is some ia64 instruction that modifies it, GCC
> doesn't know about it from the inline assembly (r8 doesn't appear in the
> inputs/outputs list). From looking at the x86 version (agh, inline asm is
> hard to parse), it does modify the return value based on whether the
> comparison was a success or not, and the return value is certainly used by
> the callers.

And indeed, pinning that variable to that register (why not "prev"
instead?) looks suspicious.

Anywhere, here's the potentially problematic patch hunk.  Ideas?

> --- a/arch/ia64/include/asm/futex.h
> +++ b/arch/ia64/include/asm/futex.h
> @@ -100,23 +100,26 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
>  }
>  
>  static inline int
> -futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
> +futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
> +			      int oldval, int newval)
>  {
>  	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
>  		return -EFAULT;
>  
>  	{
> -		register unsigned long r8 __asm ("r8");
> +		register unsigned long r8 __asm ("r8") = 0;
> +		unsigned long prev;
>  		__asm__ __volatile__(
>  			"	mf;;					\n"
>  			"	mov ar.ccv=%3;;				\n"
>  			"[1:]	cmpxchg4.acq %0=[%1],%2,ar.ccv		\n"
>  			"	.xdata4 \"__ex_table\", 1b-., 2f-.	\n"
>  			"[2:]"
> -			: "=r" (r8)
> +			: "=r" (prev)
>  			: "r" (uaddr), "r" (newval),
>  			  "rO" ((long) (unsigned) oldval)
>  			: "memory");
> +		*uval = prev;
>  		return r8;
>  	}
>  }

Jonathan

[1] https://bugzilla.kernel.org/show_bug.cgi?id=42757
[2] http://thread.gmane.org/gmane.linux.debian.ports.ia64/3121/focus=3123

^ permalink raw reply	[flat|nested] 42+ messages in thread

* [regression] Re: [PATCH 2/3] futex: Sanitize cmpxchg_futex_value_locked API
@ 2012-03-05  0:01             ` Jonathan Nieder
  0 siblings, 0 replies; 42+ messages in thread
From: Jonathan Nieder @ 2012-03-05  0:01 UTC (permalink / raw)
  To: linux-ia64
  Cc: Michel Lespinasse, Tony Luck, Émeric Maschino,
	Patrick Baggett, Jakub Jelinek, linux-kernel

(reset cc list)
Hi,

Michel Lespinasse wrote:

> This change makes the cmpxchg_futex_value_locked API more similar to the
> get_futex_value_locked one, returning an error code and updating the
> original value through a reference argument.
[...]
> Acked-by: Tony Luck <tony.luck@intel.com>  [ia64]

Émeric Maschino (cc-ed) is experiencing random crashes, X restarts,
and so on on Itanium.  Bisects to this patch[1].

Patrick Baggett, investigating, wrote[2]:

> It doesn't look like the return value (r8) is actually being set beyond
> initialized to 0. If there is some ia64 instruction that modifies it, GCC
> doesn't know about it from the inline assembly (r8 doesn't appear in the
> inputs/outputs list). From looking at the x86 version (agh, inline asm is
> hard to parse), it does modify the return value based on whether the
> comparison was a success or not, and the return value is certainly used by
> the callers.

And indeed, pinning that variable to that register (why not "prev"
instead?) looks suspicious.

Anywhere, here's the potentially problematic patch hunk.  Ideas?

> --- a/arch/ia64/include/asm/futex.h
> +++ b/arch/ia64/include/asm/futex.h
> @@ -100,23 +100,26 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
>  }
>  
>  static inline int
> -futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
> +futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
> +			      int oldval, int newval)
>  {
>  	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
>  		return -EFAULT;
>  
>  	{
> -		register unsigned long r8 __asm ("r8");
> +		register unsigned long r8 __asm ("r8") = 0;
> +		unsigned long prev;
>  		__asm__ __volatile__(
>  			"	mf;;					\n"
>  			"	mov ar.ccv=%3;;				\n"
>  			"[1:]	cmpxchg4.acq %0=[%1],%2,ar.ccv		\n"
>  			"	.xdata4 \"__ex_table\", 1b-., 2f-.	\n"
>  			"[2:]"
> -			: "=r" (r8)
> +			: "=r" (prev)
>  			: "r" (uaddr), "r" (newval),
>  			  "rO" ((long) (unsigned) oldval)
>  			: "memory");
> +		*uval = prev;
>  		return r8;
>  	}
>  }

Jonathan

[1] https://bugzilla.kernel.org/show_bug.cgi?idB757
[2] http://thread.gmane.org/gmane.linux.debian.ports.ia64/3121/focus123

^ permalink raw reply	[flat|nested] 42+ messages in thread

* RE: [regression] Re: [PATCH 2/3] futex: Sanitize cmpxchg_futex_value_locked API
  2012-03-05  0:01             ` Jonathan Nieder
@ 2012-03-05 23:21               ` Luck, Tony
  -1 siblings, 0 replies; 42+ messages in thread
From: Luck, Tony @ 2012-03-05 23:21 UTC (permalink / raw)
  To: Jonathan Nieder, linux-ia64
  Cc: Michel Lespinasse, Émeric Maschino, Patrick Baggett,
	Jakub Jelinek, linux-kernel

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="utf-8", Size: 1044 bytes --]

> It doesn't look like the return value (r8) is actually being set beyond
> initialized to 0. If there is some ia64 instruction that modifies it, GCC
> doesn't know about it from the inline assembly (r8 doesn't appear in the
> inputs/outputs list). From looking at the x86 version (agh, inline asm is
> hard to parse), it does modify the return value based on whether the
> comparison was a success or not, and the return value is certainly used by
> the callers.

The commit comment for the change makes it sound like the return value
is an error code (-ENOSYS if the function isn't implemented/configured;
-EFAULT if the user address is bogus) - or zero if nothing bad happened.

Not "the comparison was a success or not".

What's the real answer? The ia64 code is returning 0 regardless of whether the
compare/exchange found the old value or not.  Is this a bad assumption?

-Tony
ÿôèº{.nÇ+‰·Ÿ®‰­†+%ŠËÿ±éݶ\x17¥Šwÿº{.nÇ+‰·¥Š{±þG«éÿŠ{ayº\x1dʇڙë,j\a­¢f£¢·hšïêÿ‘êçz_è®\x03(­éšŽŠÝ¢j"ú\x1a¶^[m§ÿÿ¾\a«þG«éÿ¢¸?™¨è­Ú&£ø§~á¶iO•æ¬z·švØ^\x14\x04\x1a¶^[m§ÿÿÃ\fÿ¶ìÿ¢¸?–I¥

^ permalink raw reply	[flat|nested] 42+ messages in thread

* RE: [regression] Re: [PATCH 2/3] futex: Sanitize cmpxchg_futex_value_locked API
@ 2012-03-05 23:21               ` Luck, Tony
  0 siblings, 0 replies; 42+ messages in thread
From: Luck, Tony @ 2012-03-05 23:21 UTC (permalink / raw)
  To: Jonathan Nieder, linux-ia64
  Cc: Michel Lespinasse, Émeric Maschino, Patrick Baggett,
	Jakub Jelinek, linux-kernel

PiBJdCBkb2Vzbid0IGxvb2sgbGlrZSB0aGUgcmV0dXJuIHZhbHVlIChyOCkgaXMgYWN0dWFsbHkg
YmVpbmcgc2V0IGJleW9uZA0KPiBpbml0aWFsaXplZCB0byAwLiBJZiB0aGVyZSBpcyBzb21lIGlh
NjQgaW5zdHJ1Y3Rpb24gdGhhdCBtb2RpZmllcyBpdCwgR0NDDQo+IGRvZXNuJ3Qga25vdyBhYm91
dCBpdCBmcm9tIHRoZSBpbmxpbmUgYXNzZW1ibHkgKHI4IGRvZXNuJ3QgYXBwZWFyIGluIHRoZQ0K
PiBpbnB1dHMvb3V0cHV0cyBsaXN0KS4gRnJvbSBsb29raW5nIGF0IHRoZSB4ODYgdmVyc2lvbiAo
YWdoLCBpbmxpbmUgYXNtIGlzDQo+IGhhcmQgdG8gcGFyc2UpLCBpdCBkb2VzIG1vZGlmeSB0aGUg
cmV0dXJuIHZhbHVlIGJhc2VkIG9uIHdoZXRoZXIgdGhlDQo+IGNvbXBhcmlzb24gd2FzIGEgc3Vj
Y2VzcyBvciBub3QsIGFuZCB0aGUgcmV0dXJuIHZhbHVlIGlzIGNlcnRhaW5seSB1c2VkIGJ5DQo+
IHRoZSBjYWxsZXJzLg0KDQpUaGUgY29tbWl0IGNvbW1lbnQgZm9yIHRoZSBjaGFuZ2UgbWFrZXMg
aXQgc291bmQgbGlrZSB0aGUgcmV0dXJuIHZhbHVlDQppcyBhbiBlcnJvciBjb2RlICgtRU5PU1lT
IGlmIHRoZSBmdW5jdGlvbiBpc24ndCBpbXBsZW1lbnRlZC9jb25maWd1cmVkOw0KLUVGQVVMVCBp
ZiB0aGUgdXNlciBhZGRyZXNzIGlzIGJvZ3VzKSAtIG9yIHplcm8gaWYgbm90aGluZyBiYWQgaGFw
cGVuZWQuDQoNCk5vdCAidGhlIGNvbXBhcmlzb24gd2FzIGEgc3VjY2VzcyBvciBub3QiLg0KDQpX
aGF0J3MgdGhlIHJlYWwgYW5zd2VyPyBUaGUgaWE2NCBjb2RlIGlzIHJldHVybmluZyAwIHJlZ2Fy
ZGxlc3Mgb2Ygd2hldGhlciB0aGUNCmNvbXBhcmUvZXhjaGFuZ2UgZm91bmQgdGhlIG9sZCB2YWx1
ZSBvciBub3QuICBJcyB0aGlzIGEgYmFkIGFzc3VtcHRpb24/DQoNCi1Ub255DQo

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [regression] Re: [PATCH 2/3] futex: Sanitize cmpxchg_futex_value_locked API
  2012-03-05 23:21               ` Luck, Tony
@ 2012-03-05 23:42                 ` Jonathan Nieder
  -1 siblings, 0 replies; 42+ messages in thread
From: Jonathan Nieder @ 2012-03-05 23:42 UTC (permalink / raw)
  To: Luck, Tony
  Cc: linux-ia64, Michel Lespinasse, Émeric Maschino,
	Patrick Baggett, Jakub Jelinek, linux-kernel

Luck, Tony wrote:

>> It doesn't look like the return value (r8) is actually being set beyond
>> initialized to 0. If there is some ia64 instruction that modifies it, GCC
>> doesn't know about it from the inline assembly (r8 doesn't appear in the
>> inputs/outputs list). From looking at the x86 version (agh, inline asm is
>> hard to parse), it does modify the return value based on whether the
>> comparison was a success or not, and the return value is certainly used by
>> the callers.
>
> The commit comment for the change makes it sound like the return value
> is an error code (-ENOSYS if the function isn't implemented/configured;
> -EFAULT if the user address is bogus) - or zero if nothing bad happened.

Yes, that's right.

> Not "the comparison was a success or not".
>
> What's the real answer? The ia64 code is returning 0 regardless of whether the
> compare/exchange found the old value or not.  Is this a bad assumption?

No, I think something else is wrong, though I don't know what it would
be.

Émeric, was the bisection result reproducible?  E.g., if you try
building 37a9d912b24f and 37a9d912b24f^ again, does the former
consistently produce and the latter consistently not produce a crashy
system?

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [regression] Re: [PATCH 2/3] futex: Sanitize cmpxchg_futex_value_locked API
@ 2012-03-05 23:42                 ` Jonathan Nieder
  0 siblings, 0 replies; 42+ messages in thread
From: Jonathan Nieder @ 2012-03-05 23:42 UTC (permalink / raw)
  To: Luck, Tony
  Cc: linux-ia64, Michel Lespinasse, Émeric Maschino,
	Patrick Baggett, Jakub Jelinek, linux-kernel

Luck, Tony wrote:

>> It doesn't look like the return value (r8) is actually being set beyond
>> initialized to 0. If there is some ia64 instruction that modifies it, GCC
>> doesn't know about it from the inline assembly (r8 doesn't appear in the
>> inputs/outputs list). From looking at the x86 version (agh, inline asm is
>> hard to parse), it does modify the return value based on whether the
>> comparison was a success or not, and the return value is certainly used by
>> the callers.
>
> The commit comment for the change makes it sound like the return value
> is an error code (-ENOSYS if the function isn't implemented/configured;
> -EFAULT if the user address is bogus) - or zero if nothing bad happened.

Yes, that's right.

> Not "the comparison was a success or not".
>
> What's the real answer? The ia64 code is returning 0 regardless of whether the
> compare/exchange found the old value or not.  Is this a bad assumption?

No, I think something else is wrong, though I don't know what it would
be.

Émeric, was the bisection result reproducible?  E.g., if you try
building 37a9d912b24f and 37a9d912b24f^ again, does the former
consistently produce and the latter consistently not produce a crashy
system?

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [regression] Re: [PATCH 2/3] futex: Sanitize cmpxchg_futex_value_locked API
  2012-03-05 23:42                 ` Jonathan Nieder
@ 2012-03-08 20:59                   ` Émeric Maschino
  -1 siblings, 0 replies; 42+ messages in thread
From: Émeric Maschino @ 2012-03-08 20:59 UTC (permalink / raw)
  To: Jonathan Nieder
  Cc: Luck, Tony, linux-ia64, Michel Lespinasse, Patrick Baggett,
	Jakub Jelinek, linux-kernel

Hello,

Warning, long answer...

Le 6 mars 2012 00:42, Jonathan Nieder <jrnieder@gmail.com> a écrit :
> Émeric, was the bisection result reproducible?  E.g., if you try
> building 37a9d912b24f and 37a9d912b24f^ again, does the former
> consistently produce and the latter consistently not produce a crashy
> system?

Yes, definitely.

Building 37a9d912b24f leads to a broken kernel-2.6.38-rc8+ with the
symptoms described in [1]. Simply reverting 37a9d912b24f produces a
100% working kernel (well, w.r.t. the symptoms described in [1] of
course).

We exchanged a couple PMs with Tony on this subject. He first asked me
to check whether the issue is really because of the change in the ia64
bits of futex_atomic_cmpxchg_inatomic or not:

(Tony Luck, by PM, wrote to Emeric Maschino)

Could you try a half-revert of the kernel change.  Take the original
code for futex_atomic_cmpxchg_inatomic() but name it
ORIG_futex_atomic_cmpxchg_inatomic() then write the new as a wrapper
around the old one - something like:

futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, u32
oldval, u32 newval)
{
        int ret;

        ret = ORIG_futex_atomic_cmpxchg_inatomic(uaddr, oldval, newval);
        *uval = oldval;
        return (ret != oldval) ? ret : 0; /* ret<0 ?? ... this can't
cover all cases, but should be able to do something good enough */
}

If this makes the problem go away - we can start staring at the asm
bits some more to see just what is wrong with this new version of the
function.


I thus followed Tony's recommendation. Below is the result:

(Emeric Maschino, by PM, wrote to Tony Luck)

Well, partly. (about Tony's last remark: "If this makes the problem go away")

With a wrapper around the original API like you suggested above:
- the terminal window no more crashes when you hit the Tab key
- Iceweasel/Firefox no more triggers a X restart when clicking on a
menu or a button
- gdb no more exits early with a SIGTRAP signal.
That's for the good news.

The bad news: with the wrapper around the original API, I nevertheless
experience new side-effects:
- GDM3 no more displays user list, nor buttons, so you can't enter a X
session from there. I had to shut GDM3 down and manually enter a X
session with startx
- ioquake3-based Quake3 demo freezes while initializing sound.
As you already did noticed, perhaps are we hitting ret < 0 values there.

Is there something else I can try to help debugging further?


Tony then asked me to provide him with a reduced test case he could play with:

(Tony Luck, by PM, wrote to Emeric Maschino)

OK - so we do have a problem in the new implementation of this
function (otherwise this change shouldn't have had much effect).

I'd like a simple user mode test case that uses futexes to some
trivial thing. Doesn't matter whether it shows a problem, I can tweak
the test to try running into whatever corner case is causing the
problem.


And this is where I'm actually stuck.

Tony also pointed to me a futex test suite:

(Tony Luck, by PM, wrote to Emeric Maschino)

I found a futex test suite:

        git:://git.kernel.org/pub/scm/linux/kernel/git/dvhart/futextest.git

but it runs equally badly on kernel pre/post this change (I compared
v2.6.36 as the pre version, and current linus tree as the post).

Bah! an x86 system fails in the same way (pthread_create calls fail
for many tests - meaning they get skipped).


I don't know exactly how Tony run the test suite. On my side,
kernel-2.6.38-rc8+ (minus 37a9d912b24f) passed successfully. But it
had to be run as root, otherwise you'll get pthread_create errors as
experienced by Tony.

By contrast, rebuilding with 37a9d912b24f, test suite failed at second
test (futex_requeue_pi with locked argument). In fact, the test never
returns. Looking at the code, it seems to wait for the completion of
started threads, returning a value computed from the return value of
the individual futex_cmp_requeue_pi calls:

(in signal_wakerfn)
[...]
while (task_count < THREAD_MAX [...] ) {
     [...]
     args->ret = futex_cmp_requeue_pi([...]);
     [...]
     task_count += args->ret;
     [...]
}

So, if the meaning of the futex API has changed, perhaps some programs
(like this test) need to be updated accordingly.

Anyway, as Tony and Jonathan may remember, we recently had an issue on
ia64 about udev > 167 running bad because of missing accept4 syscall
into (Debian) kernel 2.6.38-2-mckinley. It thus wasn't easy to me to
stick with old 2.6.38 while udev was updated. Since this issue has
been fixed in Debian kernel 3.2.0-1-mckinley, I switched to this one,
that brought the futex issue we're now talking about.

Now, recompiling and running futex test suite under kernel
3.2.0-1-mckinley, I'm getting different results. Running
futex_requeue_pi without any parameter gives:

ERROR: No such process: FUTEX_CMP_REQUEUE_PI failed

For memories, this test passed successfully with 2.6.38-rc8+, with AND
without 37a9d912b24f included.

Now, adding locked argument, I'm getting:

ERROR: Function not implemented: FUTEX_REQUEUE_PI failed

Huh? Both these tests nevertheless gracefully return with kernel 3.2,
while the second test enters in an unfinite loop with buggy
2.6.38-rc8+.

Here's where I am for now: I still didn't found a simple futex user
code sample for Tony (or others) to play with.

Any help and guidance greatly appreciated ;-)

     Emeric


[1] https://bugzilla.kernel.org/show_bug.cgi?id=42757

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [regression] Re: [PATCH 2/3] futex: Sanitize cmpxchg_futex_value_locked API
@ 2012-03-08 20:59                   ` Émeric Maschino
  0 siblings, 0 replies; 42+ messages in thread
From: Émeric Maschino @ 2012-03-08 20:59 UTC (permalink / raw)
  To: Jonathan Nieder
  Cc: Luck, Tony, linux-ia64, Michel Lespinasse, Patrick Baggett,
	Jakub Jelinek, linux-kernel

Hello,

Warning, long answer...

Le 6 mars 2012 00:42, Jonathan Nieder <jrnieder@gmail.com> a écrit :
> Émeric, was the bisection result reproducible?  E.g., if you try
> building 37a9d912b24f and 37a9d912b24f^ again, does the former
> consistently produce and the latter consistently not produce a crashy
> system?

Yes, definitely.

Building 37a9d912b24f leads to a broken kernel-2.6.38-rc8+ with the
symptoms described in [1]. Simply reverting 37a9d912b24f produces a
100% working kernel (well, w.r.t. the symptoms described in [1] of
course).

We exchanged a couple PMs with Tony on this subject. He first asked me
to check whether the issue is really because of the change in the ia64
bits of futex_atomic_cmpxchg_inatomic or not:

(Tony Luck, by PM, wrote to Emeric Maschino)

Could you try a half-revert of the kernel change.  Take the original
code for futex_atomic_cmpxchg_inatomic() but name it
ORIG_futex_atomic_cmpxchg_inatomic() then write the new as a wrapper
around the old one - something like:

futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, u32
oldval, u32 newval)
{
        int ret;

        ret = ORIG_futex_atomic_cmpxchg_inatomic(uaddr, oldval, newval);
        *uval = oldval;
        return (ret != oldval) ? ret : 0; /* ret<0 ?? ... this can't
cover all cases, but should be able to do something good enough */
}

If this makes the problem go away - we can start staring at the asm
bits some more to see just what is wrong with this new version of the
function.


I thus followed Tony's recommendation. Below is the result:

(Emeric Maschino, by PM, wrote to Tony Luck)

Well, partly. (about Tony's last remark: "If this makes the problem go away")

With a wrapper around the original API like you suggested above:
- the terminal window no more crashes when you hit the Tab key
- Iceweasel/Firefox no more triggers a X restart when clicking on a
menu or a button
- gdb no more exits early with a SIGTRAP signal.
That's for the good news.

The bad news: with the wrapper around the original API, I nevertheless
experience new side-effects:
- GDM3 no more displays user list, nor buttons, so you can't enter a X
session from there. I had to shut GDM3 down and manually enter a X
session with startx
- ioquake3-based Quake3 demo freezes while initializing sound.
As you already did noticed, perhaps are we hitting ret < 0 values there.

Is there something else I can try to help debugging further?


Tony then asked me to provide him with a reduced test case he could play with:

(Tony Luck, by PM, wrote to Emeric Maschino)

OK - so we do have a problem in the new implementation of this
function (otherwise this change shouldn't have had much effect).

I'd like a simple user mode test case that uses futexes to some
trivial thing. Doesn't matter whether it shows a problem, I can tweak
the test to try running into whatever corner case is causing the
problem.


And this is where I'm actually stuck.

Tony also pointed to me a futex test suite:

(Tony Luck, by PM, wrote to Emeric Maschino)

I found a futex test suite:

        git:://git.kernel.org/pub/scm/linux/kernel/git/dvhart/futextest.git

but it runs equally badly on kernel pre/post this change (I compared
v2.6.36 as the pre version, and current linus tree as the post).

Bah! an x86 system fails in the same way (pthread_create calls fail
for many tests - meaning they get skipped).


I don't know exactly how Tony run the test suite. On my side,
kernel-2.6.38-rc8+ (minus 37a9d912b24f) passed successfully. But it
had to be run as root, otherwise you'll get pthread_create errors as
experienced by Tony.

By contrast, rebuilding with 37a9d912b24f, test suite failed at second
test (futex_requeue_pi with locked argument). In fact, the test never
returns. Looking at the code, it seems to wait for the completion of
started threads, returning a value computed from the return value of
the individual futex_cmp_requeue_pi calls:

(in signal_wakerfn)
[...]
while (task_count < THREAD_MAX [...] ) {
     [...]
     args->ret = futex_cmp_requeue_pi([...]);
     [...]
     task_count += args->ret;
     [...]
}

So, if the meaning of the futex API has changed, perhaps some programs
(like this test) need to be updated accordingly.

Anyway, as Tony and Jonathan may remember, we recently had an issue on
ia64 about udev > 167 running bad because of missing accept4 syscall
into (Debian) kernel 2.6.38-2-mckinley. It thus wasn't easy to me to
stick with old 2.6.38 while udev was updated. Since this issue has
been fixed in Debian kernel 3.2.0-1-mckinley, I switched to this one,
that brought the futex issue we're now talking about.

Now, recompiling and running futex test suite under kernel
3.2.0-1-mckinley, I'm getting different results. Running
futex_requeue_pi without any parameter gives:

ERROR: No such process: FUTEX_CMP_REQUEUE_PI failed

For memories, this test passed successfully with 2.6.38-rc8+, with AND
without 37a9d912b24f included.

Now, adding locked argument, I'm getting:

ERROR: Function not implemented: FUTEX_REQUEUE_PI failed

Huh? Both these tests nevertheless gracefully return with kernel 3.2,
while the second test enters in an unfinite loop with buggy
2.6.38-rc8+.

Here's where I am for now: I still didn't found a simple futex user
code sample for Tony (or others) to play with.

Any help and guidance greatly appreciated ;-)

     Emeric


[1] https://bugzilla.kernel.org/show_bug.cgi?idB757

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [regression] Re: [PATCH 2/3] futex: Sanitize cmpxchg_futex_value_locked API
  2012-03-08 20:59                   ` Émeric Maschino
@ 2012-03-08 21:12                     ` Émeric Maschino
  -1 siblings, 0 replies; 42+ messages in thread
From: Émeric Maschino @ 2012-03-08 21:12 UTC (permalink / raw)
  To: Jonathan Nieder
  Cc: Luck, Tony, linux-ia64, Michel Lespinasse, Patrick Baggett,
	Jakub Jelinek, linux-kernel

Oops, just to correct myself: the tests described below DON'T return
gracefully with kernel 3.2. Sorry for the mistake.

     Emeric


Le 8 mars 2012 21:59, Émeric Maschino <emeric.maschino@gmail.com> a écrit :
> ERROR: No such process: FUTEX_CMP_REQUEUE_PI failed
>
> For memories, this test passed successfully with 2.6.38-rc8+, with AND
> without 37a9d912b24f included.
>
> Now, adding locked argument, I'm getting:
>
> ERROR: Function not implemented: FUTEX_REQUEUE_PI failed
>
> Huh? Both these tests nevertheless gracefully return with kernel 3.2,
> while the second test enters in an unfinite loop with buggy
> 2.6.38-rc8+.

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [regression] Re: [PATCH 2/3] futex: Sanitize cmpxchg_futex_value_locked API
@ 2012-03-08 21:12                     ` Émeric Maschino
  0 siblings, 0 replies; 42+ messages in thread
From: Émeric Maschino @ 2012-03-08 21:12 UTC (permalink / raw)
  To: Jonathan Nieder
  Cc: Luck, Tony, linux-ia64, Michel Lespinasse, Patrick Baggett,
	Jakub Jelinek, linux-kernel

Oops, just to correct myself: the tests described below DON'T return
gracefully with kernel 3.2. Sorry for the mistake.

     Emeric


Le 8 mars 2012 21:59, Émeric Maschino <emeric.maschino@gmail.com> a écrit :
> ERROR: No such process: FUTEX_CMP_REQUEUE_PI failed
>
> For memories, this test passed successfully with 2.6.38-rc8+, with AND
> without 37a9d912b24f included.
>
> Now, adding locked argument, I'm getting:
>
> ERROR: Function not implemented: FUTEX_REQUEUE_PI failed
>
> Huh? Both these tests nevertheless gracefully return with kernel 3.2,
> while the second test enters in an unfinite loop with buggy
> 2.6.38-rc8+.

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [regression] Re: [PATCH 2/3] futex: Sanitize cmpxchg_futex_value_locked API
  2012-03-08 21:12                     ` Émeric Maschino
@ 2012-04-15 21:35                       ` Émeric Maschino
  -1 siblings, 0 replies; 42+ messages in thread
From: Émeric Maschino @ 2012-04-15 21:35 UTC (permalink / raw)
  To: Jonathan Nieder
  Cc: Luck, Tony, linux-ia64, Michel Lespinasse, Patrick Baggett,
	Jakub Jelinek, linux-kernel

Hi,

Patch proposed by Tony in
https://bugzilla.kernel.org/show_bug.cgi?id=42757 works for me :-)

Many thanks,

    Emeric



Le 8 mars 2012 22:12, Émeric Maschino <emeric.maschino@gmail.com> a écrit :
> Oops, just to correct myself: the tests described below DON'T return
> gracefully with kernel 3.2. Sorry for the mistake.
>
>     Emeric
>
>
> Le 8 mars 2012 21:59, Émeric Maschino <emeric.maschino@gmail.com> a écrit :
>> ERROR: No such process: FUTEX_CMP_REQUEUE_PI failed
>>
>> For memories, this test passed successfully with 2.6.38-rc8+, with AND
>> without 37a9d912b24f included.
>>
>> Now, adding locked argument, I'm getting:
>>
>> ERROR: Function not implemented: FUTEX_REQUEUE_PI failed
>>
>> Huh? Both these tests nevertheless gracefully return with kernel 3.2,
>> while the second test enters in an unfinite loop with buggy
>> 2.6.38-rc8+.

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [regression] Re: [PATCH 2/3] futex: Sanitize cmpxchg_futex_value_locked API
@ 2012-04-15 21:35                       ` Émeric Maschino
  0 siblings, 0 replies; 42+ messages in thread
From: Émeric Maschino @ 2012-04-15 21:35 UTC (permalink / raw)
  To: Jonathan Nieder
  Cc: Luck, Tony, linux-ia64, Michel Lespinasse, Patrick Baggett,
	Jakub Jelinek, linux-kernel

Hi,

Patch proposed by Tony in
https://bugzilla.kernel.org/show_bug.cgi?idB757 works for me :-)

Many thanks,

    Emeric



Le 8 mars 2012 22:12, Émeric Maschino <emeric.maschino@gmail.com> a écrit :
> Oops, just to correct myself: the tests described below DON'T return
> gracefully with kernel 3.2. Sorry for the mistake.
>
>     Emeric
>
>
> Le 8 mars 2012 21:59, Émeric Maschino <emeric.maschino@gmail.com> a écrit :
>> ERROR: No such process: FUTEX_CMP_REQUEUE_PI failed
>>
>> For memories, this test passed successfully with 2.6.38-rc8+, with AND
>> without 37a9d912b24f included.
>>
>> Now, adding locked argument, I'm getting:
>>
>> ERROR: Function not implemented: FUTEX_REQUEUE_PI failed
>>
>> Huh? Both these tests nevertheless gracefully return with kernel 3.2,
>> while the second test enters in an unfinite loop with buggy
>> 2.6.38-rc8+.

^ permalink raw reply	[flat|nested] 42+ messages in thread

end of thread, other threads:[~2012-04-15 21:35 UTC | newest]

Thread overview: 42+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-03-07  2:11 [PATCH] futex: cmpxchg_futex_value_locked API change Michel Lespinasse
2011-03-07  8:54 ` Martin Schwidefsky
2011-03-07 14:25 ` Chris Metcalf
2011-03-07 21:58 ` Luck, Tony
2011-03-08 20:17 ` Thomas Gleixner
2011-03-09 11:25   ` Michel Lespinasse
2011-03-09 15:04     ` Thomas Gleixner
2011-03-09 15:08     ` Martin Schwidefsky
2011-03-09 22:17       ` Michel Lespinasse
2011-03-09 17:50     ` Darren Hart
2011-03-10 18:55     ` Thomas Gleixner
2011-03-11  2:16       ` Michel Lespinasse
2011-03-11  2:47         ` [PATCH 1/3] futex: do not pagefault_disable in futex_atomic_cmpxchg_inatomic() Michel Lespinasse
2011-03-11 11:31           ` [tip:core/futexes] futex: Remove redundant " tip-bot for Michel Lespinasse
2011-03-13 22:49           ` [PATCH 1/3] futex: do not " Linus Torvalds
2011-03-14  0:55             ` Darren Hart
2011-03-14  1:15               ` Darren Hart
2011-03-14  9:13               ` Peter Zijlstra
2011-03-14  9:13             ` Thomas Gleixner
2011-03-14 13:56               ` Thomas Gleixner
2011-03-14 20:07                 ` Darren Hart
2011-03-14 20:15                 ` [tip:core/futexes] futex: Deobfuscate handle_futex_death() tip-bot for Thomas Gleixner
2011-03-14 20:16                 ` [tip:core/futexes] arm: Remove bogus comment in futex_atomic_cmpxchg_inatomic() tip-bot for Thomas Gleixner
2011-03-14  9:15             ` [PATCH 1/3] futex: do not pagefault_disable " Michel Lespinasse
2011-03-11  2:48         ` [PATCH 2/3] futex: cmpxchg_futex_value_locked API change Michel Lespinasse
2011-03-11 11:31           ` [tip:core/futexes] futex: Sanitize cmpxchg_futex_value_locked API tip-bot for Michel Lespinasse
2012-03-05  0:01           ` [regression] Re: [PATCH 2/3] " Jonathan Nieder
2012-03-05  0:01             ` Jonathan Nieder
2012-03-05 23:21             ` Luck, Tony
2012-03-05 23:21               ` Luck, Tony
2012-03-05 23:42               ` Jonathan Nieder
2012-03-05 23:42                 ` Jonathan Nieder
2012-03-08 20:59                 ` Émeric Maschino
2012-03-08 20:59                   ` Émeric Maschino
2012-03-08 21:12                   ` Émeric Maschino
2012-03-08 21:12                     ` Émeric Maschino
2012-04-15 21:35                     ` Émeric Maschino
2012-04-15 21:35                       ` Émeric Maschino
2011-03-11  2:50         ` [PATCH 3/3] futex: fix futex operation types Michel Lespinasse
2011-03-11 11:32           ` [tip:core/futexes] futex: Sanitize futex ops argument types tip-bot for Michel Lespinasse
2011-03-09 11:08 ` [PATCH] futex: cmpxchg_futex_value_locked API change Michal Simek
2011-03-09 12:41 ` David Howells

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.