DPDK 26.11.0-rc1
rte_bitset.h
Go to the documentation of this file.
1/* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2023 Ericsson AB
3 */
4
5#ifndef _RTE_BITSET_H_
6#define _RTE_BITSET_H_
7
32#include <limits.h>
33#include <stdbool.h>
34#include <stddef.h>
35#include <stdint.h>
36
37#include <rte_bitops.h>
39#include <rte_common.h>
40#include <rte_compat.h>
41#include <rte_debug.h>
42#include <rte_memcpy.h>
43
44#ifdef __cplusplus
45extern "C" {
46#endif
47
52#define RTE_BITSET_WORD_SIZE (sizeof(uint64_t))
53
58#define RTE_BITSET_WORD_BITS (RTE_BITSET_WORD_SIZE * CHAR_BIT)
59
63#define RTE_BITSET_NUM_WORDS(size) \
64 ((size + RTE_BITSET_WORD_BITS - 1) / RTE_BITSET_WORD_BITS)
65
70#define RTE_BITSET_SIZE(size) \
71 ((size_t)(RTE_BITSET_NUM_WORDS(size) * RTE_BITSET_WORD_SIZE))
72
73#define __RTE_BITSET_WORD_IDX(bit_num) ((bit_num) / RTE_BITSET_WORD_BITS)
74#define __RTE_BITSET_BIT_OFFSET(bit_num) ((bit_num) % RTE_BITSET_WORD_BITS)
75#define __RTE_BITSET_UNUSED(size) \
76 ((RTE_BITSET_NUM_WORDS(size) * RTE_BITSET_WORD_BITS) - (size))
77#define __RTE_BITSET_USED_MASK(size) \
78 (UINT64_MAX >> __RTE_BITSET_UNUSED(size))
79
80#define __RTE_BITSET_DELEGATE_N(fun, bitset, bit_num, ...) \
81 fun(&(bitset)[__RTE_BITSET_WORD_IDX(bit_num)], __RTE_BITSET_BIT_OFFSET(bit_num), \
82 __VA_ARGS__)
83
84/* MSVC doesn't have ##__VA_ARGS__, so argument-less -> special case */
85#define __RTE_BITSET_DELEGATE(fun, bitset, bit_num) \
86 fun(&(bitset)[__RTE_BITSET_WORD_IDX(bit_num)], __RTE_BITSET_BIT_OFFSET(bit_num))
87
100#define RTE_BITSET_DECLARE(name, size) \
101 uint64_t name[RTE_BITSET_NUM_WORDS(size)]
102
103#define __RTE_BITSET_FOREACH_LEFT(var, size, start_bit, len) \
104 ((len) - 1 - ((var) >= (start_bit) ? (var) - (start_bit) : (size) - (start_bit) + (var)))
105
106#define __RTE_BITSET_FOREACH(var, bitset, size, start_bit, len, flags) \
107 for ((var) = __rte_bitset_find(bitset, size, start_bit, len, flags); \
108 (var) != -1; \
109 (var) = __RTE_BITSET_FOREACH_LEFT(var, size, start_bit, len) > 0 ? \
110 __rte_bitset_find(bitset, size, ((var) + 1) % (size), \
111 __RTE_BITSET_FOREACH_LEFT(var, size, start_bit, len), flags) : -1)
112
128#define RTE_BITSET_FOREACH_SET(var, bitset, size) \
129 __RTE_BITSET_FOREACH(var, bitset, size, 0, size, 0)
130
145#define RTE_BITSET_FOREACH_CLEAR(var, bitset, size) \
146 __RTE_BITSET_FOREACH(var, bitset, size, 0, size, __RTE_BITSET_FIND_FLAG_FIND_CLEAR)
147
168#define RTE_BITSET_FOREACH_SET_RANGE(var, bitset, size, start_bit, len) \
169 __RTE_BITSET_FOREACH(var, bitset, size, start_bit, len, 0)
170
191#define RTE_BITSET_FOREACH_CLEAR_RANGE(var, bitset, size, start_bit, len) \
192 __RTE_BITSET_FOREACH(var, bitset, size, start_bit, len, __RTE_BITSET_FIND_FLAG_FIND_CLEAR)
193
194#define RTE_BITSET_FOREACH_SET_WRAP(var, bitset, size, start_bit, len) \
195 __RTE_BITSET_FOREACH(var, bitset, size, start_bit, len, __RTE_BITSET_FIND_FLAG_WRAP)
196
197#define RTE_BITSET_FOREACH_CLEAR_WRAP(var, bitset, size, start_bit, len) \
198 __RTE_BITSET_FOREACH(var, bitset, size, start_bit, len, \
199 __RTE_BITSET_FIND_FLAG_WRAP | __RTE_BITSET_FIND_FLAG_FIND_CLEAR)
200
215static inline void
216rte_bitset_init(uint64_t *bitset, size_t size)
217{
218 memset(bitset, 0, RTE_BITSET_SIZE(size));
219}
220
231static inline bool
232rte_bitset_test(const uint64_t *bitset, size_t bit_num)
233{
234 return __RTE_BITSET_DELEGATE(rte_bit_test, bitset, bit_num);
235}
236
249static inline void
250rte_bitset_set(uint64_t *bitset, size_t bit_num)
251{
252 __RTE_BITSET_DELEGATE(rte_bit_set, bitset, bit_num);
253}
254
267static inline void
268rte_bitset_clear(uint64_t *bitset, size_t bit_num)
269{
270 __RTE_BITSET_DELEGATE(rte_bit_clear, bitset, bit_num);
271}
272
287static inline void
288rte_bitset_assign(uint64_t *bitset, size_t bit_num, bool bit_value)
289{
290 __RTE_BITSET_DELEGATE_N(rte_bit_assign, bitset, bit_num, bit_value);
291}
292
305static inline void
306rte_bitset_flip(uint64_t *bitset, size_t bit_num)
307{
308 __RTE_BITSET_DELEGATE(rte_bit_flip, bitset, bit_num);
309}
310
326static inline bool
327rte_bitset_atomic_test(const uint64_t *bitset, size_t bit_num, int memory_order)
328{
329 return __RTE_BITSET_DELEGATE_N(rte_bit_atomic_test, bitset, bit_num, memory_order);
330}
331
351static inline void
352rte_bitset_atomic_set(uint64_t *bitset, size_t bit_num, int memory_order)
353{
354 __RTE_BITSET_DELEGATE_N(rte_bit_atomic_set, bitset, bit_num, memory_order);
355}
356
376static inline void
377rte_bitset_atomic_clear(uint64_t *bitset, size_t bit_num, int memory_order)
378{
379 __RTE_BITSET_DELEGATE_N(rte_bit_atomic_clear, bitset, bit_num, memory_order);
380}
381
403static inline void
404rte_bitset_atomic_assign(uint64_t *bitset, size_t bit_num, bool bit_value, int memory_order)
405{
406 __RTE_BITSET_DELEGATE_N(rte_bit_atomic_assign, bitset, bit_num, bit_value, memory_order);
407}
408
428static inline void
429rte_bitset_atomic_flip(uint64_t *bitset, size_t bit_num, int memory_order)
430{
431 __RTE_BITSET_DELEGATE_N(rte_bit_atomic_flip, bitset, bit_num, memory_order);
432}
433
442static inline void
443rte_bitset_set_all(uint64_t *bitset, size_t size)
444{
445 memset(bitset, 0xFF, RTE_BITSET_SIZE(size));
446}
447
456static inline void
457rte_bitset_clear_all(uint64_t *bitset, size_t size)
458{
459 rte_bitset_init(bitset, size);
460}
461
472static inline size_t
473rte_bitset_count_set(const uint64_t *bitset, size_t size)
474{
475 size_t i;
476 size_t total = 0;
477
478 /*
479 * Unused bits in a rte_bitset are always '0', and thus are
480 * not included in this count.
481 */
482 for (i = 0; i < RTE_BITSET_NUM_WORDS(size) - 1; i++)
483 total += rte_popcount64(bitset[i]);
484
485 total += rte_popcount64(bitset[i] & __RTE_BITSET_USED_MASK(size));
486
487 return total;
488}
489
500static inline size_t
501rte_bitset_count_clear(const uint64_t *bitset, size_t size)
502{
503 return size - rte_bitset_count_set(bitset, size);
504}
505
506#define __RTE_BITSET_FIND_FLAG_FIND_CLEAR (1U << 0)
507#define __RTE_BITSET_FIND_FLAG_WRAP (1U << 1)
508
509static inline ssize_t
510__rte_bitset_find_nowrap(const uint64_t *bitset, size_t __rte_unused size, size_t start_bit,
511 size_t len, bool find_clear)
512{
513 size_t word_idx;
514 size_t offset;
515 size_t end_bit = start_bit + len;
516
517 RTE_ASSERT(end_bit <= size);
518
519 if (unlikely(len == 0))
520 return -1;
521
522 word_idx = __RTE_BITSET_WORD_IDX(start_bit);
523 offset = __RTE_BITSET_BIT_OFFSET(start_bit);
524
525 while (word_idx <= __RTE_BITSET_WORD_IDX(end_bit - 1)) {
526 uint64_t word;
527
528 word = bitset[word_idx];
529 if (find_clear)
530 word = ~word;
531
532 word >>= offset;
533
534 if (word != 0) {
535 size_t ffs = start_bit + rte_bsf64(word);
536
537 /*
538 * Check if set bit were among the last,
539 * unused bits, in the last word.
540 */
541 if (unlikely(ffs >= end_bit))
542 return -1;
543
544 return ffs;
545 }
546
547 start_bit += (RTE_BITSET_WORD_BITS - offset);
548 word_idx++;
549 offset = 0;
550 }
551
552 return -1;
553
554}
555
556static inline ssize_t
557__rte_bitset_find(const uint64_t *bitset, size_t size, size_t start_bit, size_t len,
558 unsigned int flags)
559{
560 bool find_clear = flags & __RTE_BITSET_FIND_FLAG_FIND_CLEAR;
561 bool may_wrap = flags & __RTE_BITSET_FIND_FLAG_WRAP;
562 bool does_wrap = (start_bit + len) > size;
563 ssize_t rc;
564
565 RTE_ASSERT(len <= size);
566 if (!may_wrap)
567 RTE_ASSERT(!does_wrap);
568
569 if (may_wrap && does_wrap) {
570 size_t len0 = size - start_bit;
571 size_t len1 = len - len0;
572
573 rc = __rte_bitset_find_nowrap(bitset, size, start_bit, len0, find_clear);
574 if (rc < 0)
575 rc = __rte_bitset_find_nowrap(bitset, size, 0, len1, find_clear);
576 } else
577 rc = __rte_bitset_find_nowrap(bitset, size, start_bit, len, find_clear);
578
579 return rc;
580}
581
596static inline ssize_t
597rte_bitset_find_first_set(const uint64_t *bitset, size_t size)
598{
599 return __rte_bitset_find(bitset, size, 0, size, 0);
600}
601
622static inline ssize_t
623rte_bitset_find_set(const uint64_t *bitset, size_t size, size_t start_bit, size_t len)
624{
625 return __rte_bitset_find(bitset, size, start_bit, len, 0);
626}
627
649static inline ssize_t
650rte_bitset_find_set_wrap(const uint64_t *bitset, size_t size, size_t start_bit, size_t len)
651{
652 return __rte_bitset_find(bitset, size, start_bit, len, __RTE_BITSET_FIND_FLAG_WRAP);
653}
654
669static inline ssize_t
670rte_bitset_find_first_clear(const uint64_t *bitset, size_t size)
671{
672 return __rte_bitset_find(bitset, size, 0, size, __RTE_BITSET_FIND_FLAG_FIND_CLEAR);
673}
674
695static inline ssize_t
696rte_bitset_find_clear(const uint64_t *bitset, size_t size, size_t start_bit, size_t len)
697{
698 return __rte_bitset_find(bitset, size, start_bit, len, __RTE_BITSET_FIND_FLAG_FIND_CLEAR);
699}
700
722static inline ssize_t
723rte_bitset_find_clear_wrap(const uint64_t *bitset, size_t size, size_t start_bit, size_t len)
724{
725 return __rte_bitset_find(bitset, size, start_bit, len,
726 __RTE_BITSET_FIND_FLAG_FIND_CLEAR | __RTE_BITSET_FIND_FLAG_WRAP);
727}
728
743static inline void
744rte_bitset_copy(uint64_t *__rte_restrict dst_bitset, const uint64_t *__rte_restrict src_bitset,
745 size_t size)
746{
747 rte_memcpy(dst_bitset, src_bitset, RTE_BITSET_SIZE(size));
748}
749
766static inline void
767rte_bitset_or(uint64_t *dst_bitset, const uint64_t *src_bitset0, const uint64_t *src_bitset1,
768 size_t size)
769{
770 size_t i;
771
772 for (i = 0; i < RTE_BITSET_NUM_WORDS(size); i++)
773 dst_bitset[i] = src_bitset0[i] | src_bitset1[i];
774}
775
792static inline void
793rte_bitset_and(uint64_t *dst_bitset, const uint64_t *src_bitset0, const uint64_t *src_bitset1,
794 size_t size)
795{
796 size_t i;
797
798 for (i = 0; i < RTE_BITSET_NUM_WORDS(size); i++)
799 dst_bitset[i] = src_bitset0[i] & src_bitset1[i];
800}
801
818static inline void
819rte_bitset_xor(uint64_t *dst_bitset, const uint64_t *src_bitset0, const uint64_t *src_bitset1,
820 size_t size)
821{
822 size_t i;
823
824 for (i = 0; i < RTE_BITSET_NUM_WORDS(size); i++)
825 dst_bitset[i] = src_bitset0[i] ^ src_bitset1[i];
826}
827
841static inline void
842rte_bitset_complement(uint64_t *dst_bitset, const uint64_t *src_bitset, size_t size)
843{
844 size_t i;
845
846 for (i = 0; i < RTE_BITSET_NUM_WORDS(size); i++)
847 dst_bitset[i] = ~src_bitset[i];
848}
849
865static inline void
866rte_bitset_shift_left(uint64_t *dst_bitset, const uint64_t *src_bitset, size_t size,
867 size_t shift_bits)
868{
869 const int src_word_offset = shift_bits / RTE_BITSET_WORD_BITS;
870 const int src_bit_offset = shift_bits % RTE_BITSET_WORD_BITS;
871 unsigned int dst_idx;
872
873 for (dst_idx = 0; dst_idx < RTE_BITSET_NUM_WORDS(size); dst_idx++) {
874 int src_high_idx = dst_idx - src_word_offset;
875 uint64_t low_bits = 0;
876 uint64_t high_bits = 0;
877
878 if (src_high_idx >= 0) {
879 int src_low_idx = src_high_idx - 1;
880
881 high_bits = src_bitset[src_high_idx] << src_bit_offset;
882
883 if (src_bit_offset > 0 && src_low_idx >= 0)
884 low_bits = src_bitset[src_low_idx] >>
885 (RTE_BITSET_WORD_BITS - src_bit_offset);
886 }
887 dst_bitset[dst_idx] = low_bits | high_bits;
888 }
889}
890
906static inline void
907rte_bitset_shift_right(uint64_t *dst_bitset, const uint64_t *src_bitset, size_t size,
908 size_t shift_bits)
909{
910 const int num_words = RTE_BITSET_NUM_WORDS(size);
911 const uint64_t used_mask = __RTE_BITSET_USED_MASK(size);
912 const int src_word_offset = shift_bits / RTE_BITSET_WORD_BITS;
913 const int src_bit_offset = shift_bits % RTE_BITSET_WORD_BITS;
914 int dst_idx;
915
916 for (dst_idx = 0; dst_idx < num_words; dst_idx++) {
917 int src_low_idx = src_word_offset + dst_idx;
918 int src_high_idx = src_low_idx + 1;
919 uint64_t src_low_word_bits = 0;
920 uint64_t src_high_word_bits = 0;
921
922 if (src_low_idx < num_words) {
923 src_low_word_bits = src_bitset[src_low_idx];
924
925 if (src_low_idx == (num_words - 1))
926 src_low_word_bits &= used_mask;
927
928 src_low_word_bits >>= src_bit_offset;
929
930 if (src_bit_offset > 0 && src_high_idx < num_words) {
931 src_high_word_bits = src_bitset[src_high_idx];
932
933 if (src_high_idx == (num_words - 1))
934 src_high_word_bits &= used_mask;
935
936 src_high_word_bits <<= (RTE_BITSET_WORD_BITS - src_bit_offset);
937 }
938 }
939 dst_bitset[dst_idx] = src_low_word_bits | src_high_word_bits;
940 }
941}
942
955static inline bool
956rte_bitset_equal(const uint64_t *bitset_a, const uint64_t *bitset_b, size_t size)
957{
958 size_t i;
959 uint64_t last_a, last_b;
960
961 for (i = 0; i < RTE_BITSET_NUM_WORDS(size) - 1; i++)
962 if (bitset_a[i] != bitset_b[i])
963 return false;
964
965 last_a = bitset_a[i] << __RTE_BITSET_UNUSED(size);
966 last_b = bitset_b[i] << __RTE_BITSET_UNUSED(size);
967
968 return last_a == last_b;
969}
970
993ssize_t
994rte_bitset_to_str(const uint64_t *bitset, size_t size, char *buf, size_t capacity);
995
996#ifdef __cplusplus
997}
998#endif
999
1000#endif /* _RTE_BITSET_H_ */
#define rte_bit_atomic_assign(addr, nr, value, memory_order)
Definition: rte_bitops.h:320
#define rte_bit_flip(addr, nr)
Definition: rte_bitops.h:224
#define rte_bit_set(addr, nr)
Definition: rte_bitops.h:154
#define rte_bit_atomic_flip(addr, nr, memory_order)
Definition: rte_bitops.h:343
static uint32_t rte_bsf64(uint64_t v)
Definition: rte_bitops.h:1177
#define rte_bit_assign(addr, nr, value)
Definition: rte_bitops.h:201
#define rte_bit_test(addr, nr)
Definition: rte_bitops.h:127
static unsigned int rte_popcount64(uint64_t v)
Definition: rte_bitops.h:1034
#define rte_bit_atomic_set(addr, nr, memory_order)
Definition: rte_bitops.h:274
#define rte_bit_clear(addr, nr)
Definition: rte_bitops.h:177
#define rte_bit_atomic_clear(addr, nr, memory_order)
Definition: rte_bitops.h:296
#define rte_bit_atomic_test(addr, nr, memory_order)
Definition: rte_bitops.h:248
static bool rte_bitset_equal(const uint64_t *bitset_a, const uint64_t *bitset_b, size_t size)
Definition: rte_bitset.h:956
#define RTE_BITSET_WORD_BITS
Definition: rte_bitset.h:58
static void rte_bitset_init(uint64_t *bitset, size_t size)
Definition: rte_bitset.h:216
static ssize_t rte_bitset_find_first_set(const uint64_t *bitset, size_t size)
Definition: rte_bitset.h:597
static bool rte_bitset_test(const uint64_t *bitset, size_t bit_num)
Definition: rte_bitset.h:232
static ssize_t rte_bitset_find_clear_wrap(const uint64_t *bitset, size_t size, size_t start_bit, size_t len)
Definition: rte_bitset.h:723
static void rte_bitset_or(uint64_t *dst_bitset, const uint64_t *src_bitset0, const uint64_t *src_bitset1, size_t size)
Definition: rte_bitset.h:767
static void rte_bitset_shift_right(uint64_t *dst_bitset, const uint64_t *src_bitset, size_t size, size_t shift_bits)
Definition: rte_bitset.h:907
static void rte_bitset_flip(uint64_t *bitset, size_t bit_num)
Definition: rte_bitset.h:306
static void rte_bitset_assign(uint64_t *bitset, size_t bit_num, bool bit_value)
Definition: rte_bitset.h:288
static size_t rte_bitset_count_clear(const uint64_t *bitset, size_t size)
Definition: rte_bitset.h:501
static void rte_bitset_atomic_clear(uint64_t *bitset, size_t bit_num, int memory_order)
Definition: rte_bitset.h:377
static ssize_t rte_bitset_find_set_wrap(const uint64_t *bitset, size_t size, size_t start_bit, size_t len)
Definition: rte_bitset.h:650
static ssize_t rte_bitset_find_set(const uint64_t *bitset, size_t size, size_t start_bit, size_t len)
Definition: rte_bitset.h:623
static size_t rte_bitset_count_set(const uint64_t *bitset, size_t size)
Definition: rte_bitset.h:473
static ssize_t rte_bitset_find_clear(const uint64_t *bitset, size_t size, size_t start_bit, size_t len)
Definition: rte_bitset.h:696
static void rte_bitset_clear(uint64_t *bitset, size_t bit_num)
Definition: rte_bitset.h:268
static void rte_bitset_clear_all(uint64_t *bitset, size_t size)
Definition: rte_bitset.h:457
static void rte_bitset_atomic_assign(uint64_t *bitset, size_t bit_num, bool bit_value, int memory_order)
Definition: rte_bitset.h:404
static void rte_bitset_set_all(uint64_t *bitset, size_t size)
Definition: rte_bitset.h:443
static void rte_bitset_complement(uint64_t *dst_bitset, const uint64_t *src_bitset, size_t size)
Definition: rte_bitset.h:842
static void rte_bitset_xor(uint64_t *dst_bitset, const uint64_t *src_bitset0, const uint64_t *src_bitset1, size_t size)
Definition: rte_bitset.h:819
static void rte_bitset_shift_left(uint64_t *dst_bitset, const uint64_t *src_bitset, size_t size, size_t shift_bits)
Definition: rte_bitset.h:866
ssize_t rte_bitset_to_str(const uint64_t *bitset, size_t size, char *buf, size_t capacity)
static void rte_bitset_atomic_flip(uint64_t *bitset, size_t bit_num, int memory_order)
Definition: rte_bitset.h:429
static void rte_bitset_atomic_set(uint64_t *bitset, size_t bit_num, int memory_order)
Definition: rte_bitset.h:352
static ssize_t rte_bitset_find_first_clear(const uint64_t *bitset, size_t size)
Definition: rte_bitset.h:670
static void rte_bitset_set(uint64_t *bitset, size_t bit_num)
Definition: rte_bitset.h:250
static void rte_bitset_and(uint64_t *dst_bitset, const uint64_t *src_bitset0, const uint64_t *src_bitset1, size_t size)
Definition: rte_bitset.h:793
#define RTE_BITSET_NUM_WORDS(size)
Definition: rte_bitset.h:63
#define RTE_BITSET_SIZE(size)
Definition: rte_bitset.h:70
static bool rte_bitset_atomic_test(const uint64_t *bitset, size_t bit_num, int memory_order)
Definition: rte_bitset.h:327
static void rte_bitset_copy(uint64_t *__rte_restrict dst_bitset, const uint64_t *__rte_restrict src_bitset, size_t size)
Definition: rte_bitset.h:744
#define unlikely(x)
#define __rte_unused
Definition: rte_common.h:276
#define __rte_restrict
Definition: rte_common.h:283
static void * rte_memcpy(void *dst, const void *src, size_t n)