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