1 #ifndef __ASM_GENERIC_CMPXCHG_LOCAL_H 2 #define __ASM_GENERIC_CMPXCHG_LOCAL_H 3 4 #include <linux/types.h> 5 6 extern unsigned long wrong_size_cmpxchg(volatile void *ptr); 7 8 /* 9 * Generic version of __cmpxchg_local (disables interrupts). Takes an unsigned 10 * long parameter, supporting various types of architectures. 11 */ 12 static inline unsigned long __cmpxchg_local_generic(volatile void *ptr, 13 unsigned long old, unsigned long new, int size) 14 { 15 unsigned long flags, prev; 16 17 /* 18 * Sanity checking, compile-time. 19 */ 20 if (size == 8 && sizeof(unsigned long) != 8) 21 wrong_size_cmpxchg(ptr); 22 23 local_irq_save(flags); 24 switch (size) { 25 case 1: prev = *(u8 *)ptr; 26 if (prev == old) 27 *(u8 *)ptr = (u8)new; 28 break; 29 case 2: prev = *(u16 *)ptr; 30 if (prev == old) 31 *(u16 *)ptr = (u16)new; 32 break; 33 case 4: prev = *(u32 *)ptr; 34 if (prev == old) 35 *(u32 *)ptr = (u32)new; 36 break; 37 case 8: prev = *(u64 *)ptr; 38 if (prev == old) 39 *(u64 *)ptr = (u64)new; 40 break; 41 default: 42 wrong_size_cmpxchg(ptr); 43 } 44 local_irq_restore(flags); 45 return prev; 46 } 47 48 /* 49 * Generic version of __cmpxchg64_local. Takes an u64 parameter. 50 */ 51 static inline u64 __cmpxchg64_local_generic(volatile void *ptr, 52 u64 old, u64 new) 53 { 54 u64 prev; 55 unsigned long flags; 56 57 local_irq_save(flags); 58 prev = *(u64 *)ptr; 59 if (prev == old) 60 *(u64 *)ptr = new; 61 local_irq_restore(flags); 62 return prev; 63 } 64 65 #endif 66