Will be included from atomic.h and used in refcount.h Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: David Ahern <dsahern@gmail.com> Cc: Elena Reshetova <elena.reshetova@intel.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Wang Nan <wangnan0@huawei.com> Link: http://lkml.kernel.org/n/tip-pzrydfee75mhq64kazxmf9it@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>tirimbino
parent
4900653829
commit
3337e682d9
@ -0,0 +1,89 @@ |
||||
#ifndef TOOLS_ASM_X86_CMPXCHG_H |
||||
#define TOOLS_ASM_X86_CMPXCHG_H |
||||
|
||||
#include <linux/compiler.h> |
||||
|
||||
/*
|
||||
* Non-existant functions to indicate usage errors at link time |
||||
* (or compile-time if the compiler implements __compiletime_error(). |
||||
*/ |
||||
extern void __cmpxchg_wrong_size(void) |
||||
__compiletime_error("Bad argument size for cmpxchg"); |
||||
|
||||
/*
|
||||
* Constants for operation sizes. On 32-bit, the 64-bit size it set to |
||||
* -1 because sizeof will never return -1, thereby making those switch |
||||
* case statements guaranteeed dead code which the compiler will |
||||
* eliminate, and allowing the "missing symbol in the default case" to |
||||
* indicate a usage error. |
||||
*/ |
||||
#define __X86_CASE_B 1 |
||||
#define __X86_CASE_W 2 |
||||
#define __X86_CASE_L 4 |
||||
#ifdef __x86_64__ |
||||
#define __X86_CASE_Q 8 |
||||
#else |
||||
#define __X86_CASE_Q -1 /* sizeof will never return -1 */ |
||||
#endif |
||||
|
||||
/*
|
||||
* Atomic compare and exchange. Compare OLD with MEM, if identical, |
||||
* store NEW in MEM. Return the initial value in MEM. Success is |
||||
* indicated by comparing RETURN with OLD. |
||||
*/ |
||||
#define __raw_cmpxchg(ptr, old, new, size, lock) \ |
||||
({ \
|
||||
__typeof__(*(ptr)) __ret; \
|
||||
__typeof__(*(ptr)) __old = (old); \
|
||||
__typeof__(*(ptr)) __new = (new); \
|
||||
switch (size) { \
|
||||
case __X86_CASE_B: \
|
||||
{ \
|
||||
volatile u8 *__ptr = (volatile u8 *)(ptr); \
|
||||
asm volatile(lock "cmpxchgb %2,%1" \
|
||||
: "=a" (__ret), "+m" (*__ptr) \
|
||||
: "q" (__new), "0" (__old) \
|
||||
: "memory"); \
|
||||
break; \
|
||||
} \
|
||||
case __X86_CASE_W: \
|
||||
{ \
|
||||
volatile u16 *__ptr = (volatile u16 *)(ptr); \
|
||||
asm volatile(lock "cmpxchgw %2,%1" \
|
||||
: "=a" (__ret), "+m" (*__ptr) \
|
||||
: "r" (__new), "0" (__old) \
|
||||
: "memory"); \
|
||||
break; \
|
||||
} \
|
||||
case __X86_CASE_L: \
|
||||
{ \
|
||||
volatile u32 *__ptr = (volatile u32 *)(ptr); \
|
||||
asm volatile(lock "cmpxchgl %2,%1" \
|
||||
: "=a" (__ret), "+m" (*__ptr) \
|
||||
: "r" (__new), "0" (__old) \
|
||||
: "memory"); \
|
||||
break; \
|
||||
} \
|
||||
case __X86_CASE_Q: \
|
||||
{ \
|
||||
volatile u64 *__ptr = (volatile u64 *)(ptr); \
|
||||
asm volatile(lock "cmpxchgq %2,%1" \
|
||||
: "=a" (__ret), "+m" (*__ptr) \
|
||||
: "r" (__new), "0" (__old) \
|
||||
: "memory"); \
|
||||
break; \
|
||||
} \
|
||||
default: \
|
||||
__cmpxchg_wrong_size(); \
|
||||
} \
|
||||
__ret; \
|
||||
}) |
||||
|
||||
#define __cmpxchg(ptr, old, new, size) \ |
||||
__raw_cmpxchg((ptr), (old), (new), (size), LOCK_PREFIX) |
||||
|
||||
#define cmpxchg(ptr, old, new) \ |
||||
__cmpxchg(ptr, old, new, sizeof(*(ptr))) |
||||
|
||||
|
||||
#endif /* TOOLS_ASM_X86_CMPXCHG_H */ |
Loading…
Reference in new issue