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 #elif defined(CONFIG_CPU_J2) && defined(CONFIG_SMP) 17 #include <asm/cmpxchg-cas.h> 18 #else 19 #include <asm/cmpxchg-irq.h> 20 #endif 21 22 extern void __xchg_called_with_bad_pointer(void); 23 24 #define __xchg(ptr, x, size) \ 25 ({ \ 26 unsigned long __xchg__res; \ 27 volatile void *__xchg_ptr = (ptr); \ 28 switch (size) { \ 29 case 4: \ 30 __xchg__res = xchg_u32(__xchg_ptr, x); \ 31 break; \ 32 case 2: \ 33 __xchg__res = xchg_u16(__xchg_ptr, x); \ 34 break; \ 35 case 1: \ 36 __xchg__res = xchg_u8(__xchg_ptr, x); \ 37 break; \ 38 default: \ 39 __xchg_called_with_bad_pointer(); \ 40 __xchg__res = x; \ 41 break; \ 42 } \ 43 \ 44 __xchg__res; \ 45 }) 46 47 #define xchg(ptr,x) \ 48 ((__typeof__(*(ptr)))__xchg((ptr),(unsigned long)(x), sizeof(*(ptr)))) 49 50 /* This function doesn't exist, so you'll get a linker error 51 * if something tries to do an invalid cmpxchg(). */ 52 extern void __cmpxchg_called_with_bad_pointer(void); 53 54 static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old, 55 unsigned long new, int size) 56 { 57 switch (size) { 58 case 4: 59 return __cmpxchg_u32(ptr, old, new); 60 } 61 __cmpxchg_called_with_bad_pointer(); 62 return old; 63 } 64 65 #define cmpxchg(ptr,o,n) \ 66 ({ \ 67 __typeof__(*(ptr)) _o_ = (o); \ 68 __typeof__(*(ptr)) _n_ = (n); \ 69 (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \ 70 (unsigned long)_n_, sizeof(*(ptr))); \ 71 }) 72 73 #endif /* __ASM_SH_CMPXCHG_H */ 74