1 /* SPDX-License-Identifier: GPL-2.0 */
2 
3 /*
4  * This file provides wrappers with sanitizer instrumentation for atomic bit
5  * operations.
6  *
7  * To use this functionality, an arch's bitops.h file needs to define each of
8  * the below bit operations with an arch_ prefix (e.g. arch_set_bit(),
9  * arch___set_bit(), etc.).
10  */
11 #ifndef _ASM_GENERIC_BITOPS_INSTRUMENTED_ATOMIC_H
12 #define _ASM_GENERIC_BITOPS_INSTRUMENTED_ATOMIC_H
13 
14 #include <linux/instrumented.h>
15 
16 /**
17  * set_bit - Atomically set a bit in memory
18  * @nr: the bit to set
19  * @addr: the address to start counting from
20  *
21  * This is a relaxed atomic operation (no implied memory barriers).
22  *
23  * Note that @nr may be almost arbitrarily large; this function is not
24  * restricted to acting on a single-word quantity.
25  */
26 static inline void set_bit(long nr, volatile unsigned long *addr)
27 {
28 	instrument_atomic_write(addr + BIT_WORD(nr), sizeof(long));
29 	arch_set_bit(nr, addr);
30 }
31 
32 /**
33  * clear_bit - Clears a bit in memory
34  * @nr: Bit to clear
35  * @addr: Address to start counting from
36  *
37  * This is a relaxed atomic operation (no implied memory barriers).
38  */
39 static inline void clear_bit(long nr, volatile unsigned long *addr)
40 {
41 	instrument_atomic_write(addr + BIT_WORD(nr), sizeof(long));
42 	arch_clear_bit(nr, addr);
43 }
44 
45 /**
46  * change_bit - Toggle a bit in memory
47  * @nr: Bit to change
48  * @addr: Address to start counting from
49  *
50  * This is a relaxed atomic operation (no implied memory barriers).
51  *
52  * Note that @nr may be almost arbitrarily large; this function is not
53  * restricted to acting on a single-word quantity.
54  */
55 static inline void change_bit(long nr, volatile unsigned long *addr)
56 {
57 	instrument_atomic_write(addr + BIT_WORD(nr), sizeof(long));
58 	arch_change_bit(nr, addr);
59 }
60 
61 /**
62  * test_and_set_bit - Set a bit and return its old value
63  * @nr: Bit to set
64  * @addr: Address to count from
65  *
66  * This is an atomic fully-ordered operation (implied full memory barrier).
67  */
68 static inline bool test_and_set_bit(long nr, volatile unsigned long *addr)
69 {
70 	instrument_atomic_read_write(addr + BIT_WORD(nr), sizeof(long));
71 	return arch_test_and_set_bit(nr, addr);
72 }
73 
74 /**
75  * test_and_clear_bit - Clear a bit and return its old value
76  * @nr: Bit to clear
77  * @addr: Address to count from
78  *
79  * This is an atomic fully-ordered operation (implied full memory barrier).
80  */
81 static inline bool test_and_clear_bit(long nr, volatile unsigned long *addr)
82 {
83 	instrument_atomic_read_write(addr + BIT_WORD(nr), sizeof(long));
84 	return arch_test_and_clear_bit(nr, addr);
85 }
86 
87 /**
88  * test_and_change_bit - Change a bit and return its old value
89  * @nr: Bit to change
90  * @addr: Address to count from
91  *
92  * This is an atomic fully-ordered operation (implied full memory barrier).
93  */
94 static inline bool test_and_change_bit(long nr, volatile unsigned long *addr)
95 {
96 	instrument_atomic_read_write(addr + BIT_WORD(nr), sizeof(long));
97 	return arch_test_and_change_bit(nr, addr);
98 }
99 
100 #endif /* _ASM_GENERIC_BITOPS_INSTRUMENTED_NON_ATOMIC_H */
101