1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
2da6d8567SArnaldo Carvalho de Melo #ifndef _TOOLS_LINUX_ASM_X86_ATOMIC_H
3da6d8567SArnaldo Carvalho de Melo #define _TOOLS_LINUX_ASM_X86_ATOMIC_H
4da6d8567SArnaldo Carvalho de Melo
5da6d8567SArnaldo Carvalho de Melo #include <linux/compiler.h>
6da6d8567SArnaldo Carvalho de Melo #include <linux/types.h>
7da6d8567SArnaldo Carvalho de Melo #include "rmwcc.h"
8da6d8567SArnaldo Carvalho de Melo
9da6d8567SArnaldo Carvalho de Melo #define LOCK_PREFIX "\n\tlock; "
10da6d8567SArnaldo Carvalho de Melo
11cf4694beSPeter Gonda #include <asm/asm.h>
128a73615dSArnaldo Carvalho de Melo #include <asm/cmpxchg.h>
138a73615dSArnaldo Carvalho de Melo
14da6d8567SArnaldo Carvalho de Melo /*
15da6d8567SArnaldo Carvalho de Melo * Atomic operations that C can't guarantee us. Useful for
16da6d8567SArnaldo Carvalho de Melo * resource counting etc..
17da6d8567SArnaldo Carvalho de Melo */
18da6d8567SArnaldo Carvalho de Melo
19da6d8567SArnaldo Carvalho de Melo #define ATOMIC_INIT(i) { (i) }
20da6d8567SArnaldo Carvalho de Melo
21da6d8567SArnaldo Carvalho de Melo /**
22da6d8567SArnaldo Carvalho de Melo * atomic_read - read atomic variable
23da6d8567SArnaldo Carvalho de Melo * @v: pointer of type atomic_t
24da6d8567SArnaldo Carvalho de Melo *
25da6d8567SArnaldo Carvalho de Melo * Atomically reads the value of @v.
26da6d8567SArnaldo Carvalho de Melo */
atomic_read(const atomic_t * v)27da6d8567SArnaldo Carvalho de Melo static inline int atomic_read(const atomic_t *v)
28da6d8567SArnaldo Carvalho de Melo {
296aa7de05SMark Rutland return READ_ONCE((v)->counter);
30da6d8567SArnaldo Carvalho de Melo }
31da6d8567SArnaldo Carvalho de Melo
32da6d8567SArnaldo Carvalho de Melo /**
33da6d8567SArnaldo Carvalho de Melo * atomic_set - set atomic variable
34da6d8567SArnaldo Carvalho de Melo * @v: pointer of type atomic_t
35da6d8567SArnaldo Carvalho de Melo * @i: required value
36da6d8567SArnaldo Carvalho de Melo *
37da6d8567SArnaldo Carvalho de Melo * Atomically sets the value of @v to @i.
38da6d8567SArnaldo Carvalho de Melo */
atomic_set(atomic_t * v,int i)39da6d8567SArnaldo Carvalho de Melo static inline void atomic_set(atomic_t *v, int i)
40da6d8567SArnaldo Carvalho de Melo {
41da6d8567SArnaldo Carvalho de Melo v->counter = i;
42da6d8567SArnaldo Carvalho de Melo }
43da6d8567SArnaldo Carvalho de Melo
44da6d8567SArnaldo Carvalho de Melo /**
45da6d8567SArnaldo Carvalho de Melo * atomic_inc - increment atomic variable
46da6d8567SArnaldo Carvalho de Melo * @v: pointer of type atomic_t
47da6d8567SArnaldo Carvalho de Melo *
48da6d8567SArnaldo Carvalho de Melo * Atomically increments @v by 1.
49da6d8567SArnaldo Carvalho de Melo */
atomic_inc(atomic_t * v)50da6d8567SArnaldo Carvalho de Melo static inline void atomic_inc(atomic_t *v)
51da6d8567SArnaldo Carvalho de Melo {
52da6d8567SArnaldo Carvalho de Melo asm volatile(LOCK_PREFIX "incl %0"
53da6d8567SArnaldo Carvalho de Melo : "+m" (v->counter));
54da6d8567SArnaldo Carvalho de Melo }
55da6d8567SArnaldo Carvalho de Melo
56da6d8567SArnaldo Carvalho de Melo /**
57da6d8567SArnaldo Carvalho de Melo * atomic_dec_and_test - decrement and test
58da6d8567SArnaldo Carvalho de Melo * @v: pointer of type atomic_t
59da6d8567SArnaldo Carvalho de Melo *
60da6d8567SArnaldo Carvalho de Melo * Atomically decrements @v by 1 and
61da6d8567SArnaldo Carvalho de Melo * returns true if the result is 0, or false for all other
62da6d8567SArnaldo Carvalho de Melo * cases.
63da6d8567SArnaldo Carvalho de Melo */
atomic_dec_and_test(atomic_t * v)64da6d8567SArnaldo Carvalho de Melo static inline int atomic_dec_and_test(atomic_t *v)
65da6d8567SArnaldo Carvalho de Melo {
66da6d8567SArnaldo Carvalho de Melo GEN_UNARY_RMWcc(LOCK_PREFIX "decl", v->counter, "%0", "e");
67da6d8567SArnaldo Carvalho de Melo }
68da6d8567SArnaldo Carvalho de Melo
atomic_cmpxchg(atomic_t * v,int old,int new)698a73615dSArnaldo Carvalho de Melo static __always_inline int atomic_cmpxchg(atomic_t *v, int old, int new)
708a73615dSArnaldo Carvalho de Melo {
718a73615dSArnaldo Carvalho de Melo return cmpxchg(&v->counter, old, new);
728a73615dSArnaldo Carvalho de Melo }
738a73615dSArnaldo Carvalho de Melo
test_and_set_bit(long nr,unsigned long * addr)7436293352SSean Christopherson static inline int test_and_set_bit(long nr, unsigned long *addr)
75cf4694beSPeter Gonda {
76cf4694beSPeter Gonda GEN_BINARY_RMWcc(LOCK_PREFIX __ASM_SIZE(bts), *addr, "Ir", nr, "%0", "c");
77cf4694beSPeter Gonda }
78cf4694beSPeter Gonda
test_and_clear_bit(long nr,unsigned long * addr)79*bb056c0fSSean Christopherson static inline int test_and_clear_bit(long nr, unsigned long *addr)
80*bb056c0fSSean Christopherson {
81*bb056c0fSSean Christopherson GEN_BINARY_RMWcc(LOCK_PREFIX __ASM_SIZE(btc), *addr, "Ir", nr, "%0", "c");
82*bb056c0fSSean Christopherson }
83*bb056c0fSSean Christopherson
84da6d8567SArnaldo Carvalho de Melo #endif /* _TOOLS_LINUX_ASM_X86_ATOMIC_H */
85