Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 #ifndef TOOLS_ASM_X86_CMPXCHG_H
0003 #define TOOLS_ASM_X86_CMPXCHG_H
0004 
0005 #include <linux/compiler.h>
0006 
0007 /*
0008  * Non-existant functions to indicate usage errors at link time
0009  * (or compile-time if the compiler implements __compiletime_error().
0010  */
0011 extern void __cmpxchg_wrong_size(void)
0012     __compiletime_error("Bad argument size for cmpxchg");
0013 
0014 /*
0015  * Constants for operation sizes. On 32-bit, the 64-bit size it set to
0016  * -1 because sizeof will never return -1, thereby making those switch
0017  * case statements guaranteeed dead code which the compiler will
0018  * eliminate, and allowing the "missing symbol in the default case" to
0019  * indicate a usage error.
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      /* sizeof will never return -1 */
0028 #endif
0029 
0030 /*
0031  * Atomic compare and exchange.  Compare OLD with MEM, if identical,
0032  * store NEW in MEM.  Return the initial value in MEM.  Success is
0033  * indicated by comparing RETURN with OLD.
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  /* TOOLS_ASM_X86_CMPXCHG_H */