0001
0002
0003
0004
0005
0006
0007 #ifndef __ASM_GENERIC_CMPXCHG_H
0008 #define __ASM_GENERIC_CMPXCHG_H
0009
0010 #ifdef CONFIG_SMP
0011 #error "Cannot use generic cmpxchg on SMP"
0012 #endif
0013
0014 #include <linux/types.h>
0015 #include <linux/irqflags.h>
0016
0017
0018
0019
0020
0021 extern void __generic_xchg_called_with_bad_pointer(void);
0022
0023 static inline
0024 unsigned long __generic_xchg(unsigned long x, volatile void *ptr, int size)
0025 {
0026 unsigned long ret, flags;
0027
0028 switch (size) {
0029 case 1:
0030 #ifdef __xchg_u8
0031 return __xchg_u8(x, ptr);
0032 #else
0033 local_irq_save(flags);
0034 ret = *(volatile u8 *)ptr;
0035 *(volatile u8 *)ptr = x;
0036 local_irq_restore(flags);
0037 return ret;
0038 #endif
0039
0040 case 2:
0041 #ifdef __xchg_u16
0042 return __xchg_u16(x, ptr);
0043 #else
0044 local_irq_save(flags);
0045 ret = *(volatile u16 *)ptr;
0046 *(volatile u16 *)ptr = x;
0047 local_irq_restore(flags);
0048 return ret;
0049 #endif
0050
0051 case 4:
0052 #ifdef __xchg_u32
0053 return __xchg_u32(x, ptr);
0054 #else
0055 local_irq_save(flags);
0056 ret = *(volatile u32 *)ptr;
0057 *(volatile u32 *)ptr = x;
0058 local_irq_restore(flags);
0059 return ret;
0060 #endif
0061
0062 #ifdef CONFIG_64BIT
0063 case 8:
0064 #ifdef __xchg_u64
0065 return __xchg_u64(x, ptr);
0066 #else
0067 local_irq_save(flags);
0068 ret = *(volatile u64 *)ptr;
0069 *(volatile u64 *)ptr = x;
0070 local_irq_restore(flags);
0071 return ret;
0072 #endif
0073 #endif
0074
0075 default:
0076 __generic_xchg_called_with_bad_pointer();
0077 return x;
0078 }
0079 }
0080
0081 #define generic_xchg(ptr, x) ({ \
0082 ((__typeof__(*(ptr))) \
0083 __generic_xchg((unsigned long)(x), (ptr), sizeof(*(ptr)))); \
0084 })
0085
0086
0087
0088
0089 #include <asm-generic/cmpxchg-local.h>
0090
0091 #define generic_cmpxchg_local(ptr, o, n) ({ \
0092 ((__typeof__(*(ptr)))__generic_cmpxchg_local((ptr), (unsigned long)(o), \
0093 (unsigned long)(n), sizeof(*(ptr)))); \
0094 })
0095
0096 #define generic_cmpxchg64_local(ptr, o, n) \
0097 __generic_cmpxchg64_local((ptr), (o), (n))
0098
0099
0100 #ifndef arch_xchg
0101 #define arch_xchg generic_xchg
0102 #endif
0103
0104 #ifndef arch_cmpxchg_local
0105 #define arch_cmpxchg_local generic_cmpxchg_local
0106 #endif
0107
0108 #ifndef arch_cmpxchg64_local
0109 #define arch_cmpxchg64_local generic_cmpxchg64_local
0110 #endif
0111
0112 #define arch_cmpxchg arch_cmpxchg_local
0113 #define arch_cmpxchg64 arch_cmpxchg64_local
0114
0115 #endif