xref: /dpdk/lib/eal/include/rte_bitops.h (revision daa02b5cddbb8e11b31d41e2bf7bb1ae64dcae2f)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2020 Arm Limited
3  */
4 
5 #ifndef _RTE_BITOPS_H_
6 #define _RTE_BITOPS_H_
7 
8 /**
9  * @file
10  * Bit Operations
11  *
12  * This file defines a family of APIs for bit operations
13  * without enforcing memory ordering.
14  */
15 
16 #include <stdint.h>
17 #include <rte_debug.h>
18 #include <rte_compat.h>
19 
20 /**
21  * Get the uint64_t value for a specified bit set.
22  *
23  * @param nr
24  *   The bit number in range of 0 to 63.
25  */
26 #define RTE_BIT64(nr) (UINT64_C(1) << (nr))
27 
28 /**
29  * Get the uint32_t value for a specified bit set.
30  *
31  * @param nr
32  *   The bit number in range of 0 to 31.
33  */
34 #define RTE_BIT32(nr) (UINT32_C(1) << (nr))
35 
36 /*------------------------ 32-bit relaxed operations ------------------------*/
37 
38 /**
39  * @warning
40  * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
41  *
42  * Get the target bit from a 32-bit value without memory ordering.
43  *
44  * @param nr
45  *   The target bit to get.
46  * @param addr
47  *   The address holding the bit.
48  * @return
49  *   The target bit.
50  */
51 __rte_experimental
52 static inline uint32_t
53 rte_bit_relaxed_get32(unsigned int nr, volatile uint32_t *addr)
54 {
55 	RTE_ASSERT(nr < 32);
56 
57 	uint32_t mask = UINT32_C(1) << nr;
58 	return (*addr) & mask;
59 }
60 
61 /**
62  * @warning
63  * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
64  *
65  * Set the target bit in a 32-bit value to 1 without memory ordering.
66  *
67  * @param nr
68  *   The target bit to set.
69  * @param addr
70  *   The address holding the bit.
71  */
72 __rte_experimental
73 static inline void
74 rte_bit_relaxed_set32(unsigned int nr, volatile uint32_t *addr)
75 {
76 	RTE_ASSERT(nr < 32);
77 
78 	uint32_t mask = RTE_BIT32(nr);
79 	*addr = (*addr) | mask;
80 }
81 
82 /**
83  * @warning
84  * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
85  *
86  * Clear the target bit in a 32-bit value to 0 without memory ordering.
87  *
88  * @param nr
89  *   The target bit to clear.
90  * @param addr
91  *   The address holding the bit.
92  */
93 __rte_experimental
94 static inline void
95 rte_bit_relaxed_clear32(unsigned int nr, volatile uint32_t *addr)
96 {
97 	RTE_ASSERT(nr < 32);
98 
99 	uint32_t mask = RTE_BIT32(nr);
100 	*addr = (*addr) & (~mask);
101 }
102 
103 /**
104  * @warning
105  * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
106  *
107  * Return the original bit from a 32-bit value, then set it to 1 without
108  * memory ordering.
109  *
110  * @param nr
111  *   The target bit to get and set.
112  * @param addr
113  *   The address holding the bit.
114  * @return
115  *   The original bit.
116  */
117 __rte_experimental
118 static inline uint32_t
119 rte_bit_relaxed_test_and_set32(unsigned int nr, volatile uint32_t *addr)
120 {
121 	RTE_ASSERT(nr < 32);
122 
123 	uint32_t mask = RTE_BIT32(nr);
124 	uint32_t val = *addr;
125 	*addr = val | mask;
126 	return val & mask;
127 }
128 
129 /**
130  * @warning
131  * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
132  *
133  * Return the original bit from a 32-bit value, then clear it to 0 without
134  * memory ordering.
135  *
136  * @param nr
137  *   The target bit to get and clear.
138  * @param addr
139  *   The address holding the bit.
140  * @return
141  *   The original bit.
142  */
143 __rte_experimental
144 static inline uint32_t
145 rte_bit_relaxed_test_and_clear32(unsigned int nr, volatile uint32_t *addr)
146 {
147 	RTE_ASSERT(nr < 32);
148 
149 	uint32_t mask = RTE_BIT32(nr);
150 	uint32_t val = *addr;
151 	*addr = val & (~mask);
152 	return val & mask;
153 }
154 
155 /*------------------------ 64-bit relaxed operations ------------------------*/
156 
157 /**
158  * @warning
159  * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
160  *
161  * Get the target bit from a 64-bit value without memory ordering.
162  *
163  * @param nr
164  *   The target bit to get.
165  * @param addr
166  *   The address holding the bit.
167  * @return
168  *   The target bit.
169  */
170 __rte_experimental
171 static inline uint64_t
172 rte_bit_relaxed_get64(unsigned int nr, volatile uint64_t *addr)
173 {
174 	RTE_ASSERT(nr < 64);
175 
176 	uint64_t mask = RTE_BIT64(nr);
177 	return (*addr) & mask;
178 }
179 
180 /**
181  * @warning
182  * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
183  *
184  * Set the target bit in a 64-bit value to 1 without memory ordering.
185  *
186  * @param nr
187  *   The target bit to set.
188  * @param addr
189  *   The address holding the bit.
190  */
191 __rte_experimental
192 static inline void
193 rte_bit_relaxed_set64(unsigned int nr, volatile uint64_t *addr)
194 {
195 	RTE_ASSERT(nr < 64);
196 
197 	uint64_t mask = RTE_BIT64(nr);
198 	(*addr) = (*addr) | mask;
199 }
200 
201 /**
202  * @warning
203  * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
204  *
205  * Clear the target bit in a 64-bit value to 0 without memory ordering.
206  *
207  * @param nr
208  *   The target bit to clear.
209  * @param addr
210  *   The address holding the bit.
211  */
212 __rte_experimental
213 static inline void
214 rte_bit_relaxed_clear64(unsigned int nr, volatile uint64_t *addr)
215 {
216 	RTE_ASSERT(nr < 64);
217 
218 	uint64_t mask = RTE_BIT64(nr);
219 	*addr = (*addr) & (~mask);
220 }
221 
222 /**
223  * @warning
224  * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
225  *
226  * Return the original bit from a 64-bit value, then set it to 1 without
227  * memory ordering.
228  *
229  * @param nr
230  *   The target bit to get and set.
231  * @param addr
232  *   The address holding the bit.
233  * @return
234  *   The original bit.
235  */
236 __rte_experimental
237 static inline uint64_t
238 rte_bit_relaxed_test_and_set64(unsigned int nr, volatile uint64_t *addr)
239 {
240 	RTE_ASSERT(nr < 64);
241 
242 	uint64_t mask = RTE_BIT64(nr);
243 	uint64_t val = *addr;
244 	*addr = val | mask;
245 	return val;
246 }
247 
248 /**
249  * @warning
250  * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
251  *
252  * Return the original bit from a 64-bit value, then clear it to 0 without
253  * memory ordering.
254  *
255  * @param nr
256  *   The target bit to get and clear.
257  * @param addr
258  *   The address holding the bit.
259  * @return
260  *   The original bit.
261  */
262 __rte_experimental
263 static inline uint64_t
264 rte_bit_relaxed_test_and_clear64(unsigned int nr, volatile uint64_t *addr)
265 {
266 	RTE_ASSERT(nr < 64);
267 
268 	uint64_t mask = RTE_BIT64(nr);
269 	uint64_t val = *addr;
270 	*addr = val & (~mask);
271 	return val & mask;
272 }
273 
274 #endif /* _RTE_BITOPS_H_ */
275