123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990 |
- /* SPDX-License-Identifier: GPL-2.0 */
- #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 */
|