sys: introduce bit arrays
This introduces bit arrays as a new data type. This is different than sys_bitfield as it is working on raw arrays of 32-bit data. The bit arrays encode additional data inside the struct to avoid going beyond the declared number of bits, and also provides locking. Signed-off-by: Daniel Leung <daniel.leung@intel.com>
This commit is contained in:
parent
783b20712e
commit
ff407fb922
3 changed files with 794 additions and 0 deletions
228
include/sys/bitarray.h
Normal file
228
include/sys/bitarray.h
Normal file
|
@ -0,0 +1,228 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_INCLUDE_SYS_BITARRAY_H_
|
||||
#define ZEPHYR_INCLUDE_SYS_BITARRAY_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <kernel.h>
|
||||
|
||||
struct sys_bitarray {
|
||||
/* Number of bits */
|
||||
uint32_t num_bits;
|
||||
|
||||
/* Number of bundles */
|
||||
uint32_t num_bundles;
|
||||
|
||||
/* Bundle of bits */
|
||||
uint32_t *bundles;
|
||||
|
||||
/* Spinlock guarding access to this bit array */
|
||||
struct k_spinlock lock;
|
||||
};
|
||||
|
||||
typedef struct sys_bitarray sys_bitarray_t;
|
||||
|
||||
/**
|
||||
* @def SYS_BITARRAY_DEFINE
|
||||
*
|
||||
* @brief Create a bitarray object.
|
||||
*
|
||||
* @param name Name of the bitarray object.
|
||||
* @param total_bits Total number of bits in this bitarray object.
|
||||
*/
|
||||
#define SYS_BITARRAY_DEFINE(name, total_bits) \
|
||||
uint32_t _sys_bitarray_bundles_##name \
|
||||
[(((total_bits + 8 - 1) / 8) + sizeof(uint32_t) - 1) \
|
||||
/ sizeof(uint32_t)] = {0U}; \
|
||||
sys_bitarray_t name = { \
|
||||
.num_bits = total_bits, \
|
||||
.num_bundles = (((total_bits + 8 - 1) / 8) \
|
||||
+ sizeof(uint32_t) - 1) \
|
||||
/ sizeof(uint32_t), \
|
||||
.bundles = _sys_bitarray_bundles_##name, \
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a bit in a bit array
|
||||
*
|
||||
* @param[in] bitarray Bitarray struct
|
||||
* @param[in] bit The bit to be set
|
||||
*
|
||||
* @retval 0 Operation successful
|
||||
* @retval -EINVAL Invalid argument (e.g. bit to set exceeds
|
||||
* the number of bits in bit array, etc.)
|
||||
*/
|
||||
int sys_bitarray_set_bit(sys_bitarray_t *bitarray, size_t bit);
|
||||
|
||||
/**
|
||||
* Clear a bit in a bit array
|
||||
*
|
||||
* @param[in] bitarray Bitarray struct
|
||||
* @param[in] bit The bit to be cleared
|
||||
*
|
||||
* @retval 0 Operation successful
|
||||
* @retval -EINVAL Invalid argument (e.g. bit to clear exceeds
|
||||
* the number of bits in bit array, etc.)
|
||||
*/
|
||||
int sys_bitarray_clear_bit(sys_bitarray_t *bitarray, size_t bit);
|
||||
|
||||
/**
|
||||
* Test whether a bit is set or not
|
||||
*
|
||||
* @param[in] bitarray Bitarray struct
|
||||
* @param[in] bit The bit to be tested
|
||||
* @param[out] val The value of the bit (0 or 1)
|
||||
*
|
||||
* @retval 0 Operation successful
|
||||
* @retval -EINVAL Invalid argument (e.g. bit to test exceeds
|
||||
* the number of bits in bit array, etc.)
|
||||
*/
|
||||
int sys_bitarray_test_bit(sys_bitarray_t *bitarray, size_t bit, int *val);
|
||||
|
||||
/**
|
||||
* Test the bit and set it
|
||||
*
|
||||
* @param[in] bitarray Bitarray struct
|
||||
* @param[in] bit The bit to be tested and set
|
||||
* @param[out] prev_val Previous value of the bit (0 or 1)
|
||||
*
|
||||
* @retval 0 Operation successful
|
||||
* @retval -EINVAL Invalid argument (e.g. bit to test exceeds
|
||||
* the number of bits in bit array, etc.)
|
||||
*/
|
||||
int sys_bitarray_test_and_set_bit(sys_bitarray_t *bitarray, size_t bit, int *prev_val);
|
||||
|
||||
/**
|
||||
* Test the bit and clear it
|
||||
*
|
||||
* @param[in] bitarray Bitarray struct
|
||||
* @param[in] bit The bit to be tested and cleared
|
||||
* @param[out] prev_val Previous value of the bit (0 or 1)
|
||||
*
|
||||
* @retval 0 Operation successful
|
||||
* @retval -EINVAL Invalid argument (e.g. bit to test exceeds
|
||||
* the number of bits in bit array, etc.)
|
||||
*/
|
||||
int sys_bitarray_test_and_clear_bit(sys_bitarray_t *bitarray, size_t bit, int *prev_val);
|
||||
|
||||
/**
|
||||
* Allocate bits in a bit array
|
||||
*
|
||||
* This finds a number of bits (@p num_bits) in a contiguous of
|
||||
* previosly unallocated region. If such a region exists, the bits are
|
||||
* marked as allocated and the offset to the start of this region is
|
||||
* returned via @p offset.
|
||||
*
|
||||
* @param[in] bitarray Bitarray struct
|
||||
* @param[in] num_bits Number of bits to allocate
|
||||
* @param[out] offset Offset to the start of allocated region if
|
||||
* successful
|
||||
*
|
||||
* @retval 0 Allocation successful
|
||||
* @retval -EINVAL Invalid argument (e.g. allocating more bits than
|
||||
* the bitarray has, trying to allocate 0 bits, etc.)
|
||||
* @retval -ENOSPC No contiguous region big enough to accommodate
|
||||
* the allocation
|
||||
*/
|
||||
int sys_bitarray_alloc(sys_bitarray_t *bitarray, size_t num_bits,
|
||||
size_t *offset);
|
||||
|
||||
/**
|
||||
* Free bits in a bit array
|
||||
*
|
||||
* This marks the number of bits (@p num_bits) starting from @p offset
|
||||
* as no longer allocated.
|
||||
*
|
||||
* @param bitarray Bitarray struct
|
||||
* @param num_bits Number of bits to free
|
||||
* @param offset Starting bit position to free
|
||||
*
|
||||
* @retval 0 Free is successful
|
||||
* @retval -EINVAL Invalid argument (e.g. try to free more bits than
|
||||
* the bitarray has, trying to free 0 bits, etc.)
|
||||
* @retval -EFAULT The bits in the indicated region are not all allocated.
|
||||
*/
|
||||
int sys_bitarray_free(sys_bitarray_t *bitarray, size_t num_bits,
|
||||
size_t offset);
|
||||
|
||||
/**
|
||||
* Test if bits in a region is all set.
|
||||
*
|
||||
* This tests if the number of bits (@p num_bits) in region starting
|
||||
* from @p offset are all set.
|
||||
*
|
||||
* @param bitarray Bitarray struct
|
||||
* @param num_bits Number of bits to test
|
||||
* @param offset Starting bit position to test
|
||||
*
|
||||
* @retval true All bits are set.
|
||||
* @retval false Not all bits are set.
|
||||
*/
|
||||
bool sys_bitarray_is_region_set(sys_bitarray_t *bitarray, size_t num_bits,
|
||||
size_t offset);
|
||||
|
||||
/**
|
||||
* Test if bits in a region is all cleared.
|
||||
*
|
||||
* This tests if the number of bits (@p num_bits) in region starting
|
||||
* from @p offset are all cleared.
|
||||
*
|
||||
* @param bitarray Bitarray struct
|
||||
* @param num_bits Number of bits to test
|
||||
* @param offset Starting bit position to test
|
||||
*
|
||||
* @retval true All bits are cleared.
|
||||
* @retval false Not all bits are cleared.
|
||||
*/
|
||||
bool sys_bitarray_is_region_cleared(sys_bitarray_t *bitarray, size_t num_bits,
|
||||
size_t offset);
|
||||
|
||||
/**
|
||||
* Set all bits in a region.
|
||||
*
|
||||
* This sets the number of bits (@p num_bits) in region starting
|
||||
* from @p offset.
|
||||
*
|
||||
* @param bitarray Bitarray struct
|
||||
* @param num_bits Number of bits to test
|
||||
* @param offset Starting bit position to test
|
||||
*
|
||||
* @retval 0 Operation successful
|
||||
* @retval -EINVAL Invalid argument (e.g. bit to set exceeds
|
||||
* the number of bits in bit array, etc.)
|
||||
*/
|
||||
int sys_bitarray_set_region(sys_bitarray_t *bitarray, size_t num_bits,
|
||||
size_t offset);
|
||||
|
||||
/**
|
||||
* Clear all bits in a region.
|
||||
*
|
||||
* This clears the number of bits (@p num_bits) in region starting
|
||||
* from @p offset.
|
||||
*
|
||||
* @param bitarray Bitarray struct
|
||||
* @param num_bits Number of bits to test
|
||||
* @param offset Starting bit position to test
|
||||
*
|
||||
* @retval 0 Operation successful
|
||||
* @retval -EINVAL Invalid argument (e.g. bit to set exceeds
|
||||
* the number of bits in bit array, etc.)
|
||||
*/
|
||||
int sys_bitarray_clear_region(sys_bitarray_t *bitarray, size_t num_bits,
|
||||
size_t offset);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZEPHYR_INCLUDE_SYS_BITARRAY_H_ */
|
Loading…
Add table
Add a link
Reference in a new issue