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