blob: e407a3633de081c9c6e92d4409da2bb7bc0a740a [file] [log] [blame]
/*
* 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.
* @param sba_mod Modifier to the bitarray variables.
*/
#define _SYS_BITARRAY_DEFINE(name, total_bits, sba_mod) \
sba_mod uint32_t _sys_bitarray_bundles_##name \
[(((total_bits + 8 - 1) / 8) + sizeof(uint32_t) - 1) \
/ sizeof(uint32_t)] = {0U}; \
sba_mod 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, \
}
/**
* @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) \
_SYS_BITARRAY_DEFINE(name, total_bits,)
/**
* @def SYS_BITARRAY_DEFINE_STATIC
*
* @brief Create a static bitarray object.
*
* @param name Name of the bitarray object.
* @param total_bits Total number of bits in this bitarray object.
*/
#define SYS_BITARRAY_DEFINE_STATIC(name, total_bits) \
_SYS_BITARRAY_DEFINE(name, total_bits, static)
/**
* 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
* previously 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);
/**
* Test if all bits in a region are cleared/set and set/clear them
* in a single atomic operation
*
* This checks if all the bits (@p num_bits) in region starting
* from @p offset are in required state. If even one bit is not,
* -EEXIST is returned. If the whole region is set/cleared
* it is set to opposite state. The check and set is performed as a single
* atomic operation.
*
* @param bitarray Bitarray struct
* @param num_bits Number of bits to test and set
* @param offset Starting bit position to test and set
* @param to_set if true the region will be set if all bits are cleared
* if false the region will be cleard if all bits are set
*
* @retval 0 Operation successful
* @retval -EINVAL Invalid argument (e.g. bit to set exceeds
* the number of bits in bit array, etc.)
* @retval -EEXIST at least one bit in the region is set/cleared,
* operation cancelled
*/
int sys_bitarray_test_and_set_region(sys_bitarray_t *bitarray, size_t num_bits,
size_t offset, bool to_set);
/**
* 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_ */