mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
Merge pull request #14556 from benpicco/bitarithm_test_and_clear
core/bitarithm: add bitarithm_test_and_clear()
This commit is contained in:
commit
d59233baf1
@ -164,6 +164,45 @@ static inline unsigned bitarithm_lsb(unsigned v)
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Used for iterating over the bits in @p state.
|
||||
* Returns the index of a set bit in @p state, returns @p state with that bit cleared.
|
||||
*
|
||||
* @warning This is a low-level helper function, arguments are not checked.
|
||||
* It is intended to iterate over a bit map until all bits are cleared.
|
||||
* Whether it starts with the highest or lowest bit will depend on what is fastest
|
||||
* on the given hardware.
|
||||
*
|
||||
* @warning @p state must not be zero.
|
||||
*
|
||||
* @param[in] state Bit Map with at least one bit set
|
||||
* @param[out] index Index of the first set bit. Must be initialized with 0 before the
|
||||
* first call to this function, must not be modified between subsequent
|
||||
* calls.
|
||||
*
|
||||
* @return new state value - must be treated as opaque value
|
||||
*
|
||||
*/
|
||||
static inline unsigned bitarithm_test_and_clear(unsigned state, uint8_t *index)
|
||||
{
|
||||
#if defined(BITARITHM_HAS_CLZ)
|
||||
*index = 8 * sizeof(state) - __builtin_clz(state) - 1;
|
||||
return state & ~(1 << *index);
|
||||
#elif defined(BITARITHM_LSB_LOOKUP)
|
||||
/* Source: http://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightMultLookup */
|
||||
extern const uint8_t MultiplyDeBruijnBitPosition[32];
|
||||
uint32_t least_bit = state & -state;
|
||||
*index = MultiplyDeBruijnBitPosition[(least_bit * 0x077CB531U) >> 27];
|
||||
return state & ~least_bit;
|
||||
#else
|
||||
while ((state & 1) == 0) {
|
||||
*index += 1;
|
||||
state >>= 1;
|
||||
}
|
||||
return state & ~1;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -34,6 +34,17 @@ void arm_reset(void);
|
||||
*/
|
||||
#define STACK_CANARY_WORD (0xEAFFFFFEu)
|
||||
|
||||
/**
|
||||
* @brief Select fastest bitarithm_lsb implementation
|
||||
* @{
|
||||
*/
|
||||
#ifdef __ARM_FEATURE_CLZ
|
||||
#define BITARITHM_LSB_BUILTIN
|
||||
#define BITARITHM_HAS_CLZ
|
||||
#else
|
||||
#define BITARITHM_LSB_LOOKUP
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -63,6 +63,7 @@ extern "C" {
|
||||
*/
|
||||
#ifdef __ARM_FEATURE_CLZ
|
||||
#define BITARITHM_LSB_BUILTIN
|
||||
#define BITARITHM_HAS_CLZ
|
||||
#else
|
||||
#define BITARITHM_LSB_LOOKUP
|
||||
#endif
|
||||
|
@ -40,6 +40,15 @@
|
||||
#define TIMEOUT (TIMEOUT_S * US_PER_SEC)
|
||||
#define PER_ITERATION (4)
|
||||
|
||||
#if ARCH_32_BIT
|
||||
#define TEST_AND_CLEAR_TEST_MASK_0 (0xA2101045UL)
|
||||
#define TEST_AND_CLEAR_TEST_MASK_1 (0x22101044UL)
|
||||
#else
|
||||
#define TEST_AND_CLEAR_TEST_MASK_0 (0x9045UL)
|
||||
#define TEST_AND_CLEAR_TEST_MASK_1 (0x1244UL)
|
||||
|
||||
#endif
|
||||
|
||||
static atomic_bool done;
|
||||
|
||||
static void callback(void *unused)
|
||||
@ -84,6 +93,36 @@ static void run_test(const char *name, unsigned (*test)(unsigned))
|
||||
printf("+ %s: %lu iterations per second\r\n", name, (4*PER_ITERATION) * count / TIMEOUT_S);
|
||||
}
|
||||
|
||||
static unsigned do_test_and_clear(unsigned state)
|
||||
{
|
||||
uint8_t index = 0;
|
||||
unsigned found = 0;
|
||||
|
||||
while (state) {
|
||||
state = bitarithm_test_and_clear(state, &index);
|
||||
found |= 1 << index;
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
static void run_test_test_and_clear(void)
|
||||
{
|
||||
unsigned long count = 0;
|
||||
atomic_store(&done, false);
|
||||
|
||||
xtimer_t xtimer = { .callback = callback };
|
||||
xtimer_set(&xtimer, TIMEOUT);
|
||||
|
||||
do {
|
||||
assert(do_test_and_clear(TEST_AND_CLEAR_TEST_MASK_0) == TEST_AND_CLEAR_TEST_MASK_0);
|
||||
assert(do_test_and_clear(TEST_AND_CLEAR_TEST_MASK_1) == TEST_AND_CLEAR_TEST_MASK_1);
|
||||
++count;
|
||||
} while (atomic_load(&done) == false);
|
||||
|
||||
printf("+ %s: %lu iterations per second\r\n", "bitarithm_test_and_clear", 2 * count / TIMEOUT_S);
|
||||
}
|
||||
|
||||
#define run_test(test) run_test(#test, test)
|
||||
|
||||
int main(void)
|
||||
@ -93,6 +132,7 @@ int main(void)
|
||||
run_test(bitarithm_msb);
|
||||
run_test(bitarithm_lsb);
|
||||
run_test(bitarithm_bits_set);
|
||||
run_test_test_and_clear();
|
||||
|
||||
printf("Done.\r\n");
|
||||
return 0;
|
||||
|
@ -15,6 +15,7 @@ def testfunc(child):
|
||||
child.expect(r'\+ bitarithm_msb: \d+ iterations per second')
|
||||
child.expect(r'\+ bitarithm_lsb: \d+ iterations per second')
|
||||
child.expect(r'\+ bitarithm_bits_set: \d+ iterations per second')
|
||||
child.expect(r'\+ bitarithm_test_and_clear: \d+ iterations per second')
|
||||
child.expect_exact("Done.")
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user