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