]> git.ipfire.org Git - people/arne_f/kernel.git/blame - tools/arch/x86/include/asm/cmpxchg.h
License cleanup: add SPDX GPL-2.0 license identifier to files with no license
[people/arne_f/kernel.git] / tools / arch / x86 / include / asm / cmpxchg.h
CommitLineData
b2441318 1/* SPDX-License-Identifier: GPL-2.0 */
3337e682
ACM
2#ifndef TOOLS_ASM_X86_CMPXCHG_H
3#define TOOLS_ASM_X86_CMPXCHG_H
4
5#include <linux/compiler.h>
6
7/*
8 * Non-existant functions to indicate usage errors at link time
9 * (or compile-time if the compiler implements __compiletime_error().
10 */
11extern void __cmpxchg_wrong_size(void)
12 __compiletime_error("Bad argument size for cmpxchg");
13
14/*
15 * Constants for operation sizes. On 32-bit, the 64-bit size it set to
16 * -1 because sizeof will never return -1, thereby making those switch
17 * case statements guaranteeed dead code which the compiler will
18 * eliminate, and allowing the "missing symbol in the default case" to
19 * indicate a usage error.
20 */
21#define __X86_CASE_B 1
22#define __X86_CASE_W 2
23#define __X86_CASE_L 4
24#ifdef __x86_64__
25#define __X86_CASE_Q 8
26#else
27#define __X86_CASE_Q -1 /* sizeof will never return -1 */
28#endif
29
30/*
31 * Atomic compare and exchange. Compare OLD with MEM, if identical,
32 * store NEW in MEM. Return the initial value in MEM. Success is
33 * indicated by comparing RETURN with OLD.
34 */
35#define __raw_cmpxchg(ptr, old, new, size, lock) \
36({ \
37 __typeof__(*(ptr)) __ret; \
38 __typeof__(*(ptr)) __old = (old); \
39 __typeof__(*(ptr)) __new = (new); \
40 switch (size) { \
41 case __X86_CASE_B: \
42 { \
43 volatile u8 *__ptr = (volatile u8 *)(ptr); \
44 asm volatile(lock "cmpxchgb %2,%1" \
45 : "=a" (__ret), "+m" (*__ptr) \
46 : "q" (__new), "0" (__old) \
47 : "memory"); \
48 break; \
49 } \
50 case __X86_CASE_W: \
51 { \
52 volatile u16 *__ptr = (volatile u16 *)(ptr); \
53 asm volatile(lock "cmpxchgw %2,%1" \
54 : "=a" (__ret), "+m" (*__ptr) \
55 : "r" (__new), "0" (__old) \
56 : "memory"); \
57 break; \
58 } \
59 case __X86_CASE_L: \
60 { \
61 volatile u32 *__ptr = (volatile u32 *)(ptr); \
62 asm volatile(lock "cmpxchgl %2,%1" \
63 : "=a" (__ret), "+m" (*__ptr) \
64 : "r" (__new), "0" (__old) \
65 : "memory"); \
66 break; \
67 } \
68 case __X86_CASE_Q: \
69 { \
70 volatile u64 *__ptr = (volatile u64 *)(ptr); \
71 asm volatile(lock "cmpxchgq %2,%1" \
72 : "=a" (__ret), "+m" (*__ptr) \
73 : "r" (__new), "0" (__old) \
74 : "memory"); \
75 break; \
76 } \
77 default: \
78 __cmpxchg_wrong_size(); \
79 } \
80 __ret; \
81})
82
83#define __cmpxchg(ptr, old, new, size) \
84 __raw_cmpxchg((ptr), (old), (new), (size), LOCK_PREFIX)
85
86#define cmpxchg(ptr, old, new) \
87 __cmpxchg(ptr, old, new, sizeof(*(ptr)))
88
89
90#endif /* TOOLS_ASM_X86_CMPXCHG_H */