eal: add 64-bit bsf and 32-bit safe bsf functions

Add an rte_bsf64 function that follows the convention of existing
rte_bsf32 function. Also, add missing implementation for safe
version of rte_bsf32, and implement unit tests for all recently
added bsf varieties.

Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
This commit is contained in:
Anatoly Burakov 2018-12-20 12:09:48 +00:00 committed by Thomas Monjalon
parent cc7ddb00da
commit 4e261f5519
5 changed files with 86 additions and 18 deletions

View File

@ -649,19 +649,13 @@ calc_mem_size(uint32_t nb_mbufs, uint32_t mbuf_sz, size_t pgsz, size_t *out)
return 0;
}
static inline uint32_t
bsf64(uint64_t v)
{
return (uint32_t)__builtin_ctzll(v);
}
static inline uint32_t
log2_u64(uint64_t v)
{
if (v == 0)
return 0;
v = rte_align64pow2(v);
return bsf64(v);
return rte_bsf64(v);
}
static int

View File

@ -115,7 +115,9 @@ API Changes
=========================================================
* eal: Function ``rte_bsf64`` in ``rte_bitmap.h`` has been renamed to
``rte_bsf64_safe`` and moved to ``rte_common.h``.
``rte_bsf64_safe`` and moved to ``rte_common.h``. A new ``rte_bsf64`` function
has been added in ``rte_common.h`` that follows convention set by existing
``rte_bsf32`` function.
* eal: Segment fd API on Linux now sets error code to ``ENOTSUP`` in more cases
where segment fd API is not expected to be supported:

View File

@ -447,6 +447,30 @@ rte_bsf32(uint32_t v)
return (uint32_t)__builtin_ctz(v);
}
/**
* Searches the input parameter for the least significant set bit
* (starting from zero). Safe version (checks for input parameter being zero).
*
* @warning ``pos`` must be a valid pointer. It is not checked!
*
* @param v
* The input parameter.
* @param pos
* If ``v`` was not 0, this value will contain position of least significant
* bit within the input parameter.
* @return
* Returns 0 if ``v`` was 0, otherwise returns 1.
*/
static inline int
rte_bsf32_safe(uint64_t v, uint32_t *pos)
{
if (v == 0)
return 0;
*pos = rte_bsf32(v);
return 1;
}
/**
* Return the rounded-up log2 of a integer.
*
@ -482,6 +506,23 @@ rte_fls_u32(uint32_t x)
return (x == 0) ? 0 : 32 - __builtin_clz(x);
}
/**
* Searches the input parameter for the least significant set bit
* (starting from zero).
* If a least significant 1 bit is found, its bit index is returned.
* If the content of the input parameter is zero, then the content of the return
* value is undefined.
* @param v
* input parameter, should not be zero.
* @return
* least significant set bit in the input parameter.
*/
static inline int
rte_bsf64(uint64_t v)
{
return (uint32_t)__builtin_ctzll(v);
}
/**
* Searches the input parameter for the least significant set bit
* (starting from zero). Safe version (checks for input parameter being zero).
@ -502,7 +543,7 @@ rte_bsf64_safe(uint64_t v, uint32_t *pos)
if (v == 0)
return 0;
*pos = __builtin_ctzll(v);
*pos = rte_bsf64(v);
return 1;
}

View File

@ -213,19 +213,13 @@ get_file_size(int fd)
return st.st_size;
}
static inline uint32_t
bsf64(uint64_t v)
{
return (uint32_t)__builtin_ctzll(v);
}
static inline uint32_t
log2_u64(uint64_t v)
{
if (v == 0)
return 0;
v = rte_align64pow2(v);
return bsf64(v);
return rte_bsf64(v);
}
static int

View File

@ -50,12 +50,48 @@ test_macros(int __rte_unused unused_parm)
return 0;
}
static int
test_bsf(void)
{
uint32_t shift, pos;
/* safe versions should be able to handle 0 */
if (rte_bsf32_safe(0, &pos) != 0)
FAIL("rte_bsf32_safe");
if (rte_bsf64_safe(0, &pos) != 0)
FAIL("rte_bsf64_safe");
for (shift = 0; shift < 63; shift++) {
uint32_t val32;
uint64_t val64;
val64 = 1ULL << shift;
if ((uint32_t)rte_bsf64(val64) != shift)
FAIL("rte_bsf64");
if (rte_bsf64_safe(val64, &pos) != 1)
FAIL("rte_bsf64_safe");
if (pos != shift)
FAIL("rte_bsf64_safe");
if (shift > 31)
continue;
val32 = 1U << shift;
if ((uint32_t)rte_bsf32(val32) != shift)
FAIL("rte_bsf32");
if (rte_bsf32_safe(val32, &pos) != 1)
FAIL("rte_bsf32_safe");
if (pos != shift)
FAIL("rte_bsf32_safe");
}
return 0;
}
static int
test_misc(void)
{
char memdump[] = "memdump_test";
if (rte_bsf32(129))
FAIL("rte_bsf32");
rte_memdump(stdout, "test", memdump, sizeof(memdump));
rte_hexdump(stdout, "test", memdump, sizeof(memdump));
@ -226,6 +262,7 @@ test_common(void)
ret |= test_align();
ret |= test_macros(0);
ret |= test_misc();
ret |= test_bsf();
ret |= test_log2();
ret |= test_fls();