DPDK  23.11.1
rte_bitops.h
Go to the documentation of this file.
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  */
6 
7 #ifndef _RTE_BITOPS_H_
8 #define _RTE_BITOPS_H_
9 
18 #include <stdint.h>
19 
20 #include <rte_debug.h>
21 
22 #ifdef __cplusplus
23 extern "C" {
24 #endif
25 
32 #define RTE_BIT64(nr) (UINT64_C(1) << (nr))
33 
40 #define RTE_BIT32(nr) (UINT32_C(1) << (nr))
41 
42 /*------------------------ 32-bit relaxed operations ------------------------*/
43 
54 static inline uint32_t
55 rte_bit_relaxed_get32(unsigned int nr, volatile uint32_t *addr)
56 {
57  RTE_ASSERT(nr < 32);
58 
59  uint32_t mask = UINT32_C(1) << nr;
60  return (*addr) & mask;
61 }
62 
71 static inline void
72 rte_bit_relaxed_set32(unsigned int nr, volatile uint32_t *addr)
73 {
74  RTE_ASSERT(nr < 32);
75 
76  uint32_t mask = RTE_BIT32(nr);
77  *addr = (*addr) | mask;
78 }
79 
88 static inline void
89 rte_bit_relaxed_clear32(unsigned int nr, volatile uint32_t *addr)
90 {
91  RTE_ASSERT(nr < 32);
92 
93  uint32_t mask = RTE_BIT32(nr);
94  *addr = (*addr) & (~mask);
95 }
96 
108 static inline uint32_t
109 rte_bit_relaxed_test_and_set32(unsigned int nr, volatile uint32_t *addr)
110 {
111  RTE_ASSERT(nr < 32);
112 
113  uint32_t mask = RTE_BIT32(nr);
114  uint32_t val = *addr;
115  *addr = val | mask;
116  return val & mask;
117 }
118 
130 static inline uint32_t
131 rte_bit_relaxed_test_and_clear32(unsigned int nr, volatile uint32_t *addr)
132 {
133  RTE_ASSERT(nr < 32);
134 
135  uint32_t mask = RTE_BIT32(nr);
136  uint32_t val = *addr;
137  *addr = val & (~mask);
138  return val & mask;
139 }
140 
141 /*------------------------ 64-bit relaxed operations ------------------------*/
142 
153 static inline uint64_t
154 rte_bit_relaxed_get64(unsigned int nr, volatile uint64_t *addr)
155 {
156  RTE_ASSERT(nr < 64);
157 
158  uint64_t mask = RTE_BIT64(nr);
159  return (*addr) & mask;
160 }
161 
170 static inline void
171 rte_bit_relaxed_set64(unsigned int nr, volatile uint64_t *addr)
172 {
173  RTE_ASSERT(nr < 64);
174 
175  uint64_t mask = RTE_BIT64(nr);
176  (*addr) = (*addr) | mask;
177 }
178 
187 static inline void
188 rte_bit_relaxed_clear64(unsigned int nr, volatile uint64_t *addr)
189 {
190  RTE_ASSERT(nr < 64);
191 
192  uint64_t mask = RTE_BIT64(nr);
193  *addr = (*addr) & (~mask);
194 }
195 
207 static inline uint64_t
208 rte_bit_relaxed_test_and_set64(unsigned int nr, volatile uint64_t *addr)
209 {
210  RTE_ASSERT(nr < 64);
211 
212  uint64_t mask = RTE_BIT64(nr);
213  uint64_t val = *addr;
214  *addr = val | mask;
215  return val;
216 }
217 
229 static inline uint64_t
230 rte_bit_relaxed_test_and_clear64(unsigned int nr, volatile uint64_t *addr)
231 {
232  RTE_ASSERT(nr < 64);
233 
234  uint64_t mask = RTE_BIT64(nr);
235  uint64_t val = *addr;
236  *addr = val & (~mask);
237  return val & mask;
238 }
239 
240 #ifdef RTE_TOOLCHAIN_MSVC
241 
250 static inline unsigned int
251 rte_clz32(uint32_t v)
252 {
253  unsigned long rv;
254 
255  (void)_BitScanReverse(&rv, v);
256 
257  return (unsigned int)(sizeof(v) * CHAR_BIT - 1 - rv);
258 }
259 
268 static inline unsigned int
269 rte_clz64(uint64_t v)
270 {
271  unsigned long rv;
272 
273  (void)_BitScanReverse64(&rv, v);
274 
275  return (unsigned int)(sizeof(v) * CHAR_BIT - 1 - rv);
276 }
277 
286 static inline unsigned int
287 rte_ctz32(uint32_t v)
288 {
289  unsigned long rv;
290 
291  (void)_BitScanForward(&rv, v);
292 
293  return (unsigned int)rv;
294 }
295 
304 static inline unsigned int
305 rte_ctz64(uint64_t v)
306 {
307  unsigned long rv;
308 
309  (void)_BitScanForward64(&rv, v);
310 
311  return (unsigned int)rv;
312 }
313 
322 static inline unsigned int
323 rte_popcount32(uint32_t v)
324 {
325  return (unsigned int)__popcnt(v);
326 }
327 
336 static inline unsigned int
337 rte_popcount64(uint64_t v)
338 {
339  return (unsigned int)__popcnt64(v);
340 }
341 
342 #else
343 
352 static inline unsigned int
353 rte_clz32(uint32_t v)
354 {
355  return (unsigned int)__builtin_clz(v);
356 }
357 
366 static inline unsigned int
367 rte_clz64(uint64_t v)
368 {
369  return (unsigned int)__builtin_clzll(v);
370 }
371 
380 static inline unsigned int
381 rte_ctz32(uint32_t v)
382 {
383  return (unsigned int)__builtin_ctz(v);
384 }
385 
394 static inline unsigned int
395 rte_ctz64(uint64_t v)
396 {
397  return (unsigned int)__builtin_ctzll(v);
398 }
399 
408 static inline unsigned int
409 rte_popcount32(uint32_t v)
410 {
411  return (unsigned int)__builtin_popcount(v);
412 }
413 
422 static inline unsigned int
423 rte_popcount64(uint64_t v)
424 {
425  return (unsigned int)__builtin_popcountll(v);
426 }
427 
428 #endif
429 
440 static inline uint32_t
441 rte_combine32ms1b(uint32_t x)
442 {
443  x |= x >> 1;
444  x |= x >> 2;
445  x |= x >> 4;
446  x |= x >> 8;
447  x |= x >> 16;
448 
449  return x;
450 }
451 
462 static inline uint64_t
463 rte_combine64ms1b(uint64_t v)
464 {
465  v |= v >> 1;
466  v |= v >> 2;
467  v |= v >> 4;
468  v |= v >> 8;
469  v |= v >> 16;
470  v |= v >> 32;
471 
472  return v;
473 }
474 
486 static inline uint32_t
487 rte_bsf32(uint32_t v)
488 {
489  return (uint32_t)rte_ctz32(v);
490 }
491 
506 static inline int
507 rte_bsf32_safe(uint32_t v, uint32_t *pos)
508 {
509  if (v == 0)
510  return 0;
511 
512  *pos = rte_bsf32(v);
513  return 1;
514 }
515 
527 static inline uint32_t
528 rte_bsf64(uint64_t v)
529 {
530  return (uint32_t)rte_ctz64(v);
531 }
532 
547 static inline int
548 rte_bsf64_safe(uint64_t v, uint32_t *pos)
549 {
550  if (v == 0)
551  return 0;
552 
553  *pos = rte_bsf64(v);
554  return 1;
555 }
556 
568 static inline uint32_t
569 rte_fls_u32(uint32_t x)
570 {
571  return (x == 0) ? 0 : 32 - rte_clz32(x);
572 }
573 
586 static inline uint32_t
587 rte_fls_u64(uint64_t x)
588 {
589  return (x == 0) ? 0 : 64 - rte_clz64(x);
590 }
591 
592 /*********** Macros to work with powers of 2 ********/
593 
597 #define RTE_IS_POWER_OF_2(n) ((n) && !(((n) - 1) & (n)))
598 
605 static inline int
606 rte_is_power_of_2(uint32_t n)
607 {
608  return n && !(n & (n - 1));
609 }
610 
620 static inline uint32_t
621 rte_align32pow2(uint32_t x)
622 {
623  x--;
624  x = rte_combine32ms1b(x);
625 
626  return x + 1;
627 }
628 
638 static inline uint32_t
640 {
641  x = rte_combine32ms1b(x);
642 
643  return x - (x >> 1);
644 }
645 
655 static inline uint64_t
656 rte_align64pow2(uint64_t v)
657 {
658  v--;
659  v = rte_combine64ms1b(v);
660 
661  return v + 1;
662 }
663 
673 static inline uint64_t
675 {
676  v = rte_combine64ms1b(v);
677 
678  return v - (v >> 1);
679 }
680 
692 static inline uint32_t
693 rte_log2_u32(uint32_t v)
694 {
695  if (v == 0)
696  return 0;
697  v = rte_align32pow2(v);
698  return rte_bsf32(v);
699 }
700 
712 static inline uint32_t
713 rte_log2_u64(uint64_t v)
714 {
715  if (v == 0)
716  return 0;
717  v = rte_align64pow2(v);
718  /* we checked for v being 0 already, so no undefined behavior */
719  return rte_bsf64(v);
720 }
721 
722 #ifdef __cplusplus
723 }
724 #endif
725 
726 #endif /* _RTE_BITOPS_H_ */
static int rte_bsf32_safe(uint32_t v, uint32_t *pos)
Definition: rte_bitops.h:507
static void rte_bit_relaxed_clear64(unsigned int nr, volatile uint64_t *addr)
Definition: rte_bitops.h:188
static void rte_bit_relaxed_clear32(unsigned int nr, volatile uint32_t *addr)
Definition: rte_bitops.h:89
static unsigned int rte_popcount32(uint32_t v)
Definition: rte_bitops.h:409
static uint32_t rte_bit_relaxed_test_and_set32(unsigned int nr, volatile uint32_t *addr)
Definition: rte_bitops.h:109
static uint32_t rte_bit_relaxed_test_and_clear32(unsigned int nr, volatile uint32_t *addr)
Definition: rte_bitops.h:131
static unsigned int rte_clz32(uint32_t v)
Definition: rte_bitops.h:353
static uint32_t rte_bsf32(uint32_t v)
Definition: rte_bitops.h:487
static void rte_bit_relaxed_set32(unsigned int nr, volatile uint32_t *addr)
Definition: rte_bitops.h:72
#define RTE_BIT32(nr)
Definition: rte_bitops.h:40
static uint32_t rte_align32prevpow2(uint32_t x)
Definition: rte_bitops.h:639
static uint32_t rte_fls_u64(uint64_t x)
Definition: rte_bitops.h:587
static uint32_t rte_bsf64(uint64_t v)
Definition: rte_bitops.h:528
static uint32_t rte_align32pow2(uint32_t x)
Definition: rte_bitops.h:621
static uint32_t rte_fls_u32(uint32_t x)
Definition: rte_bitops.h:569
static int rte_is_power_of_2(uint32_t n)
Definition: rte_bitops.h:606
static int rte_bsf64_safe(uint64_t v, uint32_t *pos)
Definition: rte_bitops.h:548
static uint64_t rte_align64prevpow2(uint64_t v)
Definition: rte_bitops.h:674
static uint32_t rte_log2_u32(uint32_t v)
Definition: rte_bitops.h:693
static unsigned int rte_ctz64(uint64_t v)
Definition: rte_bitops.h:395
static uint64_t rte_bit_relaxed_test_and_set64(unsigned int nr, volatile uint64_t *addr)
Definition: rte_bitops.h:208
static unsigned int rte_ctz32(uint32_t v)
Definition: rte_bitops.h:381
static uint64_t rte_align64pow2(uint64_t v)
Definition: rte_bitops.h:656
static uint64_t rte_bit_relaxed_get64(unsigned int nr, volatile uint64_t *addr)
Definition: rte_bitops.h:154
static uint64_t rte_bit_relaxed_test_and_clear64(unsigned int nr, volatile uint64_t *addr)
Definition: rte_bitops.h:230
static uint32_t rte_combine32ms1b(uint32_t x)
Definition: rte_bitops.h:441
static uint64_t rte_combine64ms1b(uint64_t v)
Definition: rte_bitops.h:463
static void rte_bit_relaxed_set64(unsigned int nr, volatile uint64_t *addr)
Definition: rte_bitops.h:171
static unsigned int rte_popcount64(uint64_t v)
Definition: rte_bitops.h:423
static uint32_t rte_bit_relaxed_get32(unsigned int nr, volatile uint32_t *addr)
Definition: rte_bitops.h:55
static unsigned int rte_clz64(uint64_t v)
Definition: rte_bitops.h:367
#define RTE_BIT64(nr)
Definition: rte_bitops.h:32
static uint32_t rte_log2_u64(uint64_t v)
Definition: rte_bitops.h:713