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 __always_inline void set_bit(long nr, volatile unsigned long *addr) |
27 | { |
28 | instrument_atomic_write(v: addr + BIT_WORD(nr), size: 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 __always_inline void clear_bit(long nr, volatile unsigned long *addr) |
40 | { |
41 | instrument_atomic_write(v: addr + BIT_WORD(nr), size: 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 __always_inline void change_bit(long nr, volatile unsigned long *addr) |
56 | { |
57 | instrument_atomic_write(v: addr + BIT_WORD(nr), size: 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 __always_inline bool test_and_set_bit(long nr, volatile unsigned long *addr) |
69 | { |
70 | kcsan_mb(); |
71 | instrument_atomic_read_write(v: addr + BIT_WORD(nr), size: sizeof(long)); |
72 | return arch_test_and_set_bit(nr, addr); |
73 | } |
74 | |
75 | /** |
76 | * test_and_clear_bit - Clear a bit and return its old value |
77 | * @nr: Bit to clear |
78 | * @addr: Address to count from |
79 | * |
80 | * This is an atomic fully-ordered operation (implied full memory barrier). |
81 | */ |
82 | static __always_inline bool test_and_clear_bit(long nr, volatile unsigned long *addr) |
83 | { |
84 | kcsan_mb(); |
85 | instrument_atomic_read_write(v: addr + BIT_WORD(nr), size: sizeof(long)); |
86 | return arch_test_and_clear_bit(nr, addr); |
87 | } |
88 | |
89 | /** |
90 | * test_and_change_bit - Change a bit and return its old value |
91 | * @nr: Bit to change |
92 | * @addr: Address to count from |
93 | * |
94 | * This is an atomic fully-ordered operation (implied full memory barrier). |
95 | */ |
96 | static __always_inline bool test_and_change_bit(long nr, volatile unsigned long *addr) |
97 | { |
98 | kcsan_mb(); |
99 | instrument_atomic_read_write(v: addr + BIT_WORD(nr), size: sizeof(long)); |
100 | return arch_test_and_change_bit(nr, addr); |
101 | } |
102 | |
103 | #endif /* _ASM_GENERIC_BITOPS_INSTRUMENTED_NON_ATOMIC_H */ |
104 | |