1 #ifndef __ASM_SH_CMPXCHG_H 2 #define __ASM_SH_CMPXCHG_H 3 4 /* 5 * Atomic operations that C can't guarantee us. Useful for 6 * resource counting etc.. 7 */ 8 9 #include <linux/compiler.h> 10 #include <linux/types.h> 11 12 #if defined(CONFIG_GUSA_RB) 13 #include <asm/cmpxchg-grb.h> 14 #elif defined(CONFIG_CPU_SH4A) 15 #include <asm/cmpxchg-llsc.h> 16 #else 17 #include <asm/cmpxchg-irq.h> 18 #endif 19 20 extern void __xchg_called_with_bad_pointer(void); 21 22 #define __xchg(ptr, x, size) \ 23 ({ \ 24 unsigned long __xchg__res; \ 25 volatile void *__xchg_ptr = (ptr); \ 26 switch (size) { \ 27 case 4: \ 28 __xchg__res = xchg_u32(__xchg_ptr, x); \ 29 break; \ 30 case 1: \ 31 __xchg__res = xchg_u8(__xchg_ptr, x); \ 32 break; \ 33 default: \ 34 __xchg_called_with_bad_pointer(); \ 35 __xchg__res = x; \ 36 break; \ 37 } \ 38 \ 39 __xchg__res; \ 40 }) 41 42 #define xchg(ptr,x) \ 43 ((__typeof__(*(ptr)))__xchg((ptr),(unsigned long)(x), sizeof(*(ptr)))) 44 45 /* This function doesn't exist, so you'll get a linker error 46 * if something tries to do an invalid cmpxchg(). */ 47 extern void __cmpxchg_called_with_bad_pointer(void); 48 49 static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old, 50 unsigned long new, int size) 51 { 52 switch (size) { 53 case 4: 54 return __cmpxchg_u32(ptr, old, new); 55 } 56 __cmpxchg_called_with_bad_pointer(); 57 return old; 58 } 59 60 #define cmpxchg(ptr,o,n) \ 61 ({ \ 62 __typeof__(*(ptr)) _o_ = (o); \ 63 __typeof__(*(ptr)) _n_ = (n); \ 64 (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \ 65 (unsigned long)_n_, sizeof(*(ptr))); \ 66 }) 67 68 #endif /* __ASM_SH_CMPXCHG_H */ 69