summary refs log tree commit diff
path: root/include/asm-sh/system.h
diff options
context:
space:
mode:
authorTom Rini <trini@kernel.crashing.org>2006-09-27 11:28:20 +0900
committerPaul Mundt <lethal@linux-sh.org>2006-09-27 11:28:20 +0900
commite4e3b5ccd77226c9c4dbb0737106b868dfc182d9 (patch)
tree8401beac23ca03f79c52094ea10139658661769d /include/asm-sh/system.h
parent0c91c1a7012911e4b0180a1c1ae258e2b706f987 (diff)
downloadlinux-e4e3b5ccd77226c9c4dbb0737106b868dfc182d9.tar.gz
sh: Add a simple cmpxchg().
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>
Diffstat (limited to 'include/asm-sh/system.h')
-rw-r--r--include/asm-sh/system.h40
1 files changed, 40 insertions, 0 deletions
diff --git a/include/asm-sh/system.h b/include/asm-sh/system.h
index ad35ad4958f4..e89728d405d8 100644
--- a/include/asm-sh/system.h
+++ b/include/asm-sh/system.h
@@ -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
  */