1/* 2 * Generic UP xchg and cmpxchg using interrupt disablement. Does not 3 * support SMP. 4 */ 5 6#ifndef __ASM_GENERIC_CMPXCHG_H 7#define __ASM_GENERIC_CMPXCHG_H 8 9#ifdef CONFIG_SMP 10#error "Cannot use generic cmpxchg on SMP" 11#endif 12 13#include <linux/types.h> 14#include <linux/irqflags.h> 15 16#ifndef xchg 17 18/* 19 * This function doesn't exist, so you'll get a linker error if 20 * something tries to do an invalidly-sized xchg(). 21 */ 22extern void __xchg_called_with_bad_pointer(void); 23 24static inline 25unsigned long __xchg(unsigned long x, volatile void *ptr, int size) 26{ 27 unsigned long ret, flags; 28 29 switch (size) { 30 case 1: 31#ifdef __xchg_u8 32 return __xchg_u8(x, ptr); 33#else 34 local_irq_save(flags); 35 ret = *(volatile u8 *)ptr; 36 *(volatile u8 *)ptr = x; 37 local_irq_restore(flags); 38 return ret; 39#endif /* __xchg_u8 */ 40 41 case 2: 42#ifdef __xchg_u16 43 return __xchg_u16(x, ptr); 44#else 45 local_irq_save(flags); 46 ret = *(volatile u16 *)ptr; 47 *(volatile u16 *)ptr = x; 48 local_irq_restore(flags); 49 return ret; 50#endif /* __xchg_u16 */ 51 52 case 4: 53#ifdef __xchg_u32 54 return __xchg_u32(x, ptr); 55#else 56 local_irq_save(flags); 57 ret = *(volatile u32 *)ptr; 58 *(volatile u32 *)ptr = x; 59 local_irq_restore(flags); 60 return ret; 61#endif /* __xchg_u32 */ 62 63#ifdef CONFIG_64BIT 64 case 8: 65#ifdef __xchg_u64 66 return __xchg_u64(x, ptr); 67#else 68 local_irq_save(flags); 69 ret = *(volatile u64 *)ptr; 70 *(volatile u64 *)ptr = x; 71 local_irq_restore(flags); 72 return ret; 73#endif /* __xchg_u64 */ 74#endif /* CONFIG_64BIT */ 75 76 default: 77 __xchg_called_with_bad_pointer(); 78 return x; 79 } 80} 81 82#define xchg(ptr, x) ({ \ 83 ((__typeof__(*(ptr))) \ 84 __xchg((unsigned long)(x), (ptr), sizeof(*(ptr)))); \ 85}) 86 87#endif /* xchg */ 88 89/* 90 * Atomic compare and exchange. 91 */ 92#include <asm-generic/cmpxchg-local.h> 93 94#ifndef cmpxchg_local 95#define cmpxchg_local(ptr, o, n) ({ \ 96 ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\ 97 (unsigned long)(n), sizeof(*(ptr)))); \ 98}) 99#endif 100 101#ifndef cmpxchg64_local 102#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n)) 103#endif 104 105#define cmpxchg(ptr, o, n) cmpxchg_local((ptr), (o), (n)) 106#define cmpxchg64(ptr, o, n) cmpxchg64_local((ptr), (o), (n)) 107 108#endif /* __ASM_GENERIC_CMPXCHG_H */ 109