diff --git a/app/test/test_bitcount.c b/app/test/test_bitcount.c index 83c68feb7bf..4f34d7c90fa 100644 --- a/app/test/test_bitcount.c +++ b/app/test/test_bitcount.c @@ -112,6 +112,42 @@ test_popcount64(void) return 0; } +static int +test_bit_scan_forward(void) +{ + unsigned int bit_nr; + + TEST_ASSERT((bit_nr = rte_ffs32(0)) == 0, + "rte_ffs32 returned unexpected %d", bit_nr); + + for (int i = 0; i < 32; ++i) { + uint32_t n = RTE_BIT32(i); + + TEST_ASSERT((bit_nr = rte_ffs32(n)) == (unsigned int)(i+1), + "rte_ffs32 returned unexpected %d", bit_nr); + } + + return TEST_SUCCESS; +} + +static int +test_bit_scan_forward64(void) +{ + unsigned int bit_nr; + + TEST_ASSERT((bit_nr = rte_ffs64(0)) == 0, + "rte_ffs64 returned unexpected %d", bit_nr); + + for (int i = 0; i < 64; ++i) { + uint64_t n = RTE_BIT64(i); + + TEST_ASSERT((bit_nr = rte_ffs64(n)) == (unsigned int)(i+1), + "rte_ffs64 returned unexpected %d", bit_nr); + } + + return TEST_SUCCESS; +} + static struct unit_test_suite bitcount_test_suite = { .suite_name = "bitcount autotest", .setup = NULL, @@ -123,6 +159,8 @@ static struct unit_test_suite bitcount_test_suite = { TEST_CASE(test_ctz64), TEST_CASE(test_popcount32), TEST_CASE(test_popcount64), + TEST_CASE(test_bit_scan_forward), + TEST_CASE(test_bit_scan_forward64), TEST_CASES_END() } }; diff --git a/lib/eal/include/rte_bitops.h b/lib/eal/include/rte_bitops.h index deb1fd43f25..b9a6af381b3 100644 --- a/lib/eal/include/rte_bitops.h +++ b/lib/eal/include/rte_bitops.h @@ -958,6 +958,54 @@ rte_popcount64(uint64_t v) return (unsigned int)__popcnt64(v); } +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Search v from least significant bit (LSB) to the most + * significant bit (MSB) for a set bit (1). + * + * @param v + * The value. + * @return + * Bit index + 1 if a set bit is found, zero otherwise. + */ +__rte_experimental +static inline unsigned int +rte_ffs32(uint32_t v) +{ + unsigned long rv; + + if (_BitScanForward(&rv, v) == 0) + return 0; + + return (unsigned int)rv + 1; +} + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Search v from least significant bit (LSB) to the most + * significant bit (MSB) for a set bit (1). + * + * @param v + * The value. + * @return + * Bit index + 1 if a set bit is found, zero otherwise. + */ +__rte_experimental +static inline unsigned int +rte_ffs64(uint64_t v) +{ + unsigned long rv; + + if (_BitScanForward64(&rv, v) == 0) + return 0; + + return (unsigned int)rv + 1; +} + #else /** @@ -1044,6 +1092,44 @@ rte_popcount64(uint64_t v) return (unsigned int)__builtin_popcountll(v); } +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Search v from least significant bit (LSB) to the most + * significant bit (MSB) for a set bit (1). + * + * @param v + * The value. + * @return + * Bit index + 1 if a set bit is found, zero otherwise. + */ +__rte_experimental +static inline unsigned int +rte_ffs32(uint32_t v) +{ + return (unsigned int)__builtin_ffs(v); +} + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Search v from least significant bit (LSB) to the most + * significant bit (MSB) for a set bit (1). + * + * @param v + * The value. + * @return + * Bit index + 1 if a set bit is found, zero otherwise. + */ +__rte_experimental +static inline unsigned int +rte_ffs64(uint64_t v) +{ + return (unsigned int)__builtin_ffsll(v); +} + #endif /**