]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
sh: Add a simple cmpxchg().
authorTom Rini <trini@kernel.crashing.org>
Wed, 27 Sep 2006 02:28:20 +0000 (11:28 +0900)
committerPaul Mundt <lethal@linux-sh.org>
Wed, 27 Sep 2006 02:28:20 +0000 (11:28 +0900)
We didn't have one of these before, a simple implementation
borrowed from MIPS as well as the __HAVE_ARCH_CMPXCHG bits.

Signed-off-by: Tom Rini <trini@kernel.crashing.org>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
include/asm-sh/system.h

index ad35ad4958f44df04d7abda10e132c92d707e8bd..e89728d405d8380ac6177b18c7b54ca6bbb2bcc9 100644 (file)
@@ -6,6 +6,7 @@
  * Copyright (C) 2002 Paul Mundt
  */
 
+#include <asm/types.h>
 
 /*
  *     switch_to() should switch tasks to task nr n, first
@@ -260,6 +261,45 @@ static __inline__ unsigned long __xchg(unsigned long x, volatile void * ptr, int
        return x;
 }
 
+static inline unsigned long __cmpxchg_u32(volatile int * m, unsigned long old,
+       unsigned long new)
+{
+       __u32 retval;
+       unsigned long flags;
+
+       local_irq_save(flags);
+       retval = *m;
+       if (retval == old)
+               *m = new;
+       local_irq_restore(flags);       /* implies memory barrier  */
+       return retval;
+}
+
+/* This function doesn't exist, so you'll get a linker error
+ * if something tries to do an invalid cmpxchg(). */
+extern void __cmpxchg_called_with_bad_pointer(void);
+
+#define __HAVE_ARCH_CMPXCHG 1
+
+static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old,
+               unsigned long new, int size)
+{
+       switch (size) {
+       case 4:
+               return __cmpxchg_u32(ptr, old, new);
+       }
+       __cmpxchg_called_with_bad_pointer();
+       return old;
+}
+
+#define cmpxchg(ptr,o,n)                                                \
+  ({                                                                    \
+     __typeof__(*(ptr)) _o_ = (o);                                      \
+     __typeof__(*(ptr)) _n_ = (n);                                      \
+     (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,          \
+                                   (unsigned long)_n_, sizeof(*(ptr))); \
+  })
+
 /* XXX
  * disable hlt during certain critical i/o operations
  */