diff options
author | Tom Rini <trini@kernel.crashing.org> | 2006-09-26 22:28:20 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2006-09-26 22:28:20 -0400 |
commit | e4e3b5ccd77226c9c4dbb0737106b868dfc182d9 (patch) | |
tree | 8401beac23ca03f79c52094ea10139658661769d | |
parent | 0c91c1a7012911e4b0180a1c1ae258e2b706f987 (diff) |
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>
-rw-r--r-- | include/asm-sh/system.h | 40 |
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 @@ | |||
6 | * Copyright (C) 2002 Paul Mundt | 6 | * Copyright (C) 2002 Paul Mundt |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <asm/types.h> | ||
9 | 10 | ||
10 | /* | 11 | /* |
11 | * switch_to() should switch tasks to task nr n, first | 12 | * 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 | |||
260 | return x; | 261 | return x; |
261 | } | 262 | } |
262 | 263 | ||
264 | static inline unsigned long __cmpxchg_u32(volatile int * m, unsigned long old, | ||
265 | unsigned long new) | ||
266 | { | ||
267 | __u32 retval; | ||
268 | unsigned long flags; | ||
269 | |||
270 | local_irq_save(flags); | ||
271 | retval = *m; | ||
272 | if (retval == old) | ||
273 | *m = new; | ||
274 | local_irq_restore(flags); /* implies memory barrier */ | ||
275 | return retval; | ||
276 | } | ||
277 | |||
278 | /* This function doesn't exist, so you'll get a linker error | ||
279 | * if something tries to do an invalid cmpxchg(). */ | ||
280 | extern void __cmpxchg_called_with_bad_pointer(void); | ||
281 | |||
282 | #define __HAVE_ARCH_CMPXCHG 1 | ||
283 | |||
284 | static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old, | ||
285 | unsigned long new, int size) | ||
286 | { | ||
287 | switch (size) { | ||
288 | case 4: | ||
289 | return __cmpxchg_u32(ptr, old, new); | ||
290 | } | ||
291 | __cmpxchg_called_with_bad_pointer(); | ||
292 | return old; | ||
293 | } | ||
294 | |||
295 | #define cmpxchg(ptr,o,n) \ | ||
296 | ({ \ | ||
297 | __typeof__(*(ptr)) _o_ = (o); \ | ||
298 | __typeof__(*(ptr)) _n_ = (n); \ | ||
299 | (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \ | ||
300 | (unsigned long)_n_, sizeof(*(ptr))); \ | ||
301 | }) | ||
302 | |||
263 | /* XXX | 303 | /* XXX |
264 | * disable hlt during certain critical i/o operations | 304 | * disable hlt during certain critical i/o operations |
265 | */ | 305 | */ |