xref: /openbmc/linux/tools/include/asm-generic/atomic-gcc.h (revision 7ae9fb1b7ecbb5d85d07857943f677fd1a559b18)
1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
2da6d8567SArnaldo Carvalho de Melo #ifndef __TOOLS_ASM_GENERIC_ATOMIC_H
3da6d8567SArnaldo Carvalho de Melo #define __TOOLS_ASM_GENERIC_ATOMIC_H
4da6d8567SArnaldo Carvalho de Melo 
5da6d8567SArnaldo Carvalho de Melo #include <linux/compiler.h>
6da6d8567SArnaldo Carvalho de Melo #include <linux/types.h>
7cf4694beSPeter Gonda #include <linux/bitops.h>
8da6d8567SArnaldo Carvalho de Melo 
9da6d8567SArnaldo Carvalho de Melo /*
10da6d8567SArnaldo Carvalho de Melo  * Atomic operations that C can't guarantee us.  Useful for
11da6d8567SArnaldo Carvalho de Melo  * resource counting etc..
12da6d8567SArnaldo Carvalho de Melo  *
13da6d8567SArnaldo Carvalho de Melo  * Excerpts obtained from the Linux kernel sources.
14da6d8567SArnaldo Carvalho de Melo  */
15da6d8567SArnaldo Carvalho de Melo 
16da6d8567SArnaldo Carvalho de Melo #define ATOMIC_INIT(i)	{ (i) }
17da6d8567SArnaldo Carvalho de Melo 
18da6d8567SArnaldo Carvalho de Melo /**
19da6d8567SArnaldo Carvalho de Melo  * atomic_read - read atomic variable
20da6d8567SArnaldo Carvalho de Melo  * @v: pointer of type atomic_t
21da6d8567SArnaldo Carvalho de Melo  *
22da6d8567SArnaldo Carvalho de Melo  * Atomically reads the value of @v.
23da6d8567SArnaldo Carvalho de Melo  */
atomic_read(const atomic_t * v)24da6d8567SArnaldo Carvalho de Melo static inline int atomic_read(const atomic_t *v)
25da6d8567SArnaldo Carvalho de Melo {
266aa7de05SMark Rutland 	return READ_ONCE((v)->counter);
27da6d8567SArnaldo Carvalho de Melo }
28da6d8567SArnaldo Carvalho de Melo 
29da6d8567SArnaldo Carvalho de Melo /**
30da6d8567SArnaldo Carvalho de Melo  * atomic_set - set atomic variable
31da6d8567SArnaldo Carvalho de Melo  * @v: pointer of type atomic_t
32da6d8567SArnaldo Carvalho de Melo  * @i: required value
33da6d8567SArnaldo Carvalho de Melo  *
34da6d8567SArnaldo Carvalho de Melo  * Atomically sets the value of @v to @i.
35da6d8567SArnaldo Carvalho de Melo  */
atomic_set(atomic_t * v,int i)36da6d8567SArnaldo Carvalho de Melo static inline void atomic_set(atomic_t *v, int i)
37da6d8567SArnaldo Carvalho de Melo {
38da6d8567SArnaldo Carvalho de Melo         v->counter = i;
39da6d8567SArnaldo Carvalho de Melo }
40da6d8567SArnaldo Carvalho de Melo 
41da6d8567SArnaldo Carvalho de Melo /**
42da6d8567SArnaldo Carvalho de Melo  * atomic_inc - increment atomic variable
43da6d8567SArnaldo Carvalho de Melo  * @v: pointer of type atomic_t
44da6d8567SArnaldo Carvalho de Melo  *
45da6d8567SArnaldo Carvalho de Melo  * Atomically increments @v by 1.
46da6d8567SArnaldo Carvalho de Melo  */
atomic_inc(atomic_t * v)47da6d8567SArnaldo Carvalho de Melo static inline void atomic_inc(atomic_t *v)
48da6d8567SArnaldo Carvalho de Melo {
49da6d8567SArnaldo Carvalho de Melo 	__sync_add_and_fetch(&v->counter, 1);
50da6d8567SArnaldo Carvalho de Melo }
51da6d8567SArnaldo Carvalho de Melo 
52da6d8567SArnaldo Carvalho de Melo /**
53da6d8567SArnaldo Carvalho de Melo  * atomic_dec_and_test - decrement and test
54da6d8567SArnaldo Carvalho de Melo  * @v: pointer of type atomic_t
55da6d8567SArnaldo Carvalho de Melo  *
56da6d8567SArnaldo Carvalho de Melo  * Atomically decrements @v by 1 and
57da6d8567SArnaldo Carvalho de Melo  * returns true if the result is 0, or false for all other
58da6d8567SArnaldo Carvalho de Melo  * cases.
59da6d8567SArnaldo Carvalho de Melo  */
atomic_dec_and_test(atomic_t * v)60da6d8567SArnaldo Carvalho de Melo static inline int atomic_dec_and_test(atomic_t *v)
61da6d8567SArnaldo Carvalho de Melo {
62da6d8567SArnaldo Carvalho de Melo 	return __sync_sub_and_fetch(&v->counter, 1) == 0;
63da6d8567SArnaldo Carvalho de Melo }
64da6d8567SArnaldo Carvalho de Melo 
65ed4aad50SArnaldo Carvalho de Melo #define cmpxchg(ptr, oldval, newval) \
66ed4aad50SArnaldo Carvalho de Melo 	__sync_val_compare_and_swap(ptr, oldval, newval)
67ed4aad50SArnaldo Carvalho de Melo 
atomic_cmpxchg(atomic_t * v,int oldval,int newval)68ed4aad50SArnaldo Carvalho de Melo static inline int atomic_cmpxchg(atomic_t *v, int oldval, int newval)
69ed4aad50SArnaldo Carvalho de Melo {
70ed4aad50SArnaldo Carvalho de Melo 	return cmpxchg(&(v)->counter, oldval, newval);
71ed4aad50SArnaldo Carvalho de Melo }
72ed4aad50SArnaldo Carvalho de Melo 
test_and_set_bit(long nr,unsigned long * addr)7336293352SSean Christopherson static inline int test_and_set_bit(long nr, unsigned long *addr)
74cf4694beSPeter Gonda {
75cf4694beSPeter Gonda 	unsigned long mask = BIT_MASK(nr);
76cf4694beSPeter Gonda 	long old;
77cf4694beSPeter Gonda 
78cf4694beSPeter Gonda 	addr += BIT_WORD(nr);
79cf4694beSPeter Gonda 
80cf4694beSPeter Gonda 	old = __sync_fetch_and_or(addr, mask);
81cf4694beSPeter Gonda 	return !!(old & mask);
82cf4694beSPeter Gonda }
83cf4694beSPeter Gonda 
test_and_clear_bit(long nr,unsigned long * addr)84*bb056c0fSSean Christopherson static inline int test_and_clear_bit(long nr, unsigned long *addr)
85*bb056c0fSSean Christopherson {
86*bb056c0fSSean Christopherson 	unsigned long mask = BIT_MASK(nr);
87*bb056c0fSSean Christopherson 	long old;
88*bb056c0fSSean Christopherson 
89*bb056c0fSSean Christopherson 	addr += BIT_WORD(nr);
90*bb056c0fSSean Christopherson 
91*bb056c0fSSean Christopherson 	old = __sync_fetch_and_and(addr, ~mask);
92*bb056c0fSSean Christopherson 	return !!(old & mask);
93*bb056c0fSSean Christopherson }
94*bb056c0fSSean Christopherson 
95da6d8567SArnaldo Carvalho de Melo #endif /* __TOOLS_ASM_GENERIC_ATOMIC_H */
96