1 /* 2 * Copyright (c) 2021 Intel Corporation 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 #ifndef ZEPHYR_INCLUDE_SYS_BITARRAY_H_ 8 #define ZEPHYR_INCLUDE_SYS_BITARRAY_H_ 9 10 #ifdef __cplusplus 11 extern "C" { 12 #endif 13 14 #include <stddef.h> 15 #include <stdint.h> 16 17 #include <zephyr/kernel.h> 18 #include <zephyr/sys/util.h> 19 20 /** 21 * @file 22 * 23 * @defgroup bitarray_apis Bit array 24 * @ingroup datastructure_apis 25 * 26 * @brief Store and manipulate bits in a bit array. 27 * 28 * @{ 29 */ 30 31 /** @cond INTERNAL_HIDDEN */ 32 struct sys_bitarray { 33 /* Number of bits */ 34 uint32_t num_bits; 35 36 /* Number of bundles */ 37 uint32_t num_bundles; 38 39 /* Bundle of bits */ 40 uint32_t *bundles; 41 42 /* Spinlock guarding access to this bit array */ 43 struct k_spinlock lock; 44 }; 45 /** @endcond */ 46 47 /** Bitarray structure */ 48 typedef struct sys_bitarray sys_bitarray_t; 49 50 /** 51 * @brief Create a bitarray object. 52 * 53 * @param name Name of the bitarray object. 54 * @param total_bits Total number of bits in this bitarray object. 55 * @param sba_mod Modifier to the bitarray variables. 56 */ 57 #define _SYS_BITARRAY_DEFINE(name, total_bits, sba_mod) \ 58 sba_mod uint32_t _sys_bitarray_bundles_##name \ 59 [DIV_ROUND_UP(DIV_ROUND_UP(total_bits, 8), \ 60 sizeof(uint32_t))] = {0}; \ 61 sba_mod sys_bitarray_t name = { \ 62 .num_bits = total_bits, \ 63 .num_bundles = DIV_ROUND_UP( \ 64 DIV_ROUND_UP(total_bits, 8), sizeof(uint32_t)), \ 65 .bundles = _sys_bitarray_bundles_##name, \ 66 } 67 68 /** 69 * @brief Create a bitarray object. 70 * 71 * @param name Name of the bitarray object. 72 * @param total_bits Total number of bits in this bitarray object. 73 */ 74 #define SYS_BITARRAY_DEFINE(name, total_bits) \ 75 _SYS_BITARRAY_DEFINE(name, total_bits,) 76 77 /** 78 * @brief Create a static bitarray object. 79 * 80 * @param name Name of the bitarray object. 81 * @param total_bits Total number of bits in this bitarray object. 82 */ 83 #define SYS_BITARRAY_DEFINE_STATIC(name, total_bits) \ 84 _SYS_BITARRAY_DEFINE(name, total_bits, static) 85 86 /** 87 * Set a bit in a bit array 88 * 89 * @param[in] bitarray Bitarray struct 90 * @param[in] bit The bit to be set 91 * 92 * @retval 0 Operation successful 93 * @retval -EINVAL Invalid argument (e.g. bit to set exceeds 94 * the number of bits in bit array, etc.) 95 */ 96 int sys_bitarray_set_bit(sys_bitarray_t *bitarray, size_t bit); 97 98 /** 99 * Clear a bit in a bit array 100 * 101 * @param[in] bitarray Bitarray struct 102 * @param[in] bit The bit to be cleared 103 * 104 * @retval 0 Operation successful 105 * @retval -EINVAL Invalid argument (e.g. bit to clear exceeds 106 * the number of bits in bit array, etc.) 107 */ 108 int sys_bitarray_clear_bit(sys_bitarray_t *bitarray, size_t bit); 109 110 /** 111 * Test whether a bit is set or not 112 * 113 * @param[in] bitarray Bitarray struct 114 * @param[in] bit The bit to be tested 115 * @param[out] val The value of the bit (0 or 1) 116 * 117 * @retval 0 Operation successful 118 * @retval -EINVAL Invalid argument (e.g. bit to test exceeds 119 * the number of bits in bit array, etc.) 120 */ 121 int sys_bitarray_test_bit(sys_bitarray_t *bitarray, size_t bit, int *val); 122 123 /** 124 * Test the bit and set it 125 * 126 * @param[in] bitarray Bitarray struct 127 * @param[in] bit The bit to be tested and set 128 * @param[out] prev_val Previous value of the bit (0 or 1) 129 * 130 * @retval 0 Operation successful 131 * @retval -EINVAL Invalid argument (e.g. bit to test exceeds 132 * the number of bits in bit array, etc.) 133 */ 134 int sys_bitarray_test_and_set_bit(sys_bitarray_t *bitarray, size_t bit, int *prev_val); 135 136 /** 137 * Test the bit and clear it 138 * 139 * @param[in] bitarray Bitarray struct 140 * @param[in] bit The bit to be tested and cleared 141 * @param[out] prev_val Previous value of the bit (0 or 1) 142 * 143 * @retval 0 Operation successful 144 * @retval -EINVAL Invalid argument (e.g. bit to test exceeds 145 * the number of bits in bit array, etc.) 146 */ 147 int sys_bitarray_test_and_clear_bit(sys_bitarray_t *bitarray, size_t bit, int *prev_val); 148 149 /** 150 * Allocate bits in a bit array 151 * 152 * This finds a number of bits (@p num_bits) in a contiguous of 153 * previously unallocated region. If such a region exists, the bits are 154 * marked as allocated and the offset to the start of this region is 155 * returned via @p offset. 156 * 157 * @param[in] bitarray Bitarray struct 158 * @param[in] num_bits Number of bits to allocate 159 * @param[out] offset Offset to the start of allocated region if 160 * successful 161 * 162 * @retval 0 Allocation successful 163 * @retval -EINVAL Invalid argument (e.g. allocating more bits than 164 * the bitarray has, trying to allocate 0 bits, etc.) 165 * @retval -ENOSPC No contiguous region big enough to accommodate 166 * the allocation 167 */ 168 int sys_bitarray_alloc(sys_bitarray_t *bitarray, size_t num_bits, 169 size_t *offset); 170 171 /** 172 * Free bits in a bit array 173 * 174 * This marks the number of bits (@p num_bits) starting from @p offset 175 * as no longer allocated. 176 * 177 * @param bitarray Bitarray struct 178 * @param num_bits Number of bits to free 179 * @param offset Starting bit position to free 180 * 181 * @retval 0 Free is successful 182 * @retval -EINVAL Invalid argument (e.g. try to free more bits than 183 * the bitarray has, trying to free 0 bits, etc.) 184 * @retval -EFAULT The bits in the indicated region are not all allocated. 185 */ 186 int sys_bitarray_free(sys_bitarray_t *bitarray, size_t num_bits, 187 size_t offset); 188 189 /** 190 * Test if bits in a region is all set. 191 * 192 * This tests if the number of bits (@p num_bits) in region starting 193 * from @p offset are all set. 194 * 195 * @param bitarray Bitarray struct 196 * @param num_bits Number of bits to test 197 * @param offset Starting bit position to test 198 * 199 * @retval true All bits are set. 200 * @retval false Not all bits are set. 201 */ 202 bool sys_bitarray_is_region_set(sys_bitarray_t *bitarray, size_t num_bits, 203 size_t offset); 204 205 /** 206 * Test if bits in a region is all cleared. 207 * 208 * This tests if the number of bits (@p num_bits) in region starting 209 * from @p offset are all cleared. 210 * 211 * @param bitarray Bitarray struct 212 * @param num_bits Number of bits to test 213 * @param offset Starting bit position to test 214 * 215 * @retval true All bits are cleared. 216 * @retval false Not all bits are cleared. 217 */ 218 bool sys_bitarray_is_region_cleared(sys_bitarray_t *bitarray, size_t num_bits, 219 size_t offset); 220 221 /** 222 * Set all bits in a region. 223 * 224 * This sets the number of bits (@p num_bits) in region starting 225 * from @p offset. 226 * 227 * @param bitarray Bitarray struct 228 * @param num_bits Number of bits to test 229 * @param offset Starting bit position to test 230 * 231 * @retval 0 Operation successful 232 * @retval -EINVAL Invalid argument (e.g. bit to set exceeds 233 * the number of bits in bit array, etc.) 234 */ 235 int sys_bitarray_set_region(sys_bitarray_t *bitarray, size_t num_bits, 236 size_t offset); 237 238 /** 239 * Test if all bits in a region are cleared/set and set/clear them 240 * in a single atomic operation 241 * 242 * This checks if all the bits (@p num_bits) in region starting 243 * from @p offset are in required state. If even one bit is not, 244 * -EEXIST is returned. If the whole region is set/cleared 245 * it is set to opposite state. The check and set is performed as a single 246 * atomic operation. 247 * 248 * @param bitarray Bitarray struct 249 * @param num_bits Number of bits to test and set 250 * @param offset Starting bit position to test and set 251 * @param to_set if true the region will be set if all bits are cleared 252 * if false the region will be cleard if all bits are set 253 * 254 * @retval 0 Operation successful 255 * @retval -EINVAL Invalid argument (e.g. bit to set exceeds 256 * the number of bits in bit array, etc.) 257 * @retval -EEXIST at least one bit in the region is set/cleared, 258 * operation cancelled 259 */ 260 int sys_bitarray_test_and_set_region(sys_bitarray_t *bitarray, size_t num_bits, 261 size_t offset, bool to_set); 262 263 /** 264 * Clear all bits in a region. 265 * 266 * This clears the number of bits (@p num_bits) in region starting 267 * from @p offset. 268 * 269 * @param bitarray Bitarray struct 270 * @param num_bits Number of bits to test 271 * @param offset Starting bit position to test 272 * 273 * @retval 0 Operation successful 274 * @retval -EINVAL Invalid argument (e.g. bit to set exceeds 275 * the number of bits in bit array, etc.) 276 */ 277 int sys_bitarray_clear_region(sys_bitarray_t *bitarray, size_t num_bits, 278 size_t offset); 279 280 /** 281 * @} 282 */ 283 284 #ifdef __cplusplus 285 } 286 #endif 287 288 #endif /* ZEPHYR_INCLUDE_SYS_BITARRAY_H_ */ 289