[ARM] 4659/1: remove possibilities for spurious false negative with __kuser_cmpxchg
commitb49c0f24cf6744a3f4fd09289fe7cade349dead5
authorNicolas Pitre <nico@cam.org>
Tue, 20 Nov 2007 16:20:29 +0000 (20 17:20 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Mon, 26 Nov 2007 19:43:58 +0000 (26 19:43 +0000)
tree23d244eae940f2e36a9bc1a2e77b8f1cc53e071a
parentaeb747afb3fb1f42d9c82615a103882f7f97f291
[ARM] 4659/1: remove possibilities for spurious false negative with __kuser_cmpxchg

The ARM __kuser_cmpxchg routine is meant to implement an atomic cmpxchg
in user space.  It however can produce spurious false negative if a
processor exception occurs in the middle of the operation.  Normally
this is not a problem since cmpxchg is typically called in a loop until
it succeeds to implement an atomic increment for example.

Some use cases which don't involve a loop require that the operation be
100% reliable though.  This patch changes the implementation so to
reattempt the operation after an exception has occurred in the critical
section rather than abort it.

Here's a simple program to test the fix (don't use CONFIG_NO_HZ in your
kernel as this depends on a sufficiently high interrupt rate):

#include <stdio.h>

typedef int (__kernel_cmpxchg_t)(int oldval, int newval, int *ptr);
#define __kernel_cmpxchg (*(__kernel_cmpxchg_t *)0xffff0fc0)

int main()
{
int i, x = 0;
for (i = 0; i < 100000000; i++) {
int v = x;
if (__kernel_cmpxchg(v, v+1, &x))
printf("failed at %d: %d vs %d\n", i, v, x);
}
printf("done with %d vs %d\n", i, x);
return 0;
}

Signed-off-by: Nicolas Pitre <nico@marvell.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
arch/arm/kernel/entry-armv.S
arch/arm/kernel/traps.c