xref: /dpdk/lib/eal/include/rte_bitset.h (revision a3e126fd58d11aee85220480f4bf692612fbadc2)
199a11976SMattias Rönnblom /* SPDX-License-Identifier: BSD-3-Clause
299a11976SMattias Rönnblom  * Copyright(c) 2023 Ericsson AB
399a11976SMattias Rönnblom  */
499a11976SMattias Rönnblom 
599a11976SMattias Rönnblom #ifndef _RTE_BITSET_H_
699a11976SMattias Rönnblom #define _RTE_BITSET_H_
799a11976SMattias Rönnblom 
899a11976SMattias Rönnblom /**
999a11976SMattias Rönnblom  * @file
1099a11976SMattias Rönnblom  * RTE Bitset
1199a11976SMattias Rönnblom  *
1299a11976SMattias Rönnblom  * This file provides functions and macros for querying and
1399a11976SMattias Rönnblom  * manipulating sets of bits kept in arrays of @c uint64_t-sized
1499a11976SMattias Rönnblom  * elements.
1599a11976SMattias Rönnblom  *
1699a11976SMattias Rönnblom  * The bits in a bitset are numbered from 0 to @c size - 1, with the
1799a11976SMattias Rönnblom  * lowest index being the least significant bit.
1899a11976SMattias Rönnblom  *
1999a11976SMattias Rönnblom  * The bitset array must be properly aligned.
2099a11976SMattias Rönnblom  *
2199a11976SMattias Rönnblom  * For optimal performance, the @c size parameter, required by
2299a11976SMattias Rönnblom  * many of the API's functions, should be a compile-time constant.
2399a11976SMattias Rönnblom  *
2499a11976SMattias Rönnblom  * For large bitsets, the rte_bitmap.h API may be more appropriate.
2599a11976SMattias Rönnblom  *
2699a11976SMattias Rönnblom  * @warning
2799a11976SMattias Rönnblom  * All functions modifying a bitset may overwrite any unused bits of
2899a11976SMattias Rönnblom  * the last word. Such unused bits are ignored by all functions reading
2999a11976SMattias Rönnblom  * bits.
3099a11976SMattias Rönnblom  *
3199a11976SMattias Rönnblom  */
3299a11976SMattias Rönnblom 
3399a11976SMattias Rönnblom #include <limits.h>
3499a11976SMattias Rönnblom #include <stdbool.h>
3599a11976SMattias Rönnblom #include <stddef.h>
3699a11976SMattias Rönnblom #include <stdint.h>
3799a11976SMattias Rönnblom 
3899a11976SMattias Rönnblom #include <rte_bitops.h>
3999a11976SMattias Rönnblom #include <rte_branch_prediction.h>
4099a11976SMattias Rönnblom #include <rte_common.h>
4199a11976SMattias Rönnblom #include <rte_compat.h>
4299a11976SMattias Rönnblom #include <rte_debug.h>
4399a11976SMattias Rönnblom #include <rte_memcpy.h>
4499a11976SMattias Rönnblom 
4599a11976SMattias Rönnblom #ifdef __cplusplus
4699a11976SMattias Rönnblom extern "C" {
4799a11976SMattias Rönnblom #endif
4899a11976SMattias Rönnblom 
4999a11976SMattias Rönnblom /**
5099a11976SMattias Rönnblom  * The size (in bytes) of each element in the array used to represent
5199a11976SMattias Rönnblom  * a bitset.
5299a11976SMattias Rönnblom  */
5399a11976SMattias Rönnblom #define RTE_BITSET_WORD_SIZE (sizeof(uint64_t))
5499a11976SMattias Rönnblom 
5599a11976SMattias Rönnblom /**
5699a11976SMattias Rönnblom  * The size (in bits) of each element in the array used to represent
5799a11976SMattias Rönnblom  * a bitset.
5899a11976SMattias Rönnblom  */
5999a11976SMattias Rönnblom #define RTE_BITSET_WORD_BITS (RTE_BITSET_WORD_SIZE * CHAR_BIT)
6099a11976SMattias Rönnblom 
6199a11976SMattias Rönnblom /**
6299a11976SMattias Rönnblom  * Computes the number of words required to store @c size bits.
6399a11976SMattias Rönnblom  */
6499a11976SMattias Rönnblom #define RTE_BITSET_NUM_WORDS(size) \
6599a11976SMattias Rönnblom 	((size + RTE_BITSET_WORD_BITS - 1) / RTE_BITSET_WORD_BITS)
6699a11976SMattias Rönnblom 
6799a11976SMattias Rönnblom /**
6899a11976SMattias Rönnblom  * Computes the amount of memory (in bytes) required to fit a bitset
6999a11976SMattias Rönnblom  * holding @c size bits.
7099a11976SMattias Rönnblom  */
7199a11976SMattias Rönnblom #define RTE_BITSET_SIZE(size) \
7299a11976SMattias Rönnblom 	((size_t)(RTE_BITSET_NUM_WORDS(size) * RTE_BITSET_WORD_SIZE))
7399a11976SMattias Rönnblom 
7499a11976SMattias Rönnblom #define __RTE_BITSET_WORD_IDX(bit_num) ((bit_num) / RTE_BITSET_WORD_BITS)
7599a11976SMattias Rönnblom #define __RTE_BITSET_BIT_OFFSET(bit_num) ((bit_num) % RTE_BITSET_WORD_BITS)
7699a11976SMattias Rönnblom #define __RTE_BITSET_UNUSED(size) \
7799a11976SMattias Rönnblom 	((RTE_BITSET_NUM_WORDS(size) * RTE_BITSET_WORD_BITS) - (size))
7899a11976SMattias Rönnblom #define __RTE_BITSET_USED_MASK(size) \
7999a11976SMattias Rönnblom 	(UINT64_MAX >> __RTE_BITSET_UNUSED(size))
8099a11976SMattias Rönnblom 
8199a11976SMattias Rönnblom #define __RTE_BITSET_DELEGATE_N(fun, bitset, bit_num, ...) \
8299a11976SMattias Rönnblom 	fun(&(bitset)[__RTE_BITSET_WORD_IDX(bit_num)], __RTE_BITSET_BIT_OFFSET(bit_num), \
8399a11976SMattias Rönnblom 		__VA_ARGS__)
8499a11976SMattias Rönnblom 
8599a11976SMattias Rönnblom /* MSVC doesn't have ##__VA_ARGS__, so argument-less -> special case */
8699a11976SMattias Rönnblom #define __RTE_BITSET_DELEGATE(fun, bitset, bit_num) \
8799a11976SMattias Rönnblom 	fun(&(bitset)[__RTE_BITSET_WORD_IDX(bit_num)], __RTE_BITSET_BIT_OFFSET(bit_num))
8899a11976SMattias Rönnblom 
8999a11976SMattias Rönnblom /**
9099a11976SMattias Rönnblom  * @warning
9199a11976SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
9299a11976SMattias Rönnblom  *
9399a11976SMattias Rönnblom  * Declare a bitset.
9499a11976SMattias Rönnblom  *
9599a11976SMattias Rönnblom  * Declare (e.g., as a struct field) or define (e.g., as a stack
9699a11976SMattias Rönnblom  * variable) a bitset of the specified size.
9799a11976SMattias Rönnblom  *
9899a11976SMattias Rönnblom  * @param size
9999a11976SMattias Rönnblom  *   The number of bits the bitset must be able to represent. Must be
10099a11976SMattias Rönnblom  *   a compile-time constant.
10199a11976SMattias Rönnblom  * @param name
10299a11976SMattias Rönnblom  *   The field or variable name of the resulting definition.
10399a11976SMattias Rönnblom  */
10499a11976SMattias Rönnblom #define RTE_BITSET_DECLARE(name, size) \
10599a11976SMattias Rönnblom 	uint64_t name[RTE_BITSET_NUM_WORDS(size)]
10699a11976SMattias Rönnblom 
10799a11976SMattias Rönnblom #define __RTE_BITSET_FOREACH_LEFT(var, size, start_bit, len) \
10899a11976SMattias Rönnblom 	((len) - 1 - ((var) >= (start_bit) ? (var) - (start_bit) : (size) - (start_bit) + (var)))
10999a11976SMattias Rönnblom 
11099a11976SMattias Rönnblom #define __RTE_BITSET_FOREACH(var, bitset, size, start_bit, len, flags) \
11199a11976SMattias Rönnblom 	for ((var) = __rte_bitset_find(bitset, size, start_bit, len, flags); \
11299a11976SMattias Rönnblom 			(var) != -1; \
11399a11976SMattias Rönnblom 			(var) = __RTE_BITSET_FOREACH_LEFT(var, size, start_bit, len) > 0 ? \
11499a11976SMattias Rönnblom 				__rte_bitset_find(bitset, size, ((var) + 1) % (size), \
11599a11976SMattias Rönnblom 				__RTE_BITSET_FOREACH_LEFT(var, size, start_bit, len), flags) : -1)
11699a11976SMattias Rönnblom 
11799a11976SMattias Rönnblom /**
11899a11976SMattias Rönnblom  * @warning
11999a11976SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
12099a11976SMattias Rönnblom  *
12199a11976SMattias Rönnblom  * Iterate over all bits set.
12299a11976SMattias Rönnblom  *
12399a11976SMattias Rönnblom  * This macro iterates over all bits set (i.e., all ones) in the
12499a11976SMattias Rönnblom  * bitset, in the forward direction (i.e., starting with the least
12599a11976SMattias Rönnblom  * significant '1').
12699a11976SMattias Rönnblom  *
12799a11976SMattias Rönnblom  * @param var
12899a11976SMattias Rönnblom  *   An iterator variable of type @c ssize_t. For each successive
12999a11976SMattias Rönnblom  *   iteration, this variable will hold the bit index of a set bit.
13099a11976SMattias Rönnblom  * @param bitset
13199a11976SMattias Rönnblom  *   A <tt>const uint64_t *</tt> pointer to the bitset array.
13299a11976SMattias Rönnblom  * @param size
13399a11976SMattias Rönnblom  *   The size of the bitset (in bits).
13499a11976SMattias Rönnblom  */
13599a11976SMattias Rönnblom #define RTE_BITSET_FOREACH_SET(var, bitset, size) \
13699a11976SMattias Rönnblom 	__RTE_BITSET_FOREACH(var, bitset, size, 0, size, 0)
13799a11976SMattias Rönnblom 
13899a11976SMattias Rönnblom /**
13999a11976SMattias Rönnblom  * @warning
14099a11976SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
14199a11976SMattias Rönnblom  *
14299a11976SMattias Rönnblom  * Iterate over all bits cleared.
14399a11976SMattias Rönnblom  *
14499a11976SMattias Rönnblom  * This macro iterates over all bits cleared in the bitset, in the
14599a11976SMattias Rönnblom  * forward direction (i.e., starting with the lowest-indexed set bit).
14699a11976SMattias Rönnblom  *
14799a11976SMattias Rönnblom  * @param var
14899a11976SMattias Rönnblom  *   An iterator variable of type @c ssize_t. For each successive iteration,
14999a11976SMattias Rönnblom  *   this variable will hold the bit index of a cleared bit.
15099a11976SMattias Rönnblom  * @param bitset
15199a11976SMattias Rönnblom  *   A <tt>const uint64_t *</tt> pointer to the bitset array.
15299a11976SMattias Rönnblom  * @param size
15399a11976SMattias Rönnblom  *   The size of the bitset (in bits).
15499a11976SMattias Rönnblom  */
15599a11976SMattias Rönnblom #define RTE_BITSET_FOREACH_CLEAR(var, bitset, size) \
15699a11976SMattias Rönnblom 	__RTE_BITSET_FOREACH(var, bitset, size, 0, size, __RTE_BITSET_FIND_FLAG_FIND_CLEAR)
15799a11976SMattias Rönnblom 
15899a11976SMattias Rönnblom /**
15999a11976SMattias Rönnblom  * @warning
16099a11976SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
16199a11976SMattias Rönnblom  *
16299a11976SMattias Rönnblom  * Iterate over all bits set within a range.
16399a11976SMattias Rönnblom  *
16499a11976SMattias Rönnblom  * This macro iterates over all bits set (i.e., all ones) in the
16599a11976SMattias Rönnblom  * specified range, in the forward direction (i.e., starting with the
16699a11976SMattias Rönnblom  * least significant '1').
16799a11976SMattias Rönnblom  *
16899a11976SMattias Rönnblom  * @param var
16999a11976SMattias Rönnblom  *   An iterator variable of type @c ssize_t. For each successive iteration,
17099a11976SMattias Rönnblom  *   this variable will hold the bit index of a set bit.
17199a11976SMattias Rönnblom  * @param bitset
17299a11976SMattias Rönnblom  *   A <tt>const uint64_t *</tt> pointer to the bitset array.
17399a11976SMattias Rönnblom  * @param size
17499a11976SMattias Rönnblom  *   The size of the bitset (in bits).
17599a11976SMattias Rönnblom  * @param start_bit
17699a11976SMattias Rönnblom  *   The index of the first bit to check. Must be less than @c size.
17799a11976SMattias Rönnblom  * @param len
17899a11976SMattias Rönnblom  *   The length (in bits) of the range. @c start_bit + @c len must be less
17999a11976SMattias Rönnblom  *   than or equal to @c size.
18099a11976SMattias Rönnblom  */
18199a11976SMattias Rönnblom #define RTE_BITSET_FOREACH_SET_RANGE(var, bitset, size, start_bit, len) \
18299a11976SMattias Rönnblom 	__RTE_BITSET_FOREACH(var, bitset, size, start_bit, len, 0)
18399a11976SMattias Rönnblom 
18499a11976SMattias Rönnblom /**
18599a11976SMattias Rönnblom  * @warning
18699a11976SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
18799a11976SMattias Rönnblom  *
18899a11976SMattias Rönnblom  * Iterate over all cleared bits within a range.
18999a11976SMattias Rönnblom  *
19099a11976SMattias Rönnblom  * This macro iterates over all bits cleared (i.e., all zeroes) in the
19199a11976SMattias Rönnblom  * specified range, in the forward direction (i.e., starting with the
19299a11976SMattias Rönnblom  * least significant '0').
19399a11976SMattias Rönnblom  *
19499a11976SMattias Rönnblom  * @param var
19599a11976SMattias Rönnblom  *   An iterator variable of type @c ssize_t. For each successive iteration,
19699a11976SMattias Rönnblom  *   this variable will hold the bit index of a set bit.
19799a11976SMattias Rönnblom  * @param bitset
19899a11976SMattias Rönnblom  *   A <tt>const uint64_t *</tt> pointer to the bitset array.
19999a11976SMattias Rönnblom  * @param size
20099a11976SMattias Rönnblom  *   The size of the bitset (in bits).
20199a11976SMattias Rönnblom  * @param start_bit
20299a11976SMattias Rönnblom  *   The index of the first bit to check. Must be less than @c size.
20399a11976SMattias Rönnblom  * @param len
20499a11976SMattias Rönnblom  *   The length (in bits) of the range. @c start_bit + @c len must be less
20599a11976SMattias Rönnblom  *   than or equal to @c size.
20699a11976SMattias Rönnblom  */
20799a11976SMattias Rönnblom #define RTE_BITSET_FOREACH_CLEAR_RANGE(var, bitset, size, start_bit, len) \
20899a11976SMattias Rönnblom 	__RTE_BITSET_FOREACH(var, bitset, size, start_bit, len, __RTE_BITSET_FIND_FLAG_FIND_CLEAR)
20999a11976SMattias Rönnblom 
21099a11976SMattias Rönnblom #define RTE_BITSET_FOREACH_SET_WRAP(var, bitset, size, start_bit, len) \
21199a11976SMattias Rönnblom 	__RTE_BITSET_FOREACH(var, bitset, size, start_bit, len, __RTE_BITSET_FIND_FLAG_WRAP)
21299a11976SMattias Rönnblom 
21399a11976SMattias Rönnblom #define RTE_BITSET_FOREACH_CLEAR_WRAP(var, bitset, size, start_bit, len) \
21499a11976SMattias Rönnblom 	__RTE_BITSET_FOREACH(var, bitset, size, start_bit, len, \
21599a11976SMattias Rönnblom 		__RTE_BITSET_FIND_FLAG_WRAP | __RTE_BITSET_FIND_FLAG_FIND_CLEAR)
21699a11976SMattias Rönnblom 
21799a11976SMattias Rönnblom /**
21899a11976SMattias Rönnblom  * @warning
21999a11976SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
22099a11976SMattias Rönnblom  *
22199a11976SMattias Rönnblom  * Initializes a bitset.
22299a11976SMattias Rönnblom  *
22399a11976SMattias Rönnblom  * All bits are cleared.
22499a11976SMattias Rönnblom  *
22599a11976SMattias Rönnblom  * In case all words in the bitset array are already set to zero by
22699a11976SMattias Rönnblom  * other means (e.g., at the time of memory allocation), this function
22799a11976SMattias Rönnblom  * need not be called.
22899a11976SMattias Rönnblom  *
22999a11976SMattias Rönnblom  * @param bitset
23099a11976SMattias Rönnblom  *   A pointer to the array of bitset 64-bit words.
23199a11976SMattias Rönnblom  * @param size
23299a11976SMattias Rönnblom  *   The size of the bitset (in bits).
23399a11976SMattias Rönnblom  */
23499a11976SMattias Rönnblom __rte_experimental
23599a11976SMattias Rönnblom static inline void
23699a11976SMattias Rönnblom rte_bitset_init(uint64_t *bitset, size_t size)
23799a11976SMattias Rönnblom {
23899a11976SMattias Rönnblom 	memset(bitset, 0, RTE_BITSET_SIZE(size));
23999a11976SMattias Rönnblom }
24099a11976SMattias Rönnblom 
24199a11976SMattias Rönnblom /**
24299a11976SMattias Rönnblom  * @warning
24399a11976SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
24499a11976SMattias Rönnblom  *
24599a11976SMattias Rönnblom  * Test if a bit is set.
24699a11976SMattias Rönnblom  *
24799a11976SMattias Rönnblom  * @param bitset
24899a11976SMattias Rönnblom  *   A pointer to the array of words making up the bitset.
24999a11976SMattias Rönnblom  * @param bit_num
25099a11976SMattias Rönnblom  *   Index of the bit to test. Index 0 is the least significant bit.
25199a11976SMattias Rönnblom  * @return
25299a11976SMattias Rönnblom  *   Returns true if the bit is '1', and false if the bit is '0'.
25399a11976SMattias Rönnblom  */
25499a11976SMattias Rönnblom __rte_experimental
25599a11976SMattias Rönnblom static inline bool
25699a11976SMattias Rönnblom rte_bitset_test(const uint64_t *bitset, size_t bit_num)
25799a11976SMattias Rönnblom {
258*a3e126fdSDavid Marchand #ifdef ALLOW_EXPERIMENTAL_API
25999a11976SMattias Rönnblom 	return __RTE_BITSET_DELEGATE(rte_bit_test, bitset, bit_num);
260*a3e126fdSDavid Marchand #else
261*a3e126fdSDavid Marchand 	RTE_SET_USED(bitset);
262*a3e126fdSDavid Marchand 	RTE_SET_USED(bit_num);
263*a3e126fdSDavid Marchand 	RTE_VERIFY(false);
264*a3e126fdSDavid Marchand #endif
26599a11976SMattias Rönnblom }
26699a11976SMattias Rönnblom 
26799a11976SMattias Rönnblom /**
26899a11976SMattias Rönnblom  * @warning
26999a11976SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
27099a11976SMattias Rönnblom  *
27199a11976SMattias Rönnblom  * Set a bit in the bitset.
27299a11976SMattias Rönnblom  *
27399a11976SMattias Rönnblom  * Bits are numbered from 0 to (size - 1) (inclusive).
27499a11976SMattias Rönnblom  *
27599a11976SMattias Rönnblom  * The operation is not guaranteed to be atomic.
27699a11976SMattias Rönnblom  *
27799a11976SMattias Rönnblom  * @param bitset
27899a11976SMattias Rönnblom  *   A pointer to the array of words making up the bitset.
27999a11976SMattias Rönnblom  * @param bit_num
28099a11976SMattias Rönnblom  *   The index of the bit to be set.
28199a11976SMattias Rönnblom  */
28299a11976SMattias Rönnblom __rte_experimental
28399a11976SMattias Rönnblom static inline void
28499a11976SMattias Rönnblom rte_bitset_set(uint64_t *bitset, size_t bit_num)
28599a11976SMattias Rönnblom {
286*a3e126fdSDavid Marchand #ifdef ALLOW_EXPERIMENTAL_API
28799a11976SMattias Rönnblom 	__RTE_BITSET_DELEGATE(rte_bit_set, bitset, bit_num);
288*a3e126fdSDavid Marchand #else
289*a3e126fdSDavid Marchand 	RTE_SET_USED(bitset);
290*a3e126fdSDavid Marchand 	RTE_SET_USED(bit_num);
291*a3e126fdSDavid Marchand 	RTE_VERIFY(false);
292*a3e126fdSDavid Marchand #endif
29399a11976SMattias Rönnblom }
29499a11976SMattias Rönnblom 
29599a11976SMattias Rönnblom /**
29699a11976SMattias Rönnblom  * @warning
29799a11976SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
29899a11976SMattias Rönnblom  *
29999a11976SMattias Rönnblom  * Clear a bit in the bitset.
30099a11976SMattias Rönnblom  *
30199a11976SMattias Rönnblom  * Bits are numbered 0 to (size - 1) (inclusive).
30299a11976SMattias Rönnblom  *
30399a11976SMattias Rönnblom  * The operation is not guaranteed to be atomic.
30499a11976SMattias Rönnblom  *
30599a11976SMattias Rönnblom  * @param bitset
30699a11976SMattias Rönnblom  *   A pointer to the array of words making up the bitset.
30799a11976SMattias Rönnblom  * @param bit_num
30899a11976SMattias Rönnblom  *   The index of the bit to be cleared.
30999a11976SMattias Rönnblom  */
31099a11976SMattias Rönnblom __rte_experimental
31199a11976SMattias Rönnblom static inline void
31299a11976SMattias Rönnblom rte_bitset_clear(uint64_t *bitset, size_t bit_num)
31399a11976SMattias Rönnblom {
314*a3e126fdSDavid Marchand #ifdef ALLOW_EXPERIMENTAL_API
31599a11976SMattias Rönnblom 	__RTE_BITSET_DELEGATE(rte_bit_clear, bitset, bit_num);
316*a3e126fdSDavid Marchand #else
317*a3e126fdSDavid Marchand 	RTE_SET_USED(bitset);
318*a3e126fdSDavid Marchand 	RTE_SET_USED(bit_num);
319*a3e126fdSDavid Marchand 	RTE_VERIFY(false);
320*a3e126fdSDavid Marchand #endif
32199a11976SMattias Rönnblom }
32299a11976SMattias Rönnblom 
32399a11976SMattias Rönnblom /**
32499a11976SMattias Rönnblom  * @warning
32599a11976SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
32699a11976SMattias Rönnblom  *
32799a11976SMattias Rönnblom  * Set or clear a bit in the bitset.
32899a11976SMattias Rönnblom  *
32999a11976SMattias Rönnblom  * Bits are numbered 0 to (size - 1) (inclusive).
33099a11976SMattias Rönnblom  *
33199a11976SMattias Rönnblom  * The operation is not guaranteed to be atomic.
33299a11976SMattias Rönnblom  *
33399a11976SMattias Rönnblom  * @param bitset
33499a11976SMattias Rönnblom  *   A pointer to the array of words making up the bitset.
33599a11976SMattias Rönnblom  * @param bit_num
33699a11976SMattias Rönnblom  *   The index of the bit to be set or cleared.
33799a11976SMattias Rönnblom  * @param bit_value
33899a11976SMattias Rönnblom  *   Control if the bit should be set or cleared.
33999a11976SMattias Rönnblom  */
34099a11976SMattias Rönnblom __rte_experimental
34199a11976SMattias Rönnblom static inline void
34299a11976SMattias Rönnblom rte_bitset_assign(uint64_t *bitset, size_t bit_num, bool bit_value)
34399a11976SMattias Rönnblom {
344*a3e126fdSDavid Marchand #ifdef ALLOW_EXPERIMENTAL_API
34599a11976SMattias Rönnblom 	__RTE_BITSET_DELEGATE_N(rte_bit_assign, bitset, bit_num, bit_value);
346*a3e126fdSDavid Marchand #else
347*a3e126fdSDavid Marchand 	RTE_SET_USED(bitset);
348*a3e126fdSDavid Marchand 	RTE_SET_USED(bit_num);
349*a3e126fdSDavid Marchand 	RTE_SET_USED(bit_value);
350*a3e126fdSDavid Marchand 	RTE_VERIFY(false);
351*a3e126fdSDavid Marchand #endif
35299a11976SMattias Rönnblom }
35399a11976SMattias Rönnblom 
35499a11976SMattias Rönnblom /**
35599a11976SMattias Rönnblom  * @warning
35699a11976SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
35799a11976SMattias Rönnblom  *
35899a11976SMattias Rönnblom  * Change the value of a bit in the bitset.
35999a11976SMattias Rönnblom  *
36099a11976SMattias Rönnblom  * Bits are numbered 0 to (size - 1) (inclusive).
36199a11976SMattias Rönnblom  *
36299a11976SMattias Rönnblom  * The operation is not guaranteed to be atomic.
36399a11976SMattias Rönnblom  *
36499a11976SMattias Rönnblom  * @param bitset
36599a11976SMattias Rönnblom  *   A pointer to the array of words making up the bitset.
36699a11976SMattias Rönnblom  * @param bit_num
36799a11976SMattias Rönnblom  *   The index of the bit to be flipped.
36899a11976SMattias Rönnblom  */
36999a11976SMattias Rönnblom __rte_experimental
37099a11976SMattias Rönnblom static inline void
37199a11976SMattias Rönnblom rte_bitset_flip(uint64_t *bitset, size_t bit_num)
37299a11976SMattias Rönnblom {
373*a3e126fdSDavid Marchand #ifdef ALLOW_EXPERIMENTAL_API
37499a11976SMattias Rönnblom 	__RTE_BITSET_DELEGATE(rte_bit_flip, bitset, bit_num);
375*a3e126fdSDavid Marchand #else
376*a3e126fdSDavid Marchand 	RTE_SET_USED(bitset);
377*a3e126fdSDavid Marchand 	RTE_SET_USED(bit_num);
378*a3e126fdSDavid Marchand 	RTE_VERIFY(false);
379*a3e126fdSDavid Marchand #endif
38099a11976SMattias Rönnblom }
38199a11976SMattias Rönnblom 
38299a11976SMattias Rönnblom /**
38399a11976SMattias Rönnblom  * @warning
38499a11976SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
38599a11976SMattias Rönnblom  *
386c889c037SMattias Rönnblom  * Atomically test if a bit is set.
387c889c037SMattias Rönnblom  *
388c889c037SMattias Rönnblom  * Atomically test if a bit in a bitset is set with the specified
389c889c037SMattias Rönnblom  * memory ordering.
390c889c037SMattias Rönnblom  *
391c889c037SMattias Rönnblom  * @param bitset
392c889c037SMattias Rönnblom  *   A pointer to the array of words making up the bitset.
393c889c037SMattias Rönnblom  * @param bit_num
394c889c037SMattias Rönnblom  *   Index of the bit to test. Index 0 is the least significant bit.
395c889c037SMattias Rönnblom  * @param memory_order
396c889c037SMattias Rönnblom  *   The memory order to use.
397c889c037SMattias Rönnblom  * @return
398c889c037SMattias Rönnblom  *   Returns true if the bit is '1', and false if the bit is '0'.
399c889c037SMattias Rönnblom  */
400c889c037SMattias Rönnblom __rte_experimental
401c889c037SMattias Rönnblom static inline bool
402c889c037SMattias Rönnblom rte_bitset_atomic_test(const uint64_t *bitset, size_t bit_num, int memory_order)
403c889c037SMattias Rönnblom {
404*a3e126fdSDavid Marchand #ifdef ALLOW_EXPERIMENTAL_API
405c889c037SMattias Rönnblom 	return __RTE_BITSET_DELEGATE_N(rte_bit_atomic_test, bitset, bit_num, memory_order);
406*a3e126fdSDavid Marchand #else
407*a3e126fdSDavid Marchand 	RTE_SET_USED(bitset);
408*a3e126fdSDavid Marchand 	RTE_SET_USED(bit_num);
409*a3e126fdSDavid Marchand 	RTE_SET_USED(memory_order);
410*a3e126fdSDavid Marchand 	RTE_VERIFY(false);
411*a3e126fdSDavid Marchand #endif
412c889c037SMattias Rönnblom }
413c889c037SMattias Rönnblom 
414c889c037SMattias Rönnblom /**
415c889c037SMattias Rönnblom  * @warning
416c889c037SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
417c889c037SMattias Rönnblom  *
418c889c037SMattias Rönnblom  * Atomically set a bit in the bitset.
419c889c037SMattias Rönnblom  *
420c889c037SMattias Rönnblom  * Set a bit in a bitset as an atomic operation, with the specified
421c889c037SMattias Rönnblom  * memory ordering.
422c889c037SMattias Rönnblom  *
423c889c037SMattias Rönnblom  * rte_bitset_atomic_set() is multi-thread safe, provided all threads
424c889c037SMattias Rönnblom  * acting in parallel on the same bitset does so through
425c889c037SMattias Rönnblom  * @c rte_bitset_atomic_*() functions.
426c889c037SMattias Rönnblom  *
427c889c037SMattias Rönnblom  * Bits are numbered from 0 to (size - 1) (inclusive).
428c889c037SMattias Rönnblom  *
429c889c037SMattias Rönnblom  * @param bitset
430c889c037SMattias Rönnblom  *   A pointer to the array of words making up the bitset.
431c889c037SMattias Rönnblom  * @param bit_num
432c889c037SMattias Rönnblom  *   The index of the bit to be set.
433c889c037SMattias Rönnblom  * @param memory_order
434c889c037SMattias Rönnblom  *   The memory order to use.
435c889c037SMattias Rönnblom  */
436c889c037SMattias Rönnblom __rte_experimental
437c889c037SMattias Rönnblom static inline void
438c889c037SMattias Rönnblom rte_bitset_atomic_set(uint64_t *bitset, size_t bit_num, int memory_order)
439c889c037SMattias Rönnblom {
440*a3e126fdSDavid Marchand #ifdef ALLOW_EXPERIMENTAL_API
441c889c037SMattias Rönnblom 	__RTE_BITSET_DELEGATE_N(rte_bit_atomic_set, bitset, bit_num, memory_order);
442*a3e126fdSDavid Marchand #else
443*a3e126fdSDavid Marchand 	RTE_SET_USED(bitset);
444*a3e126fdSDavid Marchand 	RTE_SET_USED(bit_num);
445*a3e126fdSDavid Marchand 	RTE_SET_USED(memory_order);
446*a3e126fdSDavid Marchand 	RTE_VERIFY(false);
447*a3e126fdSDavid Marchand #endif
448c889c037SMattias Rönnblom }
449c889c037SMattias Rönnblom 
450c889c037SMattias Rönnblom /**
451c889c037SMattias Rönnblom  * @warning
452c889c037SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
453c889c037SMattias Rönnblom  *
454c889c037SMattias Rönnblom  * Atomically clear a bit in the bitset.
455c889c037SMattias Rönnblom  *
456c889c037SMattias Rönnblom  * Clear a bit in a bitset as an atomic operation, with the specified
457c889c037SMattias Rönnblom  * memory ordering.
458c889c037SMattias Rönnblom  *
459c889c037SMattias Rönnblom  * rte_bitset_atomic_clear() is multi-thread safe, provided all
460c889c037SMattias Rönnblom  * threads acting in parallel on the same bitset does so through @c
461c889c037SMattias Rönnblom  * rte_bitset_atomic_*() functions.
462c889c037SMattias Rönnblom  *
463c889c037SMattias Rönnblom  * Bits are numbered from 0 to (size - 1) (inclusive).
464c889c037SMattias Rönnblom  *
465c889c037SMattias Rönnblom  * @param bitset
466c889c037SMattias Rönnblom  *   A pointer to the array of words making up the bitset.
467c889c037SMattias Rönnblom  * @param bit_num
468c889c037SMattias Rönnblom  *   The index of the bit to be cleared.
469c889c037SMattias Rönnblom  * @param memory_order
470c889c037SMattias Rönnblom  *   The memory order to use.
471c889c037SMattias Rönnblom  */
472c889c037SMattias Rönnblom __rte_experimental
473c889c037SMattias Rönnblom static inline void
474c889c037SMattias Rönnblom rte_bitset_atomic_clear(uint64_t *bitset, size_t bit_num, int memory_order)
475c889c037SMattias Rönnblom {
476*a3e126fdSDavid Marchand #ifdef ALLOW_EXPERIMENTAL_API
477c889c037SMattias Rönnblom 	__RTE_BITSET_DELEGATE_N(rte_bit_atomic_clear, bitset, bit_num, memory_order);
478*a3e126fdSDavid Marchand #else
479*a3e126fdSDavid Marchand 	RTE_SET_USED(bitset);
480*a3e126fdSDavid Marchand 	RTE_SET_USED(bit_num);
481*a3e126fdSDavid Marchand 	RTE_SET_USED(memory_order);
482*a3e126fdSDavid Marchand 	RTE_VERIFY(false);
483*a3e126fdSDavid Marchand #endif
484c889c037SMattias Rönnblom }
485c889c037SMattias Rönnblom 
486c889c037SMattias Rönnblom /**
487c889c037SMattias Rönnblom  * @warning
488c889c037SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
489c889c037SMattias Rönnblom  *
490c889c037SMattias Rönnblom  * Atomically set or clear a bit in the bitset.
491c889c037SMattias Rönnblom  *
492c889c037SMattias Rönnblom  * Assign a value to a bit in a bitset as an atomic operation, with
493c889c037SMattias Rönnblom  * the specified memory ordering.
494c889c037SMattias Rönnblom  *
495c889c037SMattias Rönnblom  * rte_bitset_atomic_assign() is multi-thread safe, provided all
496c889c037SMattias Rönnblom  * threads acting in parallel on the same bitset does so through
497c889c037SMattias Rönnblom  * @c rte_bitset_atomic_*() functions.
498c889c037SMattias Rönnblom  *
499c889c037SMattias Rönnblom  * Bits are numbered from 0 to (size - 1) (inclusive).
500c889c037SMattias Rönnblom  *
501c889c037SMattias Rönnblom  * @param bitset
502c889c037SMattias Rönnblom  *   A pointer to the array of words making up the bitset.
503c889c037SMattias Rönnblom  * @param bit_num
504c889c037SMattias Rönnblom  *   The index of the bit to be set or cleared.
505c889c037SMattias Rönnblom  * @param bit_value
506c889c037SMattias Rönnblom  *   Control if the bit should be set or cleared.
507c889c037SMattias Rönnblom  * @param memory_order
508c889c037SMattias Rönnblom  *   The memory order to use.
509c889c037SMattias Rönnblom  */
510c889c037SMattias Rönnblom __rte_experimental
511c889c037SMattias Rönnblom static inline void
512c889c037SMattias Rönnblom rte_bitset_atomic_assign(uint64_t *bitset, size_t bit_num, bool bit_value, int memory_order)
513c889c037SMattias Rönnblom {
514*a3e126fdSDavid Marchand #ifdef ALLOW_EXPERIMENTAL_API
515c889c037SMattias Rönnblom 	__RTE_BITSET_DELEGATE_N(rte_bit_atomic_assign, bitset, bit_num, bit_value, memory_order);
516*a3e126fdSDavid Marchand #else
517*a3e126fdSDavid Marchand 	RTE_SET_USED(bitset);
518*a3e126fdSDavid Marchand 	RTE_SET_USED(bit_num);
519*a3e126fdSDavid Marchand 	RTE_SET_USED(bit_value);
520*a3e126fdSDavid Marchand 	RTE_SET_USED(memory_order);
521*a3e126fdSDavid Marchand 	RTE_VERIFY(false);
522*a3e126fdSDavid Marchand #endif
523c889c037SMattias Rönnblom }
524c889c037SMattias Rönnblom 
525c889c037SMattias Rönnblom /**
526c889c037SMattias Rönnblom  * @warning
527c889c037SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
528c889c037SMattias Rönnblom  *
529c889c037SMattias Rönnblom  * Atomically change the value of a bit in the bitset.
530c889c037SMattias Rönnblom  *
531c889c037SMattias Rönnblom  * Flip a bit in a bitset as an atomic operation, with the specified
532c889c037SMattias Rönnblom  * memory ordering.
533c889c037SMattias Rönnblom  *
534c889c037SMattias Rönnblom  * rte_bitset_atomic_flip() is multi-thread safe, provided all threads
535c889c037SMattias Rönnblom  * acting in parallel on the same bitset does so through
536c889c037SMattias Rönnblom  * @c rte_bitset_atomic_*() functions.
537c889c037SMattias Rönnblom  *
538c889c037SMattias Rönnblom  * Bits are numbered from 0 to (size - 1) (inclusive).
539c889c037SMattias Rönnblom  *
540c889c037SMattias Rönnblom  * @param bitset
541c889c037SMattias Rönnblom  *   A pointer to the array of words making up the bitset.
542c889c037SMattias Rönnblom  * @param bit_num
543c889c037SMattias Rönnblom  *   The index of the bit to be flipped.
544c889c037SMattias Rönnblom  * @param memory_order
545c889c037SMattias Rönnblom  *   The memory order to use.
546c889c037SMattias Rönnblom  */
547c889c037SMattias Rönnblom __rte_experimental
548c889c037SMattias Rönnblom static inline void
549c889c037SMattias Rönnblom rte_bitset_atomic_flip(uint64_t *bitset, size_t bit_num, int memory_order)
550c889c037SMattias Rönnblom {
551*a3e126fdSDavid Marchand #ifdef ALLOW_EXPERIMENTAL_API
552c889c037SMattias Rönnblom 	__RTE_BITSET_DELEGATE_N(rte_bit_atomic_flip, bitset, bit_num, memory_order);
553*a3e126fdSDavid Marchand #else
554*a3e126fdSDavid Marchand 	RTE_SET_USED(bitset);
555*a3e126fdSDavid Marchand 	RTE_SET_USED(bit_num);
556*a3e126fdSDavid Marchand 	RTE_SET_USED(memory_order);
557*a3e126fdSDavid Marchand 	RTE_VERIFY(false);
558*a3e126fdSDavid Marchand #endif
559c889c037SMattias Rönnblom }
560c889c037SMattias Rönnblom 
561c889c037SMattias Rönnblom /**
562c889c037SMattias Rönnblom  * @warning
563c889c037SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
564c889c037SMattias Rönnblom  *
56599a11976SMattias Rönnblom  * Set all bits in the bitset.
56699a11976SMattias Rönnblom  *
56799a11976SMattias Rönnblom  * @param bitset
56899a11976SMattias Rönnblom  *   A pointer to the array of words making up the bitset.
56999a11976SMattias Rönnblom  * @param size
57099a11976SMattias Rönnblom  *   The size of the bitset (in bits).
57199a11976SMattias Rönnblom  */
57299a11976SMattias Rönnblom __rte_experimental
57399a11976SMattias Rönnblom static inline void
57499a11976SMattias Rönnblom rte_bitset_set_all(uint64_t *bitset, size_t size)
57599a11976SMattias Rönnblom {
57699a11976SMattias Rönnblom 	memset(bitset, 0xFF, RTE_BITSET_SIZE(size));
57799a11976SMattias Rönnblom }
57899a11976SMattias Rönnblom 
57999a11976SMattias Rönnblom /**
58099a11976SMattias Rönnblom  * @warning
58199a11976SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
58299a11976SMattias Rönnblom  *
58399a11976SMattias Rönnblom  * Clear all bits in the bitset.
58499a11976SMattias Rönnblom  *
58599a11976SMattias Rönnblom  * @param bitset
58699a11976SMattias Rönnblom  *   A pointer to the array of words making up the bitset.
58799a11976SMattias Rönnblom  * @param size
58899a11976SMattias Rönnblom  *   The size of the bitset (in bits).
58999a11976SMattias Rönnblom  */
59099a11976SMattias Rönnblom __rte_experimental
59199a11976SMattias Rönnblom static inline void
59299a11976SMattias Rönnblom rte_bitset_clear_all(uint64_t *bitset, size_t size)
59399a11976SMattias Rönnblom {
594*a3e126fdSDavid Marchand #ifdef ALLOW_EXPERIMENTAL_API
59599a11976SMattias Rönnblom 	rte_bitset_init(bitset, size);
596*a3e126fdSDavid Marchand #else
597*a3e126fdSDavid Marchand 	RTE_SET_USED(bitset);
598*a3e126fdSDavid Marchand 	RTE_SET_USED(size);
599*a3e126fdSDavid Marchand 	RTE_VERIFY(false);
600*a3e126fdSDavid Marchand #endif
60199a11976SMattias Rönnblom }
60299a11976SMattias Rönnblom 
60399a11976SMattias Rönnblom /**
60499a11976SMattias Rönnblom  * @warning
60599a11976SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
60699a11976SMattias Rönnblom  *
60799a11976SMattias Rönnblom  * Count all set bits (also known as the @e weight).
60899a11976SMattias Rönnblom  *
60999a11976SMattias Rönnblom  * @param bitset
61099a11976SMattias Rönnblom  *   A pointer to the array of words making up the bitset.
61199a11976SMattias Rönnblom  * @param size
61299a11976SMattias Rönnblom  *   The size of the bitset (in bits).
61399a11976SMattias Rönnblom  * @return
61499a11976SMattias Rönnblom  *   Returns the number of '1' bits in the bitset.
61599a11976SMattias Rönnblom  */
61699a11976SMattias Rönnblom __rte_experimental
61799a11976SMattias Rönnblom static inline size_t
61899a11976SMattias Rönnblom rte_bitset_count_set(const uint64_t *bitset, size_t size)
61999a11976SMattias Rönnblom {
62099a11976SMattias Rönnblom 	size_t i;
62199a11976SMattias Rönnblom 	size_t total = 0;
62299a11976SMattias Rönnblom 
62399a11976SMattias Rönnblom 	/*
62499a11976SMattias Rönnblom 	 * Unused bits in a rte_bitset are always '0', and thus are
62599a11976SMattias Rönnblom 	 * not included in this count.
62699a11976SMattias Rönnblom 	 */
62799a11976SMattias Rönnblom 	for (i = 0; i < RTE_BITSET_NUM_WORDS(size) - 1; i++)
62899a11976SMattias Rönnblom 		total += rte_popcount64(bitset[i]);
62999a11976SMattias Rönnblom 
63099a11976SMattias Rönnblom 	total += rte_popcount64(bitset[i] & __RTE_BITSET_USED_MASK(size));
63199a11976SMattias Rönnblom 
63299a11976SMattias Rönnblom 	return total;
63399a11976SMattias Rönnblom }
63499a11976SMattias Rönnblom 
63599a11976SMattias Rönnblom /**
63699a11976SMattias Rönnblom  * @warning
63799a11976SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
63899a11976SMattias Rönnblom  *
63999a11976SMattias Rönnblom  * Count all cleared bits.
64099a11976SMattias Rönnblom  *
64199a11976SMattias Rönnblom  * @param bitset
64299a11976SMattias Rönnblom  *   A pointer to the array of words making up the bitset.
64399a11976SMattias Rönnblom  * @param size
64499a11976SMattias Rönnblom  *   The size of the bitset (in bits).
64599a11976SMattias Rönnblom  * @return
64699a11976SMattias Rönnblom  *   Returns the number of '0' bits in the bitset.
64799a11976SMattias Rönnblom  */
64899a11976SMattias Rönnblom __rte_experimental
64999a11976SMattias Rönnblom static inline size_t
65099a11976SMattias Rönnblom rte_bitset_count_clear(const uint64_t *bitset, size_t size)
65199a11976SMattias Rönnblom {
652*a3e126fdSDavid Marchand #ifdef ALLOW_EXPERIMENTAL_API
65399a11976SMattias Rönnblom 	return size - rte_bitset_count_set(bitset, size);
654*a3e126fdSDavid Marchand #else
655*a3e126fdSDavid Marchand 	RTE_SET_USED(bitset);
656*a3e126fdSDavid Marchand 	RTE_SET_USED(size);
657*a3e126fdSDavid Marchand 	RTE_VERIFY(false);
658*a3e126fdSDavid Marchand #endif
65999a11976SMattias Rönnblom }
66099a11976SMattias Rönnblom 
66199a11976SMattias Rönnblom #define __RTE_BITSET_FIND_FLAG_FIND_CLEAR (1U << 0)
66299a11976SMattias Rönnblom #define __RTE_BITSET_FIND_FLAG_WRAP (1U << 1)
66399a11976SMattias Rönnblom 
66499a11976SMattias Rönnblom __rte_experimental
66599a11976SMattias Rönnblom static inline ssize_t
66699a11976SMattias Rönnblom __rte_bitset_find_nowrap(const uint64_t *bitset, size_t __rte_unused size, size_t start_bit,
66799a11976SMattias Rönnblom 		size_t len, bool find_clear)
66899a11976SMattias Rönnblom {
66999a11976SMattias Rönnblom 	size_t word_idx;
67099a11976SMattias Rönnblom 	size_t offset;
67199a11976SMattias Rönnblom 	size_t end_bit = start_bit + len;
67299a11976SMattias Rönnblom 
67399a11976SMattias Rönnblom 	RTE_ASSERT(end_bit <= size);
67499a11976SMattias Rönnblom 
67599a11976SMattias Rönnblom 	if (unlikely(len == 0))
67699a11976SMattias Rönnblom 		return -1;
67799a11976SMattias Rönnblom 
67899a11976SMattias Rönnblom 	word_idx = __RTE_BITSET_WORD_IDX(start_bit);
67999a11976SMattias Rönnblom 	offset = __RTE_BITSET_BIT_OFFSET(start_bit);
68099a11976SMattias Rönnblom 
68199a11976SMattias Rönnblom 	while (word_idx <= __RTE_BITSET_WORD_IDX(end_bit - 1)) {
68299a11976SMattias Rönnblom 		uint64_t word;
68399a11976SMattias Rönnblom 
68499a11976SMattias Rönnblom 		word = bitset[word_idx];
68599a11976SMattias Rönnblom 		if (find_clear)
68699a11976SMattias Rönnblom 			word = ~word;
68799a11976SMattias Rönnblom 
68899a11976SMattias Rönnblom 		word >>= offset;
68999a11976SMattias Rönnblom 
6905f3cd043SMattias Rönnblom 		if (word != 0) {
6915f3cd043SMattias Rönnblom 			size_t ffs = start_bit + rte_bsf64(word);
69299a11976SMattias Rönnblom 
69399a11976SMattias Rönnblom 			/*
69499a11976SMattias Rönnblom 			 * Check if set bit were among the last,
69599a11976SMattias Rönnblom 			 * unused bits, in the last word.
69699a11976SMattias Rönnblom 			 */
6975f3cd043SMattias Rönnblom 			if (unlikely(ffs >= end_bit))
69899a11976SMattias Rönnblom 				return -1;
69999a11976SMattias Rönnblom 
70099a11976SMattias Rönnblom 			return ffs;
70199a11976SMattias Rönnblom 		}
70299a11976SMattias Rönnblom 
70399a11976SMattias Rönnblom 		start_bit += (RTE_BITSET_WORD_BITS - offset);
70499a11976SMattias Rönnblom 		word_idx++;
70599a11976SMattias Rönnblom 		offset = 0;
70699a11976SMattias Rönnblom 	}
70799a11976SMattias Rönnblom 
70899a11976SMattias Rönnblom 	return -1;
70999a11976SMattias Rönnblom 
71099a11976SMattias Rönnblom }
71199a11976SMattias Rönnblom 
71299a11976SMattias Rönnblom __rte_experimental
71399a11976SMattias Rönnblom static inline ssize_t
71499a11976SMattias Rönnblom __rte_bitset_find(const uint64_t *bitset, size_t size, size_t start_bit, size_t len,
71599a11976SMattias Rönnblom 		unsigned int flags)
71699a11976SMattias Rönnblom {
717*a3e126fdSDavid Marchand #ifdef ALLOW_EXPERIMENTAL_API
71899a11976SMattias Rönnblom 	bool find_clear = flags & __RTE_BITSET_FIND_FLAG_FIND_CLEAR;
71999a11976SMattias Rönnblom 	bool may_wrap = flags & __RTE_BITSET_FIND_FLAG_WRAP;
72099a11976SMattias Rönnblom 	bool does_wrap = (start_bit + len) > size;
72199a11976SMattias Rönnblom 	ssize_t rc;
72299a11976SMattias Rönnblom 
72399a11976SMattias Rönnblom 	RTE_ASSERT(len <= size);
72499a11976SMattias Rönnblom 	if (!may_wrap)
72599a11976SMattias Rönnblom 		RTE_ASSERT(!does_wrap);
72699a11976SMattias Rönnblom 
72799a11976SMattias Rönnblom 	if (may_wrap && does_wrap) {
72899a11976SMattias Rönnblom 		size_t len0 = size - start_bit;
72999a11976SMattias Rönnblom 		size_t len1 = len - len0;
73099a11976SMattias Rönnblom 
73199a11976SMattias Rönnblom 		rc = __rte_bitset_find_nowrap(bitset, size, start_bit, len0, find_clear);
73299a11976SMattias Rönnblom 		if (rc < 0)
73399a11976SMattias Rönnblom 			rc =  __rte_bitset_find_nowrap(bitset, size, 0, len1, find_clear);
73499a11976SMattias Rönnblom 	} else
73599a11976SMattias Rönnblom 		rc = __rte_bitset_find_nowrap(bitset, size, start_bit, len, find_clear);
73699a11976SMattias Rönnblom 
73799a11976SMattias Rönnblom 	return rc;
738*a3e126fdSDavid Marchand #else
739*a3e126fdSDavid Marchand 	RTE_SET_USED(bitset);
740*a3e126fdSDavid Marchand 	RTE_SET_USED(size);
741*a3e126fdSDavid Marchand 	RTE_SET_USED(start_bit);
742*a3e126fdSDavid Marchand 	RTE_SET_USED(len);
743*a3e126fdSDavid Marchand 	RTE_SET_USED(flags);
744*a3e126fdSDavid Marchand 	RTE_VERIFY(false);
745*a3e126fdSDavid Marchand #endif
74699a11976SMattias Rönnblom }
74799a11976SMattias Rönnblom 
74899a11976SMattias Rönnblom /**
74999a11976SMattias Rönnblom  * @warning
75099a11976SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
75199a11976SMattias Rönnblom  *
75299a11976SMattias Rönnblom  * Find first bit set.
75399a11976SMattias Rönnblom  *
75499a11976SMattias Rönnblom  * Scans the bitset in the forward direction (i.e., starting at the
75599a11976SMattias Rönnblom  * least significant bit), and returns the index of the first '1'.
75699a11976SMattias Rönnblom  *
75799a11976SMattias Rönnblom  * @param bitset
75899a11976SMattias Rönnblom  *   A pointer to the array of words making up the bitset.
75999a11976SMattias Rönnblom  * @param size
76099a11976SMattias Rönnblom  *   The size of the bitset (in bits).
76199a11976SMattias Rönnblom  * @return
76299a11976SMattias Rönnblom  *   Returns the index of the least significant '1', or -1 if all
76399a11976SMattias Rönnblom  *   bits are '0'.
76499a11976SMattias Rönnblom  */
76599a11976SMattias Rönnblom __rte_experimental
76699a11976SMattias Rönnblom static inline ssize_t
76799a11976SMattias Rönnblom rte_bitset_find_first_set(const uint64_t *bitset, size_t size)
76899a11976SMattias Rönnblom {
769*a3e126fdSDavid Marchand #ifdef ALLOW_EXPERIMENTAL_API
77099a11976SMattias Rönnblom 	return __rte_bitset_find(bitset, size, 0, size, 0);
771*a3e126fdSDavid Marchand #else
772*a3e126fdSDavid Marchand 	RTE_SET_USED(bitset);
773*a3e126fdSDavid Marchand 	RTE_SET_USED(size);
774*a3e126fdSDavid Marchand 	RTE_VERIFY(false);
775*a3e126fdSDavid Marchand #endif
77699a11976SMattias Rönnblom }
77799a11976SMattias Rönnblom 
77899a11976SMattias Rönnblom /**
77999a11976SMattias Rönnblom  * @warning
78099a11976SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
78199a11976SMattias Rönnblom  *
78299a11976SMattias Rönnblom  * Find first bit set at offset.
78399a11976SMattias Rönnblom  *
78499a11976SMattias Rönnblom  * Scans the bitset in the forward direction (i.e., starting at the
78599a11976SMattias Rönnblom  * least significant bit), starting at an offset @c start_bit into the
78699a11976SMattias Rönnblom  * bitset, and returns the index of the first '1' encountered.
78799a11976SMattias Rönnblom  *
78899a11976SMattias Rönnblom  * @param bitset
78999a11976SMattias Rönnblom  *   A pointer to the array of words making up the bitset.
79099a11976SMattias Rönnblom  * @param size
79199a11976SMattias Rönnblom  *   The size of the bitset (in bits).
79299a11976SMattias Rönnblom  * @param start_bit
79399a11976SMattias Rönnblom  *   The index of the first bit to check. Must be less than @c size.
79499a11976SMattias Rönnblom  * @param len
79599a11976SMattias Rönnblom  *   The number of bits to scan. @c start_bit + @c len must be less
79699a11976SMattias Rönnblom  *   than or equal to @c size.
79799a11976SMattias Rönnblom  * @return
79899a11976SMattias Rönnblom  *   Returns the index of the least significant '1', or -1 if all
79999a11976SMattias Rönnblom  *   bits are '0'.
80099a11976SMattias Rönnblom  */
80199a11976SMattias Rönnblom __rte_experimental
80299a11976SMattias Rönnblom static inline ssize_t
80399a11976SMattias Rönnblom rte_bitset_find_set(const uint64_t *bitset, size_t size, size_t start_bit, size_t len)
80499a11976SMattias Rönnblom {
805*a3e126fdSDavid Marchand #ifdef ALLOW_EXPERIMENTAL_API
80699a11976SMattias Rönnblom 	return __rte_bitset_find(bitset, size, start_bit, len, 0);
807*a3e126fdSDavid Marchand #else
808*a3e126fdSDavid Marchand 	RTE_SET_USED(bitset);
809*a3e126fdSDavid Marchand 	RTE_SET_USED(size);
810*a3e126fdSDavid Marchand 	RTE_SET_USED(start_bit);
811*a3e126fdSDavid Marchand 	RTE_SET_USED(len);
812*a3e126fdSDavid Marchand 	RTE_VERIFY(false);
813*a3e126fdSDavid Marchand #endif
81499a11976SMattias Rönnblom }
81599a11976SMattias Rönnblom 
81699a11976SMattias Rönnblom /**
81799a11976SMattias Rönnblom  * @warning
81899a11976SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
81999a11976SMattias Rönnblom  *
82099a11976SMattias Rönnblom  * Find first bit set at offset, with wrap-around.
82199a11976SMattias Rönnblom  *
82299a11976SMattias Rönnblom  * Scans the bitset in the forward direction (i.e., starting at the
82399a11976SMattias Rönnblom  * least significant bit), starting at an offset @c start_bit into the
82499a11976SMattias Rönnblom  * bitset. If no '1' is encountered before the end of the bitset, the search
82599a11976SMattias Rönnblom  * will continue at index 0.
82699a11976SMattias Rönnblom  *
82799a11976SMattias Rönnblom  * @param bitset
82899a11976SMattias Rönnblom  *   A pointer to the array of words making up the bitset.
82999a11976SMattias Rönnblom  * @param size
83099a11976SMattias Rönnblom  *   The size of the bitset (in bits).
83199a11976SMattias Rönnblom  * @param start_bit
83299a11976SMattias Rönnblom  *   The index of the first bit to check. Must be less than @c size.
83399a11976SMattias Rönnblom  * @param len
83499a11976SMattias Rönnblom  *   The number of bits to scan. @c start_bit + @c len must be less
83599a11976SMattias Rönnblom  *   than or equal to @c size.
83699a11976SMattias Rönnblom  * @return
83799a11976SMattias Rönnblom  *   Returns the index of the least significant '1', or -1 if all
83899a11976SMattias Rönnblom  *   bits are '0'.
83999a11976SMattias Rönnblom  */
84099a11976SMattias Rönnblom __rte_experimental
84199a11976SMattias Rönnblom static inline ssize_t
84299a11976SMattias Rönnblom rte_bitset_find_set_wrap(const uint64_t *bitset, size_t size, size_t start_bit, size_t len)
84399a11976SMattias Rönnblom {
844*a3e126fdSDavid Marchand #ifdef ALLOW_EXPERIMENTAL_API
84599a11976SMattias Rönnblom 	return __rte_bitset_find(bitset, size, start_bit, len, __RTE_BITSET_FIND_FLAG_WRAP);
846*a3e126fdSDavid Marchand #else
847*a3e126fdSDavid Marchand 	RTE_SET_USED(bitset);
848*a3e126fdSDavid Marchand 	RTE_SET_USED(size);
849*a3e126fdSDavid Marchand 	RTE_SET_USED(start_bit);
850*a3e126fdSDavid Marchand 	RTE_SET_USED(len);
851*a3e126fdSDavid Marchand 	RTE_VERIFY(false);
852*a3e126fdSDavid Marchand #endif
85399a11976SMattias Rönnblom }
85499a11976SMattias Rönnblom 
85599a11976SMattias Rönnblom /**
85699a11976SMattias Rönnblom  * @warning
85799a11976SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
85899a11976SMattias Rönnblom  *
85999a11976SMattias Rönnblom  * Find first cleared bit.
86099a11976SMattias Rönnblom  *
86199a11976SMattias Rönnblom  * Scans the bitset in the forward direction (i.e., starting at the
86299a11976SMattias Rönnblom  * least significant bit), and returns the index of the first '0'.
86399a11976SMattias Rönnblom  *
86499a11976SMattias Rönnblom  * @param bitset
86599a11976SMattias Rönnblom  *   A pointer to the array of words making up the bitset.
86699a11976SMattias Rönnblom  * @param size
86799a11976SMattias Rönnblom  *   The size of the bitset (in bits).
86899a11976SMattias Rönnblom  * @return
86999a11976SMattias Rönnblom  *   Returns the index of the least significant '0', or -1 if all
87099a11976SMattias Rönnblom  *   bits are '1'.
87199a11976SMattias Rönnblom  */
87299a11976SMattias Rönnblom __rte_experimental
87399a11976SMattias Rönnblom static inline ssize_t
87499a11976SMattias Rönnblom rte_bitset_find_first_clear(const uint64_t *bitset, size_t size)
87599a11976SMattias Rönnblom {
876*a3e126fdSDavid Marchand #ifdef ALLOW_EXPERIMENTAL_API
87799a11976SMattias Rönnblom 	return __rte_bitset_find(bitset, size, 0, size, __RTE_BITSET_FIND_FLAG_FIND_CLEAR);
878*a3e126fdSDavid Marchand #else
879*a3e126fdSDavid Marchand 	RTE_SET_USED(bitset);
880*a3e126fdSDavid Marchand 	RTE_SET_USED(size);
881*a3e126fdSDavid Marchand 	RTE_VERIFY(false);
882*a3e126fdSDavid Marchand #endif
88399a11976SMattias Rönnblom }
88499a11976SMattias Rönnblom 
88599a11976SMattias Rönnblom /**
88699a11976SMattias Rönnblom  * @warning
88799a11976SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
88899a11976SMattias Rönnblom  *
88999a11976SMattias Rönnblom  * Find first cleared bit at offset.
89099a11976SMattias Rönnblom  *
89199a11976SMattias Rönnblom  * Scans the bitset in the forward direction (i.e., starting at the
89299a11976SMattias Rönnblom  * least significant bit), starting at an offset @c start_bit into the
89399a11976SMattias Rönnblom  * bitset, and returns the index of the first '0' encountered.
89499a11976SMattias Rönnblom  *
89599a11976SMattias Rönnblom  * @param bitset
89699a11976SMattias Rönnblom  *   A pointer to the array of words making up the bitset.
89799a11976SMattias Rönnblom  * @param size
89899a11976SMattias Rönnblom  *   The size of the bitset (in bits).
89999a11976SMattias Rönnblom  * @param start_bit
90099a11976SMattias Rönnblom  *   The index of the first bit to check. Must be less than @c size.
90199a11976SMattias Rönnblom  * @param len
90299a11976SMattias Rönnblom  *   The number of bits to scan. @c start_bit + @c len must be less
90399a11976SMattias Rönnblom  *   than or equal to @c size.
90499a11976SMattias Rönnblom  * @return
90599a11976SMattias Rönnblom  *   Returns the index of the least significant '0', or -1 if all
90699a11976SMattias Rönnblom  *   bits are '1'.
90799a11976SMattias Rönnblom  */
90899a11976SMattias Rönnblom __rte_experimental
90999a11976SMattias Rönnblom static inline ssize_t
91099a11976SMattias Rönnblom rte_bitset_find_clear(const uint64_t *bitset, size_t size, size_t start_bit, size_t len)
91199a11976SMattias Rönnblom {
912*a3e126fdSDavid Marchand #ifdef ALLOW_EXPERIMENTAL_API
91399a11976SMattias Rönnblom 	return __rte_bitset_find(bitset, size, start_bit, len, __RTE_BITSET_FIND_FLAG_FIND_CLEAR);
914*a3e126fdSDavid Marchand #else
915*a3e126fdSDavid Marchand 	RTE_SET_USED(bitset);
916*a3e126fdSDavid Marchand 	RTE_SET_USED(size);
917*a3e126fdSDavid Marchand 	RTE_SET_USED(start_bit);
918*a3e126fdSDavid Marchand 	RTE_SET_USED(len);
919*a3e126fdSDavid Marchand 	RTE_VERIFY(false);
920*a3e126fdSDavid Marchand #endif
92199a11976SMattias Rönnblom }
92299a11976SMattias Rönnblom 
92399a11976SMattias Rönnblom /**
92499a11976SMattias Rönnblom  * @warning
92599a11976SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
92699a11976SMattias Rönnblom  *
92799a11976SMattias Rönnblom  * Find first cleared bit at offset, with wrap-around.
92899a11976SMattias Rönnblom  *
92999a11976SMattias Rönnblom  * Scans the bitset in the forward direction (i.e., starting at the
93099a11976SMattias Rönnblom  * least significant bit), starting at an offset @c start_bit into the
93199a11976SMattias Rönnblom  * bitset. If no '0' is encountered before the end of the bitset, the
93299a11976SMattias Rönnblom  * search will continue at index 0.
93399a11976SMattias Rönnblom  *
93499a11976SMattias Rönnblom  * @param bitset
93599a11976SMattias Rönnblom  *   A pointer to the array of words making up the bitset.
93699a11976SMattias Rönnblom  * @param size
93799a11976SMattias Rönnblom  *   The size of the bitset (in bits).
93899a11976SMattias Rönnblom  * @param start_bit
93999a11976SMattias Rönnblom  *   The index of the first bit to check. Must be less than @c size.
94099a11976SMattias Rönnblom  * @param len
94199a11976SMattias Rönnblom  *   The number of bits to scan. @c start_bit + @c len must be less
94299a11976SMattias Rönnblom  *   than or equal to @c size.
94399a11976SMattias Rönnblom  * @return
94499a11976SMattias Rönnblom  *   Returns the index of the least significant '0', or -1 if all
94599a11976SMattias Rönnblom  *   bits are '1'.
94699a11976SMattias Rönnblom  */
94799a11976SMattias Rönnblom __rte_experimental
94899a11976SMattias Rönnblom static inline ssize_t
94999a11976SMattias Rönnblom rte_bitset_find_clear_wrap(const uint64_t *bitset, size_t size, size_t start_bit, size_t len)
95099a11976SMattias Rönnblom {
951*a3e126fdSDavid Marchand #ifdef ALLOW_EXPERIMENTAL_API
95299a11976SMattias Rönnblom 	return __rte_bitset_find(bitset, size, start_bit, len,
95399a11976SMattias Rönnblom 		__RTE_BITSET_FIND_FLAG_FIND_CLEAR | __RTE_BITSET_FIND_FLAG_WRAP);
954*a3e126fdSDavid Marchand #else
955*a3e126fdSDavid Marchand 	RTE_SET_USED(bitset);
956*a3e126fdSDavid Marchand 	RTE_SET_USED(size);
957*a3e126fdSDavid Marchand 	RTE_SET_USED(start_bit);
958*a3e126fdSDavid Marchand 	RTE_SET_USED(len);
959*a3e126fdSDavid Marchand 	RTE_VERIFY(false);
960*a3e126fdSDavid Marchand #endif
96199a11976SMattias Rönnblom }
96299a11976SMattias Rönnblom 
96399a11976SMattias Rönnblom /**
96499a11976SMattias Rönnblom  * @warning
96599a11976SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
96699a11976SMattias Rönnblom  *
96799a11976SMattias Rönnblom  * Copy bitset.
96899a11976SMattias Rönnblom  *
96999a11976SMattias Rönnblom  * Copy the bits of the @c src_bitset to the @c dst_bitset.
97099a11976SMattias Rönnblom  *
97199a11976SMattias Rönnblom  * The bitsets may not overlap and must be of equal size.
97299a11976SMattias Rönnblom  *
97399a11976SMattias Rönnblom  * @param dst_bitset
97499a11976SMattias Rönnblom  *   A pointer to the array of words making up the bitset.
97599a11976SMattias Rönnblom  * @param src_bitset
97699a11976SMattias Rönnblom  *   A pointer to the array of words making up the bitset.
97799a11976SMattias Rönnblom  * @param size
97899a11976SMattias Rönnblom  *   The size of the bitsets (in bits).
97999a11976SMattias Rönnblom  */
98099a11976SMattias Rönnblom __rte_experimental
98199a11976SMattias Rönnblom static inline void
98299a11976SMattias Rönnblom rte_bitset_copy(uint64_t *__rte_restrict dst_bitset, const uint64_t *__rte_restrict src_bitset,
98399a11976SMattias Rönnblom 		size_t size)
98499a11976SMattias Rönnblom {
98599a11976SMattias Rönnblom 	rte_memcpy(dst_bitset, src_bitset, RTE_BITSET_SIZE(size));
98699a11976SMattias Rönnblom }
98799a11976SMattias Rönnblom 
98899a11976SMattias Rönnblom /**
98999a11976SMattias Rönnblom  * @warning
99099a11976SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
99199a11976SMattias Rönnblom  *
99299a11976SMattias Rönnblom  * Bitwise or two bitsets.
99399a11976SMattias Rönnblom  *
99499a11976SMattias Rönnblom  * Perform a bitwise OR operation on all bits in the two equal-size
99599a11976SMattias Rönnblom  * bitsets @c src_bitset0 and @c src_bitset1, and store the results in
99699a11976SMattias Rönnblom  * @c dst_bitset.
99799a11976SMattias Rönnblom  *
99899a11976SMattias Rönnblom  * @param dst_bitset
99999a11976SMattias Rönnblom  *   A pointer to the destination bitset.
100099a11976SMattias Rönnblom  * @param src_bitset0
100199a11976SMattias Rönnblom  *   A pointer to the first source bitset.
100299a11976SMattias Rönnblom  * @param src_bitset1
100399a11976SMattias Rönnblom  *   A pointer to the second source bitset.
100499a11976SMattias Rönnblom  * @param size
100599a11976SMattias Rönnblom  *   The size of the bitsets (in bits).
100699a11976SMattias Rönnblom  */
100799a11976SMattias Rönnblom __rte_experimental
100899a11976SMattias Rönnblom static inline void
100999a11976SMattias Rönnblom rte_bitset_or(uint64_t *dst_bitset, const uint64_t *src_bitset0, const uint64_t *src_bitset1,
101099a11976SMattias Rönnblom 		size_t size)
101199a11976SMattias Rönnblom {
101299a11976SMattias Rönnblom 	size_t i;
101399a11976SMattias Rönnblom 
101499a11976SMattias Rönnblom 	for (i = 0; i < RTE_BITSET_NUM_WORDS(size); i++)
101599a11976SMattias Rönnblom 		dst_bitset[i] = src_bitset0[i] | src_bitset1[i];
101699a11976SMattias Rönnblom }
101799a11976SMattias Rönnblom 
101899a11976SMattias Rönnblom /**
101999a11976SMattias Rönnblom  * @warning
102099a11976SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
102199a11976SMattias Rönnblom  *
102299a11976SMattias Rönnblom  * Bitwise and two bitsets.
102399a11976SMattias Rönnblom  *
102499a11976SMattias Rönnblom  * Perform a bitwise AND operation on all bits in the two equal-size
102599a11976SMattias Rönnblom  * bitsets @c src_bitset0 and @c src_bitset1, and store the result in
102699a11976SMattias Rönnblom  * @c dst_bitset.
102799a11976SMattias Rönnblom  *
102899a11976SMattias Rönnblom  * @param dst_bitset
102999a11976SMattias Rönnblom  *   A pointer to the destination bitset.
103099a11976SMattias Rönnblom  * @param src_bitset0
103199a11976SMattias Rönnblom  *   A pointer to the first source bitset.
103299a11976SMattias Rönnblom  * @param src_bitset1
103399a11976SMattias Rönnblom  *   A pointer to the second source bitset.
103499a11976SMattias Rönnblom  * @param size
103599a11976SMattias Rönnblom  *   The size of the bitsets (in bits).
103699a11976SMattias Rönnblom  */
103799a11976SMattias Rönnblom __rte_experimental
103899a11976SMattias Rönnblom static inline void
103999a11976SMattias Rönnblom rte_bitset_and(uint64_t *dst_bitset, const uint64_t *src_bitset0, const uint64_t *src_bitset1,
104099a11976SMattias Rönnblom 		size_t size)
104199a11976SMattias Rönnblom {
104299a11976SMattias Rönnblom 	size_t i;
104399a11976SMattias Rönnblom 
104499a11976SMattias Rönnblom 	for (i = 0; i < RTE_BITSET_NUM_WORDS(size); i++)
104599a11976SMattias Rönnblom 		dst_bitset[i] = src_bitset0[i] & src_bitset1[i];
104699a11976SMattias Rönnblom }
104799a11976SMattias Rönnblom 
104899a11976SMattias Rönnblom /**
104999a11976SMattias Rönnblom  * @warning
105099a11976SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
105199a11976SMattias Rönnblom  *
105299a11976SMattias Rönnblom  * Bitwise xor two bitsets.
105399a11976SMattias Rönnblom  *
105499a11976SMattias Rönnblom  * Perform a bitwise XOR operation on all bits in the two equal-size
105599a11976SMattias Rönnblom  * bitsets @c src_bitset0 and @c src_bitset1, and store the result in
105699a11976SMattias Rönnblom  * @c dst_bitset.
105799a11976SMattias Rönnblom  *
105899a11976SMattias Rönnblom  * @param dst_bitset
105999a11976SMattias Rönnblom  *   A pointer to the destination bitset.
106099a11976SMattias Rönnblom  * @param src_bitset0
106199a11976SMattias Rönnblom  *   A pointer to the first source bitset.
106299a11976SMattias Rönnblom  * @param src_bitset1
106399a11976SMattias Rönnblom  *   A pointer to the second source bitset.
106499a11976SMattias Rönnblom  * @param size
106599a11976SMattias Rönnblom  *   The size of the bitsets (in bits).
106699a11976SMattias Rönnblom  */
106799a11976SMattias Rönnblom __rte_experimental
106899a11976SMattias Rönnblom static inline void
106999a11976SMattias Rönnblom rte_bitset_xor(uint64_t *dst_bitset, const uint64_t *src_bitset0, const uint64_t *src_bitset1,
107099a11976SMattias Rönnblom 		size_t size)
107199a11976SMattias Rönnblom {
107299a11976SMattias Rönnblom 	size_t i;
107399a11976SMattias Rönnblom 
107499a11976SMattias Rönnblom 	for (i = 0; i < RTE_BITSET_NUM_WORDS(size); i++)
107599a11976SMattias Rönnblom 		dst_bitset[i] = src_bitset0[i] ^ src_bitset1[i];
107699a11976SMattias Rönnblom }
107799a11976SMattias Rönnblom 
107899a11976SMattias Rönnblom /**
107999a11976SMattias Rönnblom  * @warning
108099a11976SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
108199a11976SMattias Rönnblom  *
108299a11976SMattias Rönnblom  * Compute the bitwise complement of a bitset.
108399a11976SMattias Rönnblom  *
108499a11976SMattias Rönnblom  * Flip every bit in the @c src_bitset, and store the result in @c
108599a11976SMattias Rönnblom  * dst_bitset.
108699a11976SMattias Rönnblom  *
108799a11976SMattias Rönnblom  * @param dst_bitset
108899a11976SMattias Rönnblom  *   A pointer to the destination bitset.
108999a11976SMattias Rönnblom  * @param src_bitset
109099a11976SMattias Rönnblom  *   A pointer to the source bitset.
109199a11976SMattias Rönnblom  * @param size
109299a11976SMattias Rönnblom  *   The size of the bitsets (in bits).
109399a11976SMattias Rönnblom  */
109499a11976SMattias Rönnblom __rte_experimental
109599a11976SMattias Rönnblom static inline void
109699a11976SMattias Rönnblom rte_bitset_complement(uint64_t *dst_bitset, const uint64_t *src_bitset, size_t size)
109799a11976SMattias Rönnblom {
109899a11976SMattias Rönnblom 	size_t i;
109999a11976SMattias Rönnblom 
110099a11976SMattias Rönnblom 	for (i = 0; i < RTE_BITSET_NUM_WORDS(size); i++)
110199a11976SMattias Rönnblom 		dst_bitset[i] = ~src_bitset[i];
110299a11976SMattias Rönnblom }
110399a11976SMattias Rönnblom 
110499a11976SMattias Rönnblom /**
110599a11976SMattias Rönnblom  * @warning
110699a11976SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
110799a11976SMattias Rönnblom  *
110899a11976SMattias Rönnblom  * Shift bitset left.
110999a11976SMattias Rönnblom  *
111099a11976SMattias Rönnblom  * Perform a logical shift left of (multiply) @c src_bitset, and store
111199a11976SMattias Rönnblom  * the result in @c dst_bitset.
111299a11976SMattias Rönnblom  *
111399a11976SMattias Rönnblom  * @param dst_bitset
111499a11976SMattias Rönnblom  *   A pointer to the destination bitset.
111599a11976SMattias Rönnblom  * @param src_bitset
111699a11976SMattias Rönnblom  *   A pointer to the source bitset.
111799a11976SMattias Rönnblom  * @param size
111899a11976SMattias Rönnblom  *   The size of the bitsets (in bits).
111999a11976SMattias Rönnblom  * @param shift_bits
112099a11976SMattias Rönnblom  *   The number of bits to shift the bitset.
112199a11976SMattias Rönnblom  */
112299a11976SMattias Rönnblom __rte_experimental
112399a11976SMattias Rönnblom static inline void
112499a11976SMattias Rönnblom rte_bitset_shift_left(uint64_t *dst_bitset, const uint64_t *src_bitset, size_t size,
112599a11976SMattias Rönnblom 		size_t shift_bits)
112699a11976SMattias Rönnblom {
112799a11976SMattias Rönnblom 	const int src_word_offset = shift_bits / RTE_BITSET_WORD_BITS;
112899a11976SMattias Rönnblom 	const int src_bit_offset = shift_bits % RTE_BITSET_WORD_BITS;
112999a11976SMattias Rönnblom 	unsigned int dst_idx;
113099a11976SMattias Rönnblom 
113199a11976SMattias Rönnblom 	for (dst_idx = 0; dst_idx < RTE_BITSET_NUM_WORDS(size); dst_idx++) {
113299a11976SMattias Rönnblom 		int src_high_idx = dst_idx - src_word_offset;
113399a11976SMattias Rönnblom 		uint64_t low_bits = 0;
113499a11976SMattias Rönnblom 		uint64_t high_bits = 0;
113599a11976SMattias Rönnblom 
113699a11976SMattias Rönnblom 		if (src_high_idx >= 0) {
113799a11976SMattias Rönnblom 			int src_low_idx = src_high_idx - 1;
113899a11976SMattias Rönnblom 
113999a11976SMattias Rönnblom 			high_bits = src_bitset[src_high_idx] << src_bit_offset;
114099a11976SMattias Rönnblom 
114199a11976SMattias Rönnblom 			if (src_bit_offset > 0 && src_low_idx >= 0)
114299a11976SMattias Rönnblom 				low_bits = src_bitset[src_low_idx] >>
114399a11976SMattias Rönnblom 					(RTE_BITSET_WORD_BITS - src_bit_offset);
114499a11976SMattias Rönnblom 		}
114599a11976SMattias Rönnblom 		dst_bitset[dst_idx] = low_bits | high_bits;
114699a11976SMattias Rönnblom 	}
114799a11976SMattias Rönnblom }
114899a11976SMattias Rönnblom 
114999a11976SMattias Rönnblom /**
115099a11976SMattias Rönnblom  * @warning
115199a11976SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
115299a11976SMattias Rönnblom  *
115399a11976SMattias Rönnblom  * Shift bitset right.
115499a11976SMattias Rönnblom  *
115599a11976SMattias Rönnblom  * Perform a logical shift right of (divide) @c src_bitset, and store
115699a11976SMattias Rönnblom  * the result in @c dst_bitset.
115799a11976SMattias Rönnblom  *
115899a11976SMattias Rönnblom  * @param dst_bitset
115999a11976SMattias Rönnblom  *   A pointer to the destination bitset.
116099a11976SMattias Rönnblom  * @param src_bitset
116199a11976SMattias Rönnblom  *   A pointer to the source bitset.
116299a11976SMattias Rönnblom  * @param size
116399a11976SMattias Rönnblom  *   The size of the bitsets (in bits).
116499a11976SMattias Rönnblom  * @param shift_bits
116599a11976SMattias Rönnblom  *   The number of bits to shift the bitset.
116699a11976SMattias Rönnblom  */
116799a11976SMattias Rönnblom __rte_experimental
116899a11976SMattias Rönnblom static inline void
116999a11976SMattias Rönnblom rte_bitset_shift_right(uint64_t *dst_bitset, const uint64_t *src_bitset, size_t size,
117099a11976SMattias Rönnblom 		size_t shift_bits)
117199a11976SMattias Rönnblom {
117299a11976SMattias Rönnblom 	const int num_words = RTE_BITSET_NUM_WORDS(size);
117399a11976SMattias Rönnblom 	const uint64_t used_mask = __RTE_BITSET_USED_MASK(size);
117499a11976SMattias Rönnblom 	const int src_word_offset = shift_bits / RTE_BITSET_WORD_BITS;
117599a11976SMattias Rönnblom 	const int src_bit_offset = shift_bits % RTE_BITSET_WORD_BITS;
117699a11976SMattias Rönnblom 	int dst_idx;
117799a11976SMattias Rönnblom 
117899a11976SMattias Rönnblom 	for (dst_idx = 0; dst_idx < num_words; dst_idx++) {
117999a11976SMattias Rönnblom 		int src_low_idx = src_word_offset + dst_idx;
118099a11976SMattias Rönnblom 		int src_high_idx = src_low_idx + 1;
118199a11976SMattias Rönnblom 		uint64_t src_low_word_bits = 0;
118299a11976SMattias Rönnblom 		uint64_t src_high_word_bits = 0;
118399a11976SMattias Rönnblom 
118499a11976SMattias Rönnblom 		if (src_low_idx < num_words) {
118599a11976SMattias Rönnblom 			src_low_word_bits = src_bitset[src_low_idx];
118699a11976SMattias Rönnblom 
118799a11976SMattias Rönnblom 			if (src_low_idx == (num_words - 1))
118899a11976SMattias Rönnblom 				src_low_word_bits &= used_mask;
118999a11976SMattias Rönnblom 
119099a11976SMattias Rönnblom 			src_low_word_bits >>= src_bit_offset;
119199a11976SMattias Rönnblom 
119299a11976SMattias Rönnblom 			if (src_bit_offset > 0 && src_high_idx < num_words) {
119399a11976SMattias Rönnblom 				src_high_word_bits = src_bitset[src_high_idx];
119499a11976SMattias Rönnblom 
119599a11976SMattias Rönnblom 				if (src_high_idx == (num_words - 1))
119699a11976SMattias Rönnblom 					src_high_word_bits &= used_mask;
119799a11976SMattias Rönnblom 
119899a11976SMattias Rönnblom 				src_high_word_bits <<= (RTE_BITSET_WORD_BITS - src_bit_offset);
119999a11976SMattias Rönnblom 			}
120099a11976SMattias Rönnblom 		}
120199a11976SMattias Rönnblom 		dst_bitset[dst_idx] = src_low_word_bits | src_high_word_bits;
120299a11976SMattias Rönnblom 	}
120399a11976SMattias Rönnblom }
120499a11976SMattias Rönnblom 
120599a11976SMattias Rönnblom /**
120699a11976SMattias Rönnblom  * @warning
120799a11976SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
120899a11976SMattias Rönnblom  *
120999a11976SMattias Rönnblom  * Compare two bitsets.
121099a11976SMattias Rönnblom  *
121199a11976SMattias Rönnblom  * Compare two bitsets for equality.
121299a11976SMattias Rönnblom  *
121399a11976SMattias Rönnblom  * @param bitset_a
121499a11976SMattias Rönnblom  *   A pointer to the destination bitset.
121599a11976SMattias Rönnblom  * @param bitset_b
121699a11976SMattias Rönnblom  *   A pointer to the source bitset.
121799a11976SMattias Rönnblom  * @param size
121899a11976SMattias Rönnblom  *   The size of the bitsets (in bits).
121999a11976SMattias Rönnblom  */
122099a11976SMattias Rönnblom __rte_experimental
122199a11976SMattias Rönnblom static inline bool
122299a11976SMattias Rönnblom rte_bitset_equal(const uint64_t *bitset_a, const uint64_t *bitset_b, size_t size)
122399a11976SMattias Rönnblom {
122499a11976SMattias Rönnblom 	size_t i;
122599a11976SMattias Rönnblom 	uint64_t last_a, last_b;
122699a11976SMattias Rönnblom 
122799a11976SMattias Rönnblom 	for (i = 0; i < RTE_BITSET_NUM_WORDS(size) - 1; i++)
122899a11976SMattias Rönnblom 		if (bitset_a[i] != bitset_b[i])
122999a11976SMattias Rönnblom 			return false;
123099a11976SMattias Rönnblom 
123199a11976SMattias Rönnblom 	last_a = bitset_a[i] << __RTE_BITSET_UNUSED(size);
123299a11976SMattias Rönnblom 	last_b = bitset_b[i] << __RTE_BITSET_UNUSED(size);
123399a11976SMattias Rönnblom 
123499a11976SMattias Rönnblom 	return last_a == last_b;
123599a11976SMattias Rönnblom }
123699a11976SMattias Rönnblom 
123799a11976SMattias Rönnblom /**
123899a11976SMattias Rönnblom  * @warning
123999a11976SMattias Rönnblom  * @b EXPERIMENTAL: this API may change without prior notice.
124099a11976SMattias Rönnblom  *
124199a11976SMattias Rönnblom  * Converts a bitset to a string.
124299a11976SMattias Rönnblom  *
124399a11976SMattias Rönnblom  * This function prints a string representation of the bitstring to
124499a11976SMattias Rönnblom  * the supplied buffer.
124599a11976SMattias Rönnblom  *
124699a11976SMattias Rönnblom  * Each bit is represented either by '0' or '1' in the output, with
124799a11976SMattias Rönnblom  * the first (left-most) character in the output being the most
124899a11976SMattias Rönnblom  * significant bit. The resulting string is NUL terminated.
124999a11976SMattias Rönnblom  *
125099a11976SMattias Rönnblom  * @param bitset
125199a11976SMattias Rönnblom  *   A pointer to the array of bitset 64-bit words.
125299a11976SMattias Rönnblom  * @param size
125399a11976SMattias Rönnblom  *   The number of bits the bitset represent.
125499a11976SMattias Rönnblom  * @param buf
125599a11976SMattias Rönnblom  *   A buffer to hold the output.
125699a11976SMattias Rönnblom  * @param capacity
125799a11976SMattias Rönnblom  *   The size of the buffer. Must be @c size + 1 or larger.
125899a11976SMattias Rönnblom  * @return
125999a11976SMattias Rönnblom  *   Returns the number of bytes written (i.e., @c size + 1), or -EINVAL
126099a11976SMattias Rönnblom  *   in case the buffer capacity was too small.
126199a11976SMattias Rönnblom  */
126299a11976SMattias Rönnblom __rte_experimental
126399a11976SMattias Rönnblom ssize_t
126499a11976SMattias Rönnblom rte_bitset_to_str(const uint64_t *bitset, size_t size, char *buf, size_t capacity);
126599a11976SMattias Rönnblom 
126699a11976SMattias Rönnblom #ifdef __cplusplus
126799a11976SMattias Rönnblom }
126899a11976SMattias Rönnblom #endif
126999a11976SMattias Rönnblom 
127099a11976SMattias Rönnblom #endif /* _RTE_BITSET_H_ */
1271