0001
0002 #ifndef TOOLS_ASM_X86_CMPXCHG_H
0003 #define TOOLS_ASM_X86_CMPXCHG_H
0004
0005 #include <linux/compiler.h>
0006
0007
0008
0009
0010
0011 extern void __cmpxchg_wrong_size(void)
0012 __compiletime_error("Bad argument size for cmpxchg");
0013
0014
0015
0016
0017
0018
0019
0020
0021 #define __X86_CASE_B 1
0022 #define __X86_CASE_W 2
0023 #define __X86_CASE_L 4
0024 #ifdef __x86_64__
0025 #define __X86_CASE_Q 8
0026 #else
0027 #define __X86_CASE_Q -1
0028 #endif
0029
0030
0031
0032
0033
0034
0035 #define __raw_cmpxchg(ptr, old, new, size, lock) \
0036 ({ \
0037 __typeof__(*(ptr)) __ret; \
0038 __typeof__(*(ptr)) __old = (old); \
0039 __typeof__(*(ptr)) __new = (new); \
0040 switch (size) { \
0041 case __X86_CASE_B: \
0042 { \
0043 volatile u8 *__ptr = (volatile u8 *)(ptr); \
0044 asm volatile(lock "cmpxchgb %2,%1" \
0045 : "=a" (__ret), "+m" (*__ptr) \
0046 : "q" (__new), "0" (__old) \
0047 : "memory"); \
0048 break; \
0049 } \
0050 case __X86_CASE_W: \
0051 { \
0052 volatile u16 *__ptr = (volatile u16 *)(ptr); \
0053 asm volatile(lock "cmpxchgw %2,%1" \
0054 : "=a" (__ret), "+m" (*__ptr) \
0055 : "r" (__new), "0" (__old) \
0056 : "memory"); \
0057 break; \
0058 } \
0059 case __X86_CASE_L: \
0060 { \
0061 volatile u32 *__ptr = (volatile u32 *)(ptr); \
0062 asm volatile(lock "cmpxchgl %2,%1" \
0063 : "=a" (__ret), "+m" (*__ptr) \
0064 : "r" (__new), "0" (__old) \
0065 : "memory"); \
0066 break; \
0067 } \
0068 case __X86_CASE_Q: \
0069 { \
0070 volatile u64 *__ptr = (volatile u64 *)(ptr); \
0071 asm volatile(lock "cmpxchgq %2,%1" \
0072 : "=a" (__ret), "+m" (*__ptr) \
0073 : "r" (__new), "0" (__old) \
0074 : "memory"); \
0075 break; \
0076 } \
0077 default: \
0078 __cmpxchg_wrong_size(); \
0079 } \
0080 __ret; \
0081 })
0082
0083 #define __cmpxchg(ptr, old, new, size) \
0084 __raw_cmpxchg((ptr), (old), (new), (size), LOCK_PREFIX)
0085
0086 #define cmpxchg(ptr, old, new) \
0087 __cmpxchg(ptr, old, new, sizeof(*(ptr)))
0088
0089
0090 #endif