Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2020 Arm Limited
3 : : * Copyright(c) 2010-2019 Intel Corporation
4 : : * Copyright(c) 2023 Microsoft Corporation
5 : : * Copyright(c) 2024 Ericsson AB
6 : : */
7 : :
8 : : #ifndef _RTE_BITOPS_H_
9 : : #define _RTE_BITOPS_H_
10 : :
11 : : /**
12 : : * @file
13 : : * Bit Operations
14 : : *
15 : : * This file provides functionality for low-level, single-word
16 : : * arithmetic and bit-level operations, such as counting or
17 : : * setting individual bits.
18 : : */
19 : :
20 : : #include <stdint.h>
21 : :
22 : : #include <rte_compat.h>
23 : : #include <rte_debug.h>
24 : : #include <rte_stdatomic.h>
25 : :
26 : : #ifdef __cplusplus
27 : : extern "C" {
28 : : #endif
29 : :
30 : : /**
31 : : * Get the uint64_t value for a specified bit set.
32 : : *
33 : : * @param nr
34 : : * The bit number in range of 0 to 63.
35 : : */
36 : : #define RTE_BIT64(nr) (UINT64_C(1) << (nr))
37 : :
38 : : /**
39 : : * Get the uint32_t value for a specified bit set.
40 : : *
41 : : * @param nr
42 : : * The bit number in range of 0 to 31.
43 : : */
44 : : #define RTE_BIT32(nr) (UINT32_C(1) << (nr))
45 : :
46 : : /**
47 : : * Get the uint32_t shifted value.
48 : : *
49 : : * @param val
50 : : * The value to be shifted.
51 : : * @param nr
52 : : * The shift number in range of 0 to (32 - width of val).
53 : : */
54 : : #define RTE_SHIFT_VAL32(val, nr) ((uint32_t)(val) << (nr))
55 : :
56 : : /**
57 : : * Get the uint64_t shifted value.
58 : : *
59 : : * @param val
60 : : * The value to be shifted.
61 : : * @param nr
62 : : * The shift number in range of 0 to (64 - width of val).
63 : : */
64 : : #define RTE_SHIFT_VAL64(val, nr) ((uint64_t)(val) << (nr))
65 : :
66 : : /**
67 : : * Generate a contiguous 32-bit mask
68 : : * starting at bit position low and ending at position high.
69 : : *
70 : : * @param high
71 : : * High bit position.
72 : : * @param low
73 : : * Low bit position.
74 : : */
75 : : #define RTE_GENMASK32(high, low) \
76 : : (((~UINT32_C(0)) << (low)) & (~UINT32_C(0) >> (31u - (high))))
77 : :
78 : : /**
79 : : * Generate a contiguous 64-bit mask
80 : : * starting at bit position low and ending at position high.
81 : : *
82 : : * @param high
83 : : * High bit position.
84 : : * @param low
85 : : * Low bit position.
86 : : */
87 : : #define RTE_GENMASK64(high, low) \
88 : : (((~UINT64_C(0)) << (low)) & (~UINT64_C(0) >> (63u - (high))))
89 : :
90 : : /**
91 : : * Extract a 32-bit field element.
92 : : *
93 : : * @param mask
94 : : * Shifted mask.
95 : : * @param reg
96 : : * Value of entire bitfield.
97 : : */
98 : : #define RTE_FIELD_GET32(mask, reg) \
99 : : ((typeof(mask))(((reg) & (mask)) >> rte_ctz32(mask)))
100 : :
101 : : /**
102 : : * Extract a 64-bit field element.
103 : : *
104 : : * @param mask
105 : : * Shifted mask.
106 : : * @param reg
107 : : * Value of entire bitfield.
108 : : */
109 : : #define RTE_FIELD_GET64(mask, reg) \
110 : : ((typeof(mask))(((reg) & (mask)) >> rte_ctz64(mask)))
111 : :
112 : : /**
113 : : * Test bit in word.
114 : : *
115 : : * Generic selection macro to test the value of a bit in a 32-bit or
116 : : * 64-bit word. The type of operation depends on the type of the @c
117 : : * addr parameter.
118 : : *
119 : : * This macro does not give any guarantees in regards to memory
120 : : * ordering or atomicity.
121 : : *
122 : : * @param addr
123 : : * A pointer to the word to modify.
124 : : * @param nr
125 : : * The index of the bit.
126 : : */
127 : : #define rte_bit_test(addr, nr) \
128 : : _Generic((addr), \
129 : : uint32_t *: __rte_bit_test32, \
130 : : const uint32_t *: __rte_bit_test32, \
131 : : volatile uint32_t *: __rte_bit_v_test32, \
132 : : const volatile uint32_t *: __rte_bit_v_test32, \
133 : : uint64_t *: __rte_bit_test64, \
134 : : const uint64_t *: __rte_bit_test64, \
135 : : volatile uint64_t *: __rte_bit_v_test64, \
136 : : const volatile uint64_t *: __rte_bit_v_test64) \
137 : : (addr, nr)
138 : :
139 : : /**
140 : : * Set bit in word.
141 : : *
142 : : * Generic selection macro to set a bit in a 32-bit or 64-bit
143 : : * word. The type of operation depends on the type of the @c addr
144 : : * parameter.
145 : : *
146 : : * This macro does not give any guarantees in regards to memory
147 : : * ordering or atomicity.
148 : : *
149 : : * @param addr
150 : : * A pointer to the word to modify.
151 : : * @param nr
152 : : * The index of the bit.
153 : : */
154 : : #define rte_bit_set(addr, nr) \
155 : : _Generic((addr), \
156 : : uint32_t *: __rte_bit_set32, \
157 : : volatile uint32_t *: __rte_bit_v_set32, \
158 : : uint64_t *: __rte_bit_set64, \
159 : : volatile uint64_t *: __rte_bit_v_set64) \
160 : : (addr, nr)
161 : :
162 : : /**
163 : : * Clear bit in word.
164 : : *
165 : : * Generic selection macro to clear a bit in a 32-bit or 64-bit
166 : : * word. The type of operation depends on the type of the @c addr
167 : : * parameter.
168 : : *
169 : : * This macro does not give any guarantees in regards to memory
170 : : * ordering or atomicity.
171 : : *
172 : : * @param addr
173 : : * A pointer to the word to modify.
174 : : * @param nr
175 : : * The index of the bit.
176 : : */
177 : : #define rte_bit_clear(addr, nr) \
178 : : _Generic((addr), \
179 : : uint32_t *: __rte_bit_clear32, \
180 : : volatile uint32_t *: __rte_bit_v_clear32, \
181 : : uint64_t *: __rte_bit_clear64, \
182 : : volatile uint64_t *: __rte_bit_v_clear64) \
183 : : (addr, nr)
184 : :
185 : : /**
186 : : * Assign a value to a bit in word.
187 : : *
188 : : * Generic selection macro to assign a value to a bit in a 32-bit or 64-bit
189 : : * word. The type of operation depends on the type of the @c addr parameter.
190 : : *
191 : : * This macro does not give any guarantees in regards to memory
192 : : * ordering or atomicity.
193 : : *
194 : : * @param addr
195 : : * A pointer to the word to modify.
196 : : * @param nr
197 : : * The index of the bit.
198 : : * @param value
199 : : * The new value of the bit - true for '1', or false for '0'.
200 : : */
201 : : #define rte_bit_assign(addr, nr, value) \
202 : : _Generic((addr), \
203 : : uint32_t *: __rte_bit_assign32, \
204 : : volatile uint32_t *: __rte_bit_v_assign32, \
205 : : uint64_t *: __rte_bit_assign64, \
206 : : volatile uint64_t *: __rte_bit_v_assign64) \
207 : : (addr, nr, value)
208 : :
209 : : /**
210 : : * Flip a bit in word.
211 : : *
212 : : * Generic selection macro to change the value of a bit to '0' if '1'
213 : : * or '1' if '0' in a 32-bit or 64-bit word. The type of operation
214 : : * depends on the type of the @c addr parameter.
215 : : *
216 : : * This macro does not give any guarantees in regards to memory
217 : : * ordering or atomicity.
218 : : *
219 : : * @param addr
220 : : * A pointer to the word to modify.
221 : : * @param nr
222 : : * The index of the bit.
223 : : */
224 : : #define rte_bit_flip(addr, nr) \
225 : : _Generic((addr), \
226 : : uint32_t *: __rte_bit_flip32, \
227 : : volatile uint32_t *: __rte_bit_v_flip32, \
228 : : uint64_t *: __rte_bit_flip64, \
229 : : volatile uint64_t *: __rte_bit_v_flip64) \
230 : : (addr, nr)
231 : :
232 : : /**
233 : : * Test if a particular bit in a word is set with a particular memory
234 : : * order.
235 : : *
236 : : * Test a bit with the resulting memory load ordered as per the
237 : : * specified memory order.
238 : : *
239 : : * @param addr
240 : : * A pointer to the word to query.
241 : : * @param nr
242 : : * The index of the bit.
243 : : * @param memory_order
244 : : * The memory order to use.
245 : : * @return
246 : : * Returns true if the bit is set, and false otherwise.
247 : : */
248 : : #define rte_bit_atomic_test(addr, nr, memory_order) \
249 : : _Generic((addr), \
250 : : uint32_t *: __rte_bit_atomic_test32, \
251 : : const uint32_t *: __rte_bit_atomic_test32, \
252 : : volatile uint32_t *: __rte_bit_atomic_v_test32, \
253 : : const volatile uint32_t *: __rte_bit_atomic_v_test32, \
254 : : uint64_t *: __rte_bit_atomic_test64, \
255 : : const uint64_t *: __rte_bit_atomic_test64, \
256 : : volatile uint64_t *: __rte_bit_atomic_v_test64, \
257 : : const volatile uint64_t *: __rte_bit_atomic_v_test64) \
258 : : (addr, nr, memory_order)
259 : :
260 : : /**
261 : : * Atomically set bit in word.
262 : : *
263 : : * Generic selection macro to atomically set bit specified by @c nr in
264 : : * the word pointed to by @c addr to '1', with the memory ordering as
265 : : * specified by @c memory_order.
266 : : *
267 : : * @param addr
268 : : * A pointer to the word to modify.
269 : : * @param nr
270 : : * The index of the bit.
271 : : * @param memory_order
272 : : * The memory order to use.
273 : : */
274 : : #define rte_bit_atomic_set(addr, nr, memory_order) \
275 : : _Generic((addr), \
276 : : uint32_t *: __rte_bit_atomic_set32, \
277 : : volatile uint32_t *: __rte_bit_atomic_v_set32, \
278 : : uint64_t *: __rte_bit_atomic_set64, \
279 : : volatile uint64_t *: __rte_bit_atomic_v_set64) \
280 : : (addr, nr, memory_order)
281 : :
282 : : /**
283 : : * Atomically clear bit in word.
284 : : *
285 : : * Generic selection macro to atomically set bit specified by @c nr in
286 : : * the word pointed to by @c addr to '0', with the memory ordering as
287 : : * specified by @c memory_order.
288 : : *
289 : : * @param addr
290 : : * A pointer to the word to modify.
291 : : * @param nr
292 : : * The index of the bit.
293 : : * @param memory_order
294 : : * The memory order to use.
295 : : */
296 : : #define rte_bit_atomic_clear(addr, nr, memory_order) \
297 : : _Generic((addr), \
298 : : uint32_t *: __rte_bit_atomic_clear32, \
299 : : volatile uint32_t *: __rte_bit_atomic_v_clear32, \
300 : : uint64_t *: __rte_bit_atomic_clear64, \
301 : : volatile uint64_t *: __rte_bit_atomic_v_clear64) \
302 : : (addr, nr, memory_order)
303 : :
304 : : /**
305 : : * Atomically assign a value to bit in word.
306 : : *
307 : : * Generic selection macro to atomically set bit specified by @c nr in the
308 : : * word pointed to by @c addr to the value indicated by @c value, with
309 : : * the memory ordering as specified with @c memory_order.
310 : : *
311 : : * @param addr
312 : : * A pointer to the word to modify.
313 : : * @param nr
314 : : * The index of the bit.
315 : : * @param value
316 : : * The new value of the bit - true for '1', or false for '0'.
317 : : * @param memory_order
318 : : * The memory order to use.
319 : : */
320 : : #define rte_bit_atomic_assign(addr, nr, value, memory_order) \
321 : : _Generic((addr), \
322 : : uint32_t *: __rte_bit_atomic_assign32, \
323 : : volatile uint32_t *: __rte_bit_atomic_v_assign32, \
324 : : uint64_t *: __rte_bit_atomic_assign64, \
325 : : volatile uint64_t *: __rte_bit_atomic_v_assign64) \
326 : : (addr, nr, value, memory_order)
327 : :
328 : : /**
329 : : * Atomically flip bit in word.
330 : : *
331 : : * Generic selection macro to atomically negate the value of the bit
332 : : * specified by @c nr in the word pointed to by @c addr to the value
333 : : * indicated by @c value, with the memory ordering as specified with
334 : : * @c memory_order.
335 : : *
336 : : * @param addr
337 : : * A pointer to the word to modify.
338 : : * @param nr
339 : : * The index of the bit.
340 : : * @param memory_order
341 : : * The memory order to use.
342 : : */
343 : : #define rte_bit_atomic_flip(addr, nr, memory_order) \
344 : : _Generic((addr), \
345 : : uint32_t *: __rte_bit_atomic_flip32, \
346 : : volatile uint32_t *: __rte_bit_atomic_v_flip32, \
347 : : uint64_t *: __rte_bit_atomic_flip64, \
348 : : volatile uint64_t *: __rte_bit_atomic_v_flip64) \
349 : : (addr, nr, memory_order)
350 : :
351 : : /**
352 : : * Atomically test and set a bit in word.
353 : : *
354 : : * Generic selection macro to atomically test and set bit specified by
355 : : * @c nr in the word pointed to by @c addr to '1', with the memory
356 : : * ordering as specified with @c memory_order.
357 : : *
358 : : * @param addr
359 : : * A pointer to the word to modify.
360 : : * @param nr
361 : : * The index of the bit.
362 : : * @param memory_order
363 : : * The memory order to use.
364 : : * @return
365 : : * Returns true if the bit was set, and false otherwise.
366 : : */
367 : : #define rte_bit_atomic_test_and_set(addr, nr, memory_order) \
368 : : _Generic((addr), \
369 : : uint32_t *: __rte_bit_atomic_test_and_set32, \
370 : : volatile uint32_t *: __rte_bit_atomic_v_test_and_set32, \
371 : : uint64_t *: __rte_bit_atomic_test_and_set64, \
372 : : volatile uint64_t *: __rte_bit_atomic_v_test_and_set64) \
373 : : (addr, nr, memory_order)
374 : :
375 : : /**
376 : : * Atomically test and clear a bit in word.
377 : : *
378 : : * Generic selection macro to atomically test and clear bit specified
379 : : * by @c nr in the word pointed to by @c addr to '0', with the memory
380 : : * ordering as specified with @c memory_order.
381 : : *
382 : : * @param addr
383 : : * A pointer to the word to modify.
384 : : * @param nr
385 : : * The index of the bit.
386 : : * @param memory_order
387 : : * The memory order to use.
388 : : * @return
389 : : * Returns true if the bit was set, and false otherwise.
390 : : */
391 : : #define rte_bit_atomic_test_and_clear(addr, nr, memory_order) \
392 : : _Generic((addr), \
393 : : uint32_t *: __rte_bit_atomic_test_and_clear32, \
394 : : volatile uint32_t *: __rte_bit_atomic_v_test_and_clear32, \
395 : : uint64_t *: __rte_bit_atomic_test_and_clear64, \
396 : : volatile uint64_t *: __rte_bit_atomic_v_test_and_clear64) \
397 : : (addr, nr, memory_order)
398 : :
399 : : /**
400 : : * Atomically test and assign a bit in word.
401 : : *
402 : : * Generic selection macro to atomically test and assign bit specified
403 : : * by @c nr in the word pointed to by @c addr the value specified by
404 : : * @c value, with the memory ordering as specified with @c
405 : : * memory_order.
406 : : *
407 : : * @param addr
408 : : * A pointer to the word to modify.
409 : : * @param nr
410 : : * The index of the bit.
411 : : * @param value
412 : : * The new value of the bit - true for '1', or false for '0'.
413 : : * @param memory_order
414 : : * The memory order to use.
415 : : * @return
416 : : * Returns true if the bit was set, and false otherwise.
417 : : */
418 : : #define rte_bit_atomic_test_and_assign(addr, nr, value, memory_order) \
419 : : _Generic((addr), \
420 : : uint32_t *: __rte_bit_atomic_test_and_assign32, \
421 : : volatile uint32_t *: __rte_bit_atomic_v_test_and_assign32, \
422 : : uint64_t *: __rte_bit_atomic_test_and_assign64, \
423 : : volatile uint64_t *: __rte_bit_atomic_v_test_and_assign64) \
424 : : (addr, nr, value, memory_order)
425 : :
426 : : #define __RTE_GEN_BIT_TEST(variant, qualifier, size) \
427 : : static inline bool \
428 : : __rte_bit_ ## variant ## test ## size(const qualifier uint ## size ## _t *addr, unsigned int nr) \
429 : : { \
430 : : RTE_ASSERT(nr < size); \
431 : : uint ## size ## _t mask = (uint ## size ## _t)1 << nr; \
432 : : return *addr & mask; \
433 : : }
434 : :
435 : : #define __RTE_GEN_BIT_SET(variant, qualifier, size) \
436 : : static inline void \
437 : : __rte_bit_ ## variant ## set ## size(qualifier uint ## size ## _t *addr, unsigned int nr) \
438 : : { \
439 : : RTE_ASSERT(nr < size); \
440 : : uint ## size ## _t mask = (uint ## size ## _t)1 << nr; \
441 : : *addr |= mask; \
442 : : }
443 : :
444 : : #define __RTE_GEN_BIT_CLEAR(variant, qualifier, size) \
445 : : static inline void \
446 : : __rte_bit_ ## variant ## clear ## size(qualifier uint ## size ## _t *addr, unsigned int nr) \
447 : : { \
448 : : RTE_ASSERT(nr < size); \
449 : : uint ## size ## _t mask = ~((uint ## size ## _t)1 << nr); \
450 : : (*addr) &= mask; \
451 : : }
452 : :
453 : : #define __RTE_GEN_BIT_ASSIGN(variant, qualifier, size) \
454 : : static inline void \
455 : : __rte_bit_ ## variant ## assign ## size(qualifier uint ## size ## _t *addr, unsigned int nr, \
456 : : bool value) \
457 : : { \
458 : : if (value) \
459 : : __rte_bit_ ## variant ## set ## size(addr, nr); \
460 : : else \
461 : : __rte_bit_ ## variant ## clear ## size(addr, nr); \
462 : : }
463 : :
464 : : #define __RTE_GEN_BIT_FLIP(variant, qualifier, size) \
465 : : static inline void \
466 : : __rte_bit_ ## variant ## flip ## size(qualifier uint ## size ## _t *addr, unsigned int nr) \
467 : : { \
468 : : bool value; \
469 : : value = __rte_bit_ ## variant ## test ## size(addr, nr); \
470 : : __rte_bit_ ## variant ## assign ## size(addr, nr, !value); \
471 : : }
472 : :
473 : : #define __RTE_GEN_BIT_OPS(v, qualifier, size) \
474 : : __RTE_GEN_BIT_TEST(v, qualifier, size) \
475 : : __RTE_GEN_BIT_SET(v, qualifier, size) \
476 : : __RTE_GEN_BIT_CLEAR(v, qualifier, size) \
477 : : __RTE_GEN_BIT_ASSIGN(v, qualifier, size) \
478 : : __RTE_GEN_BIT_FLIP(v, qualifier, size)
479 : :
480 : : #define __RTE_GEN_BIT_OPS_SIZE(size) \
481 : : __RTE_GEN_BIT_OPS(,, size) \
482 : : __RTE_GEN_BIT_OPS(v_, volatile, size)
483 : :
484 [ - + + - : 194 : __RTE_GEN_BIT_OPS_SIZE(32)
- + + - +
+ - + + +
- + + + -
+ - + + +
- + + + -
+ + + - +
- + ]
485 [ + + + + : 57770538 : __RTE_GEN_BIT_OPS_SIZE(64)
- + + + +
+ - + + +
- + + + +
+ + + + +
+ + + + -
+ + + - +
- + ]
486 : :
487 : : #define __RTE_GEN_BIT_ATOMIC_TEST(variant, qualifier, size) \
488 : : static inline bool \
489 : : __rte_bit_atomic_ ## variant ## test ## size(const qualifier uint ## size ## _t *addr, \
490 : : unsigned int nr, int memory_order) \
491 : : { \
492 : : RTE_ASSERT(nr < size); \
493 : : const qualifier RTE_ATOMIC(uint ## size ## _t) *a_addr = \
494 : : (const qualifier RTE_ATOMIC(uint ## size ## _t) *)addr; \
495 : : uint ## size ## _t mask = (uint ## size ## _t)1 << nr; \
496 : : return rte_atomic_load_explicit(a_addr, memory_order) & mask; \
497 : : }
498 : :
499 : : #define __RTE_GEN_BIT_ATOMIC_SET(variant, qualifier, size) \
500 : : static inline void \
501 : : __rte_bit_atomic_ ## variant ## set ## size(qualifier uint ## size ## _t *addr, \
502 : : unsigned int nr, int memory_order) \
503 : : { \
504 : : RTE_ASSERT(nr < size); \
505 : : qualifier RTE_ATOMIC(uint ## size ## _t) *a_addr = \
506 : : (qualifier RTE_ATOMIC(uint ## size ## _t) *)addr; \
507 : : uint ## size ## _t mask = (uint ## size ## _t)1 << nr; \
508 : : rte_atomic_fetch_or_explicit(a_addr, mask, memory_order); \
509 : : }
510 : :
511 : : #define __RTE_GEN_BIT_ATOMIC_CLEAR(variant, qualifier, size) \
512 : : static inline void \
513 : : __rte_bit_atomic_ ## variant ## clear ## size(qualifier uint ## size ## _t *addr, \
514 : : unsigned int nr, int memory_order) \
515 : : { \
516 : : RTE_ASSERT(nr < size); \
517 : : qualifier RTE_ATOMIC(uint ## size ## _t) *a_addr = \
518 : : (qualifier RTE_ATOMIC(uint ## size ## _t) *)addr; \
519 : : uint ## size ## _t mask = (uint ## size ## _t)1 << nr; \
520 : : rte_atomic_fetch_and_explicit(a_addr, ~mask, memory_order); \
521 : : }
522 : :
523 : : #define __RTE_GEN_BIT_ATOMIC_FLIP(variant, qualifier, size) \
524 : : static inline void \
525 : : __rte_bit_atomic_ ## variant ## flip ## size(qualifier uint ## size ## _t *addr, \
526 : : unsigned int nr, int memory_order) \
527 : : { \
528 : : RTE_ASSERT(nr < size); \
529 : : qualifier RTE_ATOMIC(uint ## size ## _t) *a_addr = \
530 : : (qualifier RTE_ATOMIC(uint ## size ## _t) *)addr; \
531 : : uint ## size ## _t mask = (uint ## size ## _t)1 << nr; \
532 : : rte_atomic_fetch_xor_explicit(a_addr, mask, memory_order); \
533 : : }
534 : :
535 : : #define __RTE_GEN_BIT_ATOMIC_ASSIGN(variant, qualifier, size) \
536 : : static inline void \
537 : : __rte_bit_atomic_## variant ## assign ## size(qualifier uint ## size ## _t *addr, \
538 : : unsigned int nr, bool value, int memory_order) \
539 : : { \
540 : : if (value) \
541 : : __rte_bit_atomic_ ## variant ## set ## size(addr, nr, memory_order); \
542 : : else \
543 : : __rte_bit_atomic_ ## variant ## clear ## size(addr, nr, memory_order); \
544 : : }
545 : :
546 : : #define __RTE_GEN_BIT_ATOMIC_TEST_AND_SET(variant, qualifier, size) \
547 : : static inline bool \
548 : : __rte_bit_atomic_ ## variant ## test_and_set ## size(qualifier uint ## size ## _t *addr, \
549 : : unsigned int nr, int memory_order) \
550 : : { \
551 : : RTE_ASSERT(nr < size); \
552 : : qualifier RTE_ATOMIC(uint ## size ## _t) *a_addr = \
553 : : (qualifier RTE_ATOMIC(uint ## size ## _t) *)addr; \
554 : : uint ## size ## _t mask = (uint ## size ## _t)1 << nr; \
555 : : uint ## size ## _t prev; \
556 : : prev = rte_atomic_fetch_or_explicit(a_addr, mask, memory_order); \
557 : : return prev & mask; \
558 : : }
559 : :
560 : : #define __RTE_GEN_BIT_ATOMIC_TEST_AND_CLEAR(variant, qualifier, size) \
561 : : static inline bool \
562 : : __rte_bit_atomic_ ## variant ## test_and_clear ## size(qualifier uint ## size ## _t *addr, \
563 : : unsigned int nr, int memory_order) \
564 : : { \
565 : : RTE_ASSERT(nr < size); \
566 : : qualifier RTE_ATOMIC(uint ## size ## _t) *a_addr = \
567 : : (qualifier RTE_ATOMIC(uint ## size ## _t) *)addr; \
568 : : uint ## size ## _t mask = (uint ## size ## _t)1 << nr; \
569 : : uint ## size ## _t prev; \
570 : : prev = rte_atomic_fetch_and_explicit(a_addr, ~mask, memory_order); \
571 : : return prev & mask; \
572 : : }
573 : :
574 : : #define __RTE_GEN_BIT_ATOMIC_TEST_AND_ASSIGN(variant, qualifier, size) \
575 : : static inline bool \
576 : : __rte_bit_atomic_ ## variant ## test_and_assign ## size( \
577 : : qualifier uint ## size ## _t *addr, unsigned int nr, bool value, \
578 : : int memory_order) \
579 : : { \
580 : : if (value) \
581 : : return __rte_bit_atomic_ ## variant ## test_and_set ## size(addr, nr, \
582 : : memory_order); \
583 : : else \
584 : : return __rte_bit_atomic_ ## variant ## test_and_clear ## size(addr, nr, \
585 : : memory_order); \
586 : : }
587 : :
588 : : #define __RTE_GEN_BIT_ATOMIC_OPS(variant, qualifier, size) \
589 : : __RTE_GEN_BIT_ATOMIC_TEST(variant, qualifier, size) \
590 : : __RTE_GEN_BIT_ATOMIC_SET(variant, qualifier, size) \
591 : : __RTE_GEN_BIT_ATOMIC_CLEAR(variant, qualifier, size) \
592 : : __RTE_GEN_BIT_ATOMIC_ASSIGN(variant, qualifier, size) \
593 : : __RTE_GEN_BIT_ATOMIC_TEST_AND_SET(variant, qualifier, size) \
594 : : __RTE_GEN_BIT_ATOMIC_TEST_AND_CLEAR(variant, qualifier, size) \
595 : : __RTE_GEN_BIT_ATOMIC_TEST_AND_ASSIGN(variant, qualifier, size) \
596 : : __RTE_GEN_BIT_ATOMIC_FLIP(variant, qualifier, size)
597 : :
598 : : #define __RTE_GEN_BIT_ATOMIC_OPS_SIZE(size) \
599 : : __RTE_GEN_BIT_ATOMIC_OPS(,, size) \
600 : : __RTE_GEN_BIT_ATOMIC_OPS(v_, volatile, size)
601 : :
602 [ + + - + : 6490108 : __RTE_GEN_BIT_ATOMIC_OPS_SIZE(32)
- + - + -
+ - + - +
- + - + ]
603 [ + + - + : 10574458 : __RTE_GEN_BIT_ATOMIC_OPS_SIZE(64)
- + - + -
+ - + - +
- + - + ]
604 : :
605 : : /*------------------------ 32-bit relaxed operations ------------------------*/
606 : :
607 : : /**
608 : : * Get the target bit from a 32-bit value without memory ordering.
609 : : *
610 : : * @param nr
611 : : * The target bit to get.
612 : : * @param addr
613 : : * The address holding the bit.
614 : : * @return
615 : : * The target bit.
616 : : */
617 : : static inline uint32_t
618 : : rte_bit_relaxed_get32(unsigned int nr, volatile uint32_t *addr)
619 : : {
620 : : RTE_ASSERT(nr < 32);
621 : :
622 : 96 : uint32_t mask = UINT32_C(1) << nr;
623 [ - + - + : 96 : return (*addr) & mask;
- + # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # #
# ]
624 : : }
625 : :
626 : : /**
627 : : * Set the target bit in a 32-bit value to 1 without memory ordering.
628 : : *
629 : : * @param nr
630 : : * The target bit to set.
631 : : * @param addr
632 : : * The address holding the bit.
633 : : */
634 : : static inline void
635 : : rte_bit_relaxed_set32(unsigned int nr, volatile uint32_t *addr)
636 : : {
637 : : RTE_ASSERT(nr < 32);
638 : :
639 : 32 : uint32_t mask = RTE_BIT32(nr);
640 [ # # # # : 32 : *addr = (*addr) | mask;
# # # # #
# # # # ]
641 : 0 : }
642 : :
643 : : /**
644 : : * Clear the target bit in a 32-bit value to 0 without memory ordering.
645 : : *
646 : : * @param nr
647 : : * The target bit to clear.
648 : : * @param addr
649 : : * The address holding the bit.
650 : : */
651 : : static inline void
652 : : rte_bit_relaxed_clear32(unsigned int nr, volatile uint32_t *addr)
653 : : {
654 : : RTE_ASSERT(nr < 32);
655 : :
656 : 32 : uint32_t mask = RTE_BIT32(nr);
657 [ # # ]: 32 : *addr = (*addr) & (~mask);
658 : 0 : }
659 : :
660 : : /**
661 : : * Return the original bit from a 32-bit value, then set it to 1 without
662 : : * memory ordering.
663 : : *
664 : : * @param nr
665 : : * The target bit to get and set.
666 : : * @param addr
667 : : * The address holding the bit.
668 : : * @return
669 : : * The original bit.
670 : : */
671 : : static inline uint32_t
672 : : rte_bit_relaxed_test_and_set32(unsigned int nr, volatile uint32_t *addr)
673 : : {
674 : : RTE_ASSERT(nr < 32);
675 : :
676 : 32 : uint32_t mask = RTE_BIT32(nr);
677 : 32 : uint32_t val = *addr;
678 : 32 : *addr = val | mask;
679 [ # # ]: 0 : return val & mask;
680 : : }
681 : :
682 : : /**
683 : : * Return the original bit from a 32-bit value, then clear it to 0 without
684 : : * memory ordering.
685 : : *
686 : : * @param nr
687 : : * The target bit to get and clear.
688 : : * @param addr
689 : : * The address holding the bit.
690 : : * @return
691 : : * The original bit.
692 : : */
693 : : static inline uint32_t
694 : : rte_bit_relaxed_test_and_clear32(unsigned int nr, volatile uint32_t *addr)
695 : : {
696 : : RTE_ASSERT(nr < 32);
697 : :
698 : 32 : uint32_t mask = RTE_BIT32(nr);
699 : 32 : uint32_t val = *addr;
700 : 32 : *addr = val & (~mask);
701 [ - + # # ]: 32 : return val & mask;
702 : : }
703 : :
704 : : /*------------------------ 64-bit relaxed operations ------------------------*/
705 : :
706 : : /**
707 : : * Get the target bit from a 64-bit value without memory ordering.
708 : : *
709 : : * @param nr
710 : : * The target bit to get.
711 : : * @param addr
712 : : * The address holding the bit.
713 : : * @return
714 : : * The target bit.
715 : : */
716 : : static inline uint64_t
717 : : rte_bit_relaxed_get64(unsigned int nr, volatile uint64_t *addr)
718 : : {
719 : : RTE_ASSERT(nr < 64);
720 : :
721 : 192 : uint64_t mask = RTE_BIT64(nr);
722 [ - + - + : 192 : return (*addr) & mask;
- + ]
723 : : }
724 : :
725 : : /**
726 : : * Set the target bit in a 64-bit value to 1 without memory ordering.
727 : : *
728 : : * @param nr
729 : : * The target bit to set.
730 : : * @param addr
731 : : * The address holding the bit.
732 : : */
733 : : static inline void
734 : : rte_bit_relaxed_set64(unsigned int nr, volatile uint64_t *addr)
735 : : {
736 : : RTE_ASSERT(nr < 64);
737 : :
738 : 336 : uint64_t mask = RTE_BIT64(nr);
739 : 336 : (*addr) = (*addr) | mask;
740 : : }
741 : :
742 : : /**
743 : : * Clear the target bit in a 64-bit value to 0 without memory ordering.
744 : : *
745 : : * @param nr
746 : : * The target bit to clear.
747 : : * @param addr
748 : : * The address holding the bit.
749 : : */
750 : : static inline void
751 : : rte_bit_relaxed_clear64(unsigned int nr, volatile uint64_t *addr)
752 : : {
753 : : RTE_ASSERT(nr < 64);
754 : :
755 : 267 : uint64_t mask = RTE_BIT64(nr);
756 : 267 : *addr = (*addr) & (~mask);
757 : 203 : }
758 : :
759 : : /**
760 : : * Return the original bit from a 64-bit value, then set it to 1 without
761 : : * memory ordering.
762 : : *
763 : : * @param nr
764 : : * The target bit to get and set.
765 : : * @param addr
766 : : * The address holding the bit.
767 : : * @return
768 : : * The original bit.
769 : : */
770 : : static inline uint64_t
771 : : rte_bit_relaxed_test_and_set64(unsigned int nr, volatile uint64_t *addr)
772 : : {
773 : : RTE_ASSERT(nr < 64);
774 : :
775 : 64 : uint64_t mask = RTE_BIT64(nr);
776 : 64 : uint64_t val = *addr;
777 : 64 : *addr = val | mask;
778 : : return val;
779 : : }
780 : :
781 : : /**
782 : : * Return the original bit from a 64-bit value, then clear it to 0 without
783 : : * memory ordering.
784 : : *
785 : : * @param nr
786 : : * The target bit to get and clear.
787 : : * @param addr
788 : : * The address holding the bit.
789 : : * @return
790 : : * The original bit.
791 : : */
792 : : static inline uint64_t
793 : : rte_bit_relaxed_test_and_clear64(unsigned int nr, volatile uint64_t *addr)
794 : : {
795 : : RTE_ASSERT(nr < 64);
796 : :
797 : 64 : uint64_t mask = RTE_BIT64(nr);
798 : 64 : uint64_t val = *addr;
799 : 64 : *addr = val & (~mask);
800 [ - + ]: 64 : return val & mask;
801 : : }
802 : :
803 : : #ifdef RTE_TOOLCHAIN_MSVC
804 : :
805 : : /**
806 : : * Get the count of leading 0-bits in v.
807 : : *
808 : : * @param v
809 : : * The value.
810 : : * @return
811 : : * The count of leading zero bits.
812 : : */
813 : : static inline unsigned int
814 : : rte_clz32(uint32_t v)
815 : : {
816 : : unsigned long rv;
817 : :
818 : : (void)_BitScanReverse(&rv, v);
819 : :
820 : : return (unsigned int)(sizeof(v) * CHAR_BIT - 1 - rv);
821 : : }
822 : :
823 : : /**
824 : : * Get the count of leading 0-bits in v.
825 : : *
826 : : * @param v
827 : : * The value.
828 : : * @return
829 : : * The count of leading zero bits.
830 : : */
831 : : static inline unsigned int
832 : : rte_clz64(uint64_t v)
833 : : {
834 : : unsigned long rv;
835 : :
836 : : (void)_BitScanReverse64(&rv, v);
837 : :
838 : : return (unsigned int)(sizeof(v) * CHAR_BIT - 1 - rv);
839 : : }
840 : :
841 : : /**
842 : : * Get the count of trailing 0-bits in v.
843 : : *
844 : : * @param v
845 : : * The value.
846 : : * @return
847 : : * The count of trailing zero bits.
848 : : */
849 : : static inline unsigned int
850 : : rte_ctz32(uint32_t v)
851 : : {
852 : : unsigned long rv;
853 : :
854 : : (void)_BitScanForward(&rv, v);
855 : :
856 : : return (unsigned int)rv;
857 : : }
858 : :
859 : : /**
860 : : * Get the count of trailing 0-bits in v.
861 : : *
862 : : * @param v
863 : : * The value.
864 : : * @return
865 : : * The count of trailing zero bits.
866 : : */
867 : : static inline unsigned int
868 : : rte_ctz64(uint64_t v)
869 : : {
870 : : unsigned long rv;
871 : :
872 : : (void)_BitScanForward64(&rv, v);
873 : :
874 : : return (unsigned int)rv;
875 : : }
876 : :
877 : : /**
878 : : * Get the count of 1-bits in v.
879 : : *
880 : : * @param v
881 : : * The value.
882 : : * @return
883 : : * The count of 1-bits.
884 : : */
885 : : static inline unsigned int
886 : : rte_popcount32(uint32_t v)
887 : : {
888 : : return (unsigned int)__popcnt(v);
889 : : }
890 : :
891 : : /**
892 : : * Get the count of 1-bits in v.
893 : : *
894 : : * @param v
895 : : * The value.
896 : : * @return
897 : : * The count of 1-bits.
898 : : */
899 : : static inline unsigned int
900 : : rte_popcount64(uint64_t v)
901 : : {
902 : : return (unsigned int)__popcnt64(v);
903 : : }
904 : :
905 : : /**
906 : : * @warning
907 : : * @b EXPERIMENTAL: this API may change without prior notice.
908 : : *
909 : : * Search v from least significant bit (LSB) to the most
910 : : * significant bit (MSB) for a set bit (1).
911 : : *
912 : : * @param v
913 : : * The value.
914 : : * @return
915 : : * Bit index + 1 if a set bit is found, zero otherwise.
916 : : */
917 : : __rte_experimental
918 : : static inline unsigned int
919 : : rte_ffs32(uint32_t v)
920 : : {
921 : : unsigned long rv;
922 : :
923 : : if (_BitScanForward(&rv, v) == 0)
924 : : return 0;
925 : :
926 : : return (unsigned int)rv + 1;
927 : : }
928 : :
929 : : /**
930 : : * @warning
931 : : * @b EXPERIMENTAL: this API may change without prior notice.
932 : : *
933 : : * Search v from least significant bit (LSB) to the most
934 : : * significant bit (MSB) for a set bit (1).
935 : : *
936 : : * @param v
937 : : * The value.
938 : : * @return
939 : : * Bit index + 1 if a set bit is found, zero otherwise.
940 : : */
941 : : __rte_experimental
942 : : static inline unsigned int
943 : : rte_ffs64(uint64_t v)
944 : : {
945 : : unsigned long rv;
946 : :
947 : : if (_BitScanForward64(&rv, v) == 0)
948 : : return 0;
949 : :
950 : : return (unsigned int)rv + 1;
951 : : }
952 : :
953 : : #else
954 : :
955 : : /**
956 : : * Get the count of leading 0-bits in v.
957 : : *
958 : : * @param v
959 : : * The value.
960 : : * @return
961 : : * The count of leading zero bits.
962 : : */
963 : : static inline unsigned int
964 : : rte_clz32(uint32_t v)
965 : : {
966 [ + + ]: 3285388 : return (unsigned int)__builtin_clz(v);
967 : : }
968 : :
969 : : /**
970 : : * Get the count of leading 0-bits in v.
971 : : *
972 : : * @param v
973 : : * The value.
974 : : * @return
975 : : * The count of leading zero bits.
976 : : */
977 : : static inline unsigned int
978 : : rte_clz64(uint64_t v)
979 : : {
980 [ + + + + : 6645085 : return (unsigned int)__builtin_clzll(v);
+ + ]
981 : : }
982 : :
983 : : /**
984 : : * Get the count of trailing 0-bits in v.
985 : : *
986 : : * @param v
987 : : * The value.
988 : : * @return
989 : : * The count of trailing zero bits.
990 : : */
991 : : static inline unsigned int
992 : 0 : rte_ctz32(uint32_t v)
993 : : {
994 [ + + - + : 110687912 : return (unsigned int)__builtin_ctz(v);
+ + - - +
- ]
995 : : }
996 : :
997 : : /**
998 : : * Get the count of trailing 0-bits in v.
999 : : *
1000 : : * @param v
1001 : : * The value.
1002 : : * @return
1003 : : * The count of trailing zero bits.
1004 : : */
1005 : : static inline unsigned int
1006 : 8 : rte_ctz64(uint64_t v)
1007 : : {
1008 [ + + + + : 20773614 : return (unsigned int)__builtin_ctzll(v);
+ + - - -
- + - + -
- - - + ]
1009 : : }
1010 : :
1011 : : /**
1012 : : * Get the count of 1-bits in v.
1013 : : *
1014 : : * @param v
1015 : : * The value.
1016 : : * @return
1017 : : * The count of 1-bits.
1018 : : */
1019 : : static inline unsigned int
1020 : : rte_popcount32(uint32_t v)
1021 : : {
1022 [ + + + + : 2646710 : return (unsigned int)__builtin_popcount(v);
# # # # #
# ]
1023 : : }
1024 : :
1025 : : /**
1026 : : * Get the count of 1-bits in v.
1027 : : *
1028 : : * @param v
1029 : : * The value.
1030 : : * @return
1031 : : * The count of 1-bits.
1032 : : */
1033 : : static inline unsigned int
1034 : 0 : rte_popcount64(uint64_t v)
1035 : : {
1036 [ + + - + : 67825378 : return (unsigned int)__builtin_popcountll(v);
# # # # #
# # # # #
# # # # #
# # # #
# ]
1037 : : }
1038 : :
1039 : : /**
1040 : : * @warning
1041 : : * @b EXPERIMENTAL: this API may change without prior notice.
1042 : : *
1043 : : * Search v from least significant bit (LSB) to the most
1044 : : * significant bit (MSB) for a set bit (1).
1045 : : *
1046 : : * @param v
1047 : : * The value.
1048 : : * @return
1049 : : * Bit index + 1 if a set bit is found, zero otherwise.
1050 : : */
1051 : : __rte_experimental
1052 : : static inline unsigned int
1053 : : rte_ffs32(uint32_t v)
1054 : : {
1055 [ - + # # : 32 : return (unsigned int)__builtin_ffs(v);
# # # #
# ]
1056 : : }
1057 : :
1058 : : /**
1059 : : * @warning
1060 : : * @b EXPERIMENTAL: this API may change without prior notice.
1061 : : *
1062 : : * Search v from least significant bit (LSB) to the most
1063 : : * significant bit (MSB) for a set bit (1).
1064 : : *
1065 : : * @param v
1066 : : * The value.
1067 : : * @return
1068 : : * Bit index + 1 if a set bit is found, zero otherwise.
1069 : : */
1070 : : __rte_experimental
1071 : : static inline unsigned int
1072 : : rte_ffs64(uint64_t v)
1073 : : {
1074 [ - + ]: 64 : return (unsigned int)__builtin_ffsll(v);
1075 : : }
1076 : :
1077 : : #endif
1078 : :
1079 : : /**
1080 : : * Combines 32b inputs most significant set bits into the least
1081 : : * significant bits to construct a value with the same MSBs as x
1082 : : * but all 1's under it.
1083 : : *
1084 : : * @param x
1085 : : * The integer whose MSBs need to be combined with its LSBs
1086 : : * @return
1087 : : * The combined value.
1088 : : */
1089 : : static inline uint32_t
1090 : 0 : rte_combine32ms1b(uint32_t x)
1091 : : {
1092 : 2164300 : x |= x >> 1;
1093 : 2164300 : x |= x >> 2;
1094 : 2164300 : x |= x >> 4;
1095 : 2164300 : x |= x >> 8;
1096 : 2164300 : x |= x >> 16;
1097 : :
1098 : 0 : return x;
1099 : : }
1100 : :
1101 : : /**
1102 : : * Combines 64b inputs most significant set bits into the least
1103 : : * significant bits to construct a value with the same MSBs as x
1104 : : * but all 1's under it.
1105 : : *
1106 : : * @param v
1107 : : * The integer whose MSBs need to be combined with its LSBs
1108 : : * @return
1109 : : * The combined value.
1110 : : */
1111 : : static inline uint64_t
1112 : : rte_combine64ms1b(uint64_t v)
1113 : : {
1114 : 2228284 : v |= v >> 1;
1115 : 2228284 : v |= v >> 2;
1116 : 2228284 : v |= v >> 4;
1117 : 2228284 : v |= v >> 8;
1118 : 2228284 : v |= v >> 16;
1119 : 2228284 : v |= v >> 32;
1120 : :
1121 : : return v;
1122 : : }
1123 : :
1124 : : /**
1125 : : * Searches the input parameter for the least significant set bit
1126 : : * (starting from zero).
1127 : : * If a least significant 1 bit is found, its bit index is returned.
1128 : : * If the content of the input parameter is zero, then the content of the return
1129 : : * value is undefined.
1130 : : * @param v
1131 : : * input parameter, should not be zero.
1132 : : * @return
1133 : : * least significant set bit in the input parameter.
1134 : : */
1135 : : static inline uint32_t
1136 : 0 : rte_bsf32(uint32_t v)
1137 : : {
1138 : 0 : return (uint32_t)rte_ctz32(v);
1139 : : }
1140 : :
1141 : : /**
1142 : : * Searches the input parameter for the least significant set bit
1143 : : * (starting from zero). Safe version (checks for input parameter being zero).
1144 : : *
1145 : : * @warning ``pos`` must be a valid pointer. It is not checked!
1146 : : *
1147 : : * @param v
1148 : : * The input parameter.
1149 : : * @param pos
1150 : : * If ``v`` was not 0, this value will contain position of least significant
1151 : : * bit within the input parameter.
1152 : : * @return
1153 : : * Returns 0 if ``v`` was 0, otherwise returns 1.
1154 : : */
1155 : : static inline int
1156 : : rte_bsf32_safe(uint32_t v, uint32_t *pos)
1157 : : {
1158 : : if (v == 0)
1159 : : return 0;
1160 : :
1161 : : *pos = rte_bsf32(v);
1162 : : return 1;
1163 : : }
1164 : :
1165 : : /**
1166 : : * Searches the input parameter for the least significant set bit
1167 : : * (starting from zero).
1168 : : * If a least significant 1 bit is found, its bit index is returned.
1169 : : * If the content of the input parameter is zero, then the content of the return
1170 : : * value is undefined.
1171 : : * @param v
1172 : : * input parameter, should not be zero.
1173 : : * @return
1174 : : * least significant set bit in the input parameter.
1175 : : */
1176 : : static inline uint32_t
1177 : : rte_bsf64(uint64_t v)
1178 : : {
1179 : : return (uint32_t)rte_ctz64(v);
1180 : : }
1181 : :
1182 : : /**
1183 : : * Searches the input parameter for the least significant set bit
1184 : : * (starting from zero). Safe version (checks for input parameter being zero).
1185 : : *
1186 : : * @warning ``pos`` must be a valid pointer. It is not checked!
1187 : : *
1188 : : * @param v
1189 : : * The input parameter.
1190 : : * @param pos
1191 : : * If ``v`` was not 0, this value will contain position of least significant
1192 : : * bit within the input parameter.
1193 : : * @return
1194 : : * Returns 0 if ``v`` was 0, otherwise returns 1.
1195 : : */
1196 : : static inline int
1197 : : rte_bsf64_safe(uint64_t v, uint32_t *pos)
1198 : : {
1199 [ + + + + : 2823 : if (v == 0)
+ + ]
1200 : : return 0;
1201 : :
1202 : 220 : *pos = rte_bsf64(v);
1203 : : return 1;
1204 : : }
1205 : :
1206 : : /**
1207 : : * Return the last (most-significant) bit set.
1208 : : *
1209 : : * @note The last (most significant) bit is at position 32.
1210 : : * @note rte_fls_u32(0) = 0, rte_fls_u32(1) = 1, rte_fls_u32(0x80000000) = 32
1211 : : *
1212 : : * @param x
1213 : : * The input parameter.
1214 : : * @return
1215 : : * The last (most-significant) bit set, or 0 if the input is 0.
1216 : : */
1217 : : static inline uint32_t
1218 : : rte_fls_u32(uint32_t x)
1219 : : {
1220 [ + + # # : 5 : return (x == 0) ? 0 : 32 - rte_clz32(x);
# # ]
1221 : : }
1222 : :
1223 : : /**
1224 : : * Return the last (most-significant) bit set.
1225 : : *
1226 : : * @note The last (most significant) bit is at position 64.
1227 : : * @note rte_fls_u64(0) = 0, rte_fls_u64(1) = 1,
1228 : : * rte_fls_u64(0x8000000000000000) = 64
1229 : : *
1230 : : * @param x
1231 : : * The input parameter.
1232 : : * @return
1233 : : * The last (most-significant) bit set, or 0 if the input is 0.
1234 : : */
1235 : : static inline uint32_t
1236 : : rte_fls_u64(uint64_t x)
1237 : : {
1238 [ + + + + : 1369 : return (x == 0) ? 0 : 64 - rte_clz64(x);
+ + + - ]
1239 : : }
1240 : :
1241 : : /*********** Macros to work with powers of 2 ********/
1242 : :
1243 : : /**
1244 : : * Macro to return 1 if n is a power of 2, 0 otherwise
1245 : : */
1246 : : #define RTE_IS_POWER_OF_2(n) ((n) != 0 && (((n) - 1) & (n)) == 0)
1247 : :
1248 : : /**
1249 : : * Returns true if n is a power of 2
1250 : : * @param n
1251 : : * Number to check
1252 : : * @return 1 if true, 0 otherwise
1253 : : */
1254 : : static inline int
1255 : 0 : rte_is_power_of_2(uint32_t n)
1256 : : {
1257 [ + + + + : 2388512 : return n && !(n & (n - 1));
+ + + + #
# # # # #
# # # # #
# ]
1258 : : }
1259 : :
1260 : : /**
1261 : : * Aligns input parameter to the next power of 2
1262 : : *
1263 : : * @param x
1264 : : * The integer value to align
1265 : : *
1266 : : * @return
1267 : : * The smallest power of 2 which is greater than or equal to @c x.
1268 : : */
1269 : : static inline uint32_t
1270 : 0 : rte_align32pow2(uint32_t x)
1271 : : {
1272 : 1115062 : x--;
1273 : 0 : x = rte_combine32ms1b(x);
1274 : :
1275 [ + + - + : 1115712 : return x + 1;
# # ]
1276 : : }
1277 : :
1278 : : /**
1279 : : * Aligns input parameter to the previous power of 2
1280 : : *
1281 : : * @param x
1282 : : * The integer value to align
1283 : : *
1284 : : * @return
1285 : : * The greatest power of 2 which is smaller than or equal to @c x.
1286 : : */
1287 : : static inline uint32_t
1288 : : rte_align32prevpow2(uint32_t x)
1289 : : {
1290 : : x = rte_combine32ms1b(x);
1291 : :
1292 [ - + ]: 1048576 : return x - (x >> 1);
1293 : : }
1294 : :
1295 : : /**
1296 : : * Aligns 64b input parameter to the next power of 2
1297 : : *
1298 : : * @param v
1299 : : * The 64b value to align
1300 : : *
1301 : : * @return
1302 : : * The smallest power of 2 which is greater than or equal to @c v.
1303 : : */
1304 : : static inline uint64_t
1305 : : rte_align64pow2(uint64_t v)
1306 : : {
1307 : 1179706 : v--;
1308 : : v = rte_combine64ms1b(v);
1309 : :
1310 [ - + - + : 1179708 : return v + 1;
- + ]
1311 : : }
1312 : :
1313 : : /**
1314 : : * Aligns 64b input parameter to the previous power of 2
1315 : : *
1316 : : * @param v
1317 : : * The 64b value to align
1318 : : *
1319 : : * @return
1320 : : * The greatest power of 2 which is smaller than or equal to @c v.
1321 : : */
1322 : : static inline uint64_t
1323 : : rte_align64prevpow2(uint64_t v)
1324 : : {
1325 : : v = rte_combine64ms1b(v);
1326 : :
1327 [ - + ]: 1048576 : return v - (v >> 1);
1328 : : }
1329 : :
1330 : : /**
1331 : : * Return the rounded-up log2 of a integer.
1332 : : *
1333 : : * @note Contrary to the logarithm mathematical operation,
1334 : : * rte_log2_u32(0) == 0 and not -inf.
1335 : : *
1336 : : * @param v
1337 : : * The input parameter.
1338 : : * @return
1339 : : * The rounded-up log2 of the input, or 0 if the input is 0.
1340 : : */
1341 : : static inline uint32_t
1342 : 0 : rte_log2_u32(uint32_t v)
1343 : : {
1344 [ # # # # : 0 : if (v == 0)
# # # # #
# # # #
# ]
1345 : : return 0;
1346 : 0 : v = rte_align32pow2(v);
1347 : 0 : return rte_bsf32(v);
1348 : : }
1349 : :
1350 : : /**
1351 : : * Return the rounded-up log2 of a 64-bit integer.
1352 : : *
1353 : : * @note Contrary to the logarithm mathematical operation,
1354 : : * rte_log2_u64(0) == 0 and not -inf.
1355 : : *
1356 : : * @param v
1357 : : * The input parameter.
1358 : : * @return
1359 : : * The rounded-up log2 of the input, or 0 if the input is 0.
1360 : : */
1361 : : static inline uint32_t
1362 : : rte_log2_u64(uint64_t v)
1363 : : {
1364 [ + - ]: 60 : if (v == 0)
1365 : : return 0;
1366 : : v = rte_align64pow2(v);
1367 : : /* we checked for v being 0 already, so no undefined behavior */
1368 : 60 : return rte_bsf64(v);
1369 : : }
1370 : :
1371 : : #ifdef __cplusplus
1372 : : }
1373 : :
1374 : : /*
1375 : : * Since C++ doesn't support generic selection (i.e., _Generic),
1376 : : * function overloading is used instead. Such functions must be
1377 : : * defined outside 'extern "C"' to be accepted by the compiler.
1378 : : */
1379 : :
1380 : : #undef rte_bit_test
1381 : : #undef rte_bit_set
1382 : : #undef rte_bit_clear
1383 : : #undef rte_bit_assign
1384 : : #undef rte_bit_flip
1385 : :
1386 : : #undef rte_bit_atomic_test
1387 : : #undef rte_bit_atomic_set
1388 : : #undef rte_bit_atomic_clear
1389 : : #undef rte_bit_atomic_assign
1390 : : #undef rte_bit_atomic_flip
1391 : : #undef rte_bit_atomic_test_and_set
1392 : : #undef rte_bit_atomic_test_and_clear
1393 : : #undef rte_bit_atomic_test_and_assign
1394 : :
1395 : : #define __RTE_BIT_OVERLOAD_V_2(family, v, fun, qualifier, size, arg1_type, arg1_name) \
1396 : : static inline void \
1397 : : rte_bit_ ## family ## fun(qualifier uint ## size ## _t *addr, arg1_type arg1_name) \
1398 : : { \
1399 : : __rte_bit_ ## family ## v ## fun ## size(addr, arg1_name); \
1400 : : }
1401 : :
1402 : : #define __RTE_BIT_OVERLOAD_SZ_2(family, fun, qualifier, size, arg1_type, arg1_name) \
1403 : : __RTE_BIT_OVERLOAD_V_2(family,, fun, qualifier, size, arg1_type, arg1_name) \
1404 : : __RTE_BIT_OVERLOAD_V_2(family, v_, fun, qualifier volatile, size, arg1_type, arg1_name)
1405 : :
1406 : : #define __RTE_BIT_OVERLOAD_2(family, fun, qualifier, arg1_type, arg1_name) \
1407 : : __RTE_BIT_OVERLOAD_SZ_2(family, fun, qualifier, 32, arg1_type, arg1_name) \
1408 : : __RTE_BIT_OVERLOAD_SZ_2(family, fun, qualifier, 64, arg1_type, arg1_name)
1409 : :
1410 : : #define __RTE_BIT_OVERLOAD_V_2R(family, v, fun, qualifier, size, ret_type, arg1_type, arg1_name) \
1411 : : static inline ret_type \
1412 : : rte_bit_ ## family ## fun(qualifier uint ## size ## _t *addr, arg1_type arg1_name) \
1413 : : { \
1414 : : return __rte_bit_ ## family ## v ## fun ## size(addr, arg1_name); \
1415 : : }
1416 : :
1417 : : #define __RTE_BIT_OVERLOAD_SZ_2R(family, fun, qualifier, size, ret_type, arg1_type, arg1_name) \
1418 : : __RTE_BIT_OVERLOAD_V_2R(family,, fun, qualifier, size, ret_type, arg1_type, arg1_name) \
1419 : : __RTE_BIT_OVERLOAD_V_2R(family, v_, fun, qualifier volatile, size, ret_type, arg1_type, \
1420 : : arg1_name)
1421 : :
1422 : : #define __RTE_BIT_OVERLOAD_2R(family, fun, qualifier, ret_type, arg1_type, arg1_name) \
1423 : : __RTE_BIT_OVERLOAD_SZ_2R(family, fun, qualifier, 32, ret_type, arg1_type, arg1_name) \
1424 : : __RTE_BIT_OVERLOAD_SZ_2R(family, fun, qualifier, 64, ret_type, arg1_type, arg1_name)
1425 : :
1426 : : #define __RTE_BIT_OVERLOAD_V_3(family, v, fun, qualifier, size, arg1_type, arg1_name, \
1427 : : arg2_type, arg2_name) \
1428 : : static inline void \
1429 : : rte_bit_ ## family ## fun(qualifier uint ## size ## _t *addr, arg1_type arg1_name, \
1430 : : arg2_type arg2_name) \
1431 : : { \
1432 : : __rte_bit_ ## family ## v ## fun ## size(addr, arg1_name, arg2_name); \
1433 : : }
1434 : :
1435 : : #define __RTE_BIT_OVERLOAD_SZ_3(family, fun, qualifier, size, arg1_type, arg1_name, \
1436 : : arg2_type, arg2_name) \
1437 : : __RTE_BIT_OVERLOAD_V_3(family,, fun, qualifier, size, arg1_type, arg1_name, \
1438 : : arg2_type, arg2_name) \
1439 : : __RTE_BIT_OVERLOAD_V_3(family, v_, fun, qualifier volatile, size, arg1_type, arg1_name, \
1440 : : arg2_type, arg2_name)
1441 : :
1442 : : #define __RTE_BIT_OVERLOAD_3(family, fun, qualifier, arg1_type, arg1_name, arg2_type, arg2_name) \
1443 : : __RTE_BIT_OVERLOAD_SZ_3(family, fun, qualifier, 32, arg1_type, arg1_name, \
1444 : : arg2_type, arg2_name) \
1445 : : __RTE_BIT_OVERLOAD_SZ_3(family, fun, qualifier, 64, arg1_type, arg1_name, \
1446 : : arg2_type, arg2_name)
1447 : :
1448 : : #define __RTE_BIT_OVERLOAD_V_3R(family, v, fun, qualifier, size, ret_type, arg1_type, arg1_name, \
1449 : : arg2_type, arg2_name) \
1450 : : static inline ret_type \
1451 : : rte_bit_ ## family ## fun(qualifier uint ## size ## _t *addr, arg1_type arg1_name, \
1452 : : arg2_type arg2_name) \
1453 : : { \
1454 : : return __rte_bit_ ## family ## v ## fun ## size(addr, arg1_name, arg2_name); \
1455 : : }
1456 : :
1457 : : #define __RTE_BIT_OVERLOAD_SZ_3R(family, fun, qualifier, size, ret_type, arg1_type, arg1_name, \
1458 : : arg2_type, arg2_name) \
1459 : : __RTE_BIT_OVERLOAD_V_3R(family,, fun, qualifier, size, ret_type, arg1_type, arg1_name, \
1460 : : arg2_type, arg2_name) \
1461 : : __RTE_BIT_OVERLOAD_V_3R(family, v_, fun, qualifier volatile, size, ret_type, \
1462 : : arg1_type, arg1_name, arg2_type, arg2_name)
1463 : :
1464 : : #define __RTE_BIT_OVERLOAD_3R(family, fun, qualifier, ret_type, arg1_type, arg1_name, \
1465 : : arg2_type, arg2_name) \
1466 : : __RTE_BIT_OVERLOAD_SZ_3R(family, fun, qualifier, 32, ret_type, arg1_type, arg1_name, \
1467 : : arg2_type, arg2_name) \
1468 : : __RTE_BIT_OVERLOAD_SZ_3R(family, fun, qualifier, 64, ret_type, arg1_type, arg1_name, \
1469 : : arg2_type, arg2_name)
1470 : :
1471 : : #define __RTE_BIT_OVERLOAD_V_4(family, v, fun, qualifier, size, arg1_type, arg1_name, \
1472 : : arg2_type, arg2_name, arg3_type, arg3_name) \
1473 : : static inline void \
1474 : : rte_bit_ ## family ## fun(qualifier uint ## size ## _t *addr, arg1_type arg1_name, \
1475 : : arg2_type arg2_name, arg3_type arg3_name) \
1476 : : { \
1477 : : __rte_bit_ ## family ## v ## fun ## size(addr, arg1_name, arg2_name, arg3_name); \
1478 : : }
1479 : :
1480 : : #define __RTE_BIT_OVERLOAD_SZ_4(family, fun, qualifier, size, arg1_type, arg1_name, \
1481 : : arg2_type, arg2_name, arg3_type, arg3_name) \
1482 : : __RTE_BIT_OVERLOAD_V_4(family,, fun, qualifier, size, arg1_type, arg1_name, \
1483 : : arg2_type, arg2_name, arg3_type, arg3_name) \
1484 : : __RTE_BIT_OVERLOAD_V_4(family, v_, fun, qualifier volatile, size, arg1_type, arg1_name, \
1485 : : arg2_type, arg2_name, arg3_type, arg3_name)
1486 : :
1487 : : #define __RTE_BIT_OVERLOAD_4(family, fun, qualifier, arg1_type, arg1_name, arg2_type, arg2_name, \
1488 : : arg3_type, arg3_name) \
1489 : : __RTE_BIT_OVERLOAD_SZ_4(family, fun, qualifier, 32, arg1_type, arg1_name, \
1490 : : arg2_type, arg2_name, arg3_type, arg3_name) \
1491 : : __RTE_BIT_OVERLOAD_SZ_4(family, fun, qualifier, 64, arg1_type, arg1_name, \
1492 : : arg2_type, arg2_name, arg3_type, arg3_name)
1493 : :
1494 : : #define __RTE_BIT_OVERLOAD_V_4R(family, v, fun, qualifier, size, ret_type, arg1_type, arg1_name, \
1495 : : arg2_type, arg2_name, arg3_type, arg3_name) \
1496 : : static inline ret_type \
1497 : : rte_bit_ ## family ## fun(qualifier uint ## size ## _t *addr, arg1_type arg1_name, \
1498 : : arg2_type arg2_name, arg3_type arg3_name) \
1499 : : { \
1500 : : return __rte_bit_ ## family ## v ## fun ## size(addr, arg1_name, arg2_name, \
1501 : : arg3_name); \
1502 : : }
1503 : :
1504 : : #define __RTE_BIT_OVERLOAD_SZ_4R(family, fun, qualifier, size, ret_type, arg1_type, arg1_name, \
1505 : : arg2_type, arg2_name, arg3_type, arg3_name) \
1506 : : __RTE_BIT_OVERLOAD_V_4R(family,, fun, qualifier, size, ret_type, arg1_type, arg1_name, \
1507 : : arg2_type, arg2_name, arg3_type, arg3_name) \
1508 : : __RTE_BIT_OVERLOAD_V_4R(family, v_, fun, qualifier volatile, size, ret_type, \
1509 : : arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name)
1510 : :
1511 : : #define __RTE_BIT_OVERLOAD_4R(family, fun, qualifier, ret_type, arg1_type, arg1_name, \
1512 : : arg2_type, arg2_name, arg3_type, arg3_name) \
1513 : : __RTE_BIT_OVERLOAD_SZ_4R(family, fun, qualifier, 32, ret_type, arg1_type, arg1_name, \
1514 : : arg2_type, arg2_name, arg3_type, arg3_name) \
1515 : : __RTE_BIT_OVERLOAD_SZ_4R(family, fun, qualifier, 64, ret_type, arg1_type, arg1_name, \
1516 : : arg2_type, arg2_name, arg3_type, arg3_name)
1517 : :
1518 : : __RTE_BIT_OVERLOAD_2R(, test, const, bool, unsigned int, nr)
1519 : : __RTE_BIT_OVERLOAD_2(, set,, unsigned int, nr)
1520 : : __RTE_BIT_OVERLOAD_2(, clear,, unsigned int, nr)
1521 : : __RTE_BIT_OVERLOAD_3(, assign,, unsigned int, nr, bool, value)
1522 : : __RTE_BIT_OVERLOAD_2(, flip,, unsigned int, nr)
1523 : :
1524 : : __RTE_BIT_OVERLOAD_3R(atomic_, test, const, bool, unsigned int, nr, int, memory_order)
1525 : : __RTE_BIT_OVERLOAD_3(atomic_, set,, unsigned int, nr, int, memory_order)
1526 : : __RTE_BIT_OVERLOAD_3(atomic_, clear,, unsigned int, nr, int, memory_order)
1527 : : __RTE_BIT_OVERLOAD_4(atomic_, assign,, unsigned int, nr, bool, value, int, memory_order)
1528 : : __RTE_BIT_OVERLOAD_3(atomic_, flip,, unsigned int, nr, int, memory_order)
1529 : : __RTE_BIT_OVERLOAD_3R(atomic_, test_and_set,, bool, unsigned int, nr, int, memory_order)
1530 : : __RTE_BIT_OVERLOAD_3R(atomic_, test_and_clear,, bool, unsigned int, nr, int, memory_order)
1531 : : __RTE_BIT_OVERLOAD_4R(atomic_, test_and_assign,, bool, unsigned int, nr, bool, value,
1532 : : int, memory_order)
1533 : :
1534 : : #endif
1535 : :
1536 : : #endif /* _RTE_BITOPS_H_ */
|