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 <kernel.h>
18 
19 struct sys_bitarray {
20 	/* Number of bits */
21 	uint32_t num_bits;
22 
23 	/* Number of bundles */
24 	uint32_t num_bundles;
25 
26 	/* Bundle of bits */
27 	uint32_t *bundles;
28 
29 	/* Spinlock guarding access to this bit array */
30 	struct k_spinlock lock;
31 };
32 
33 typedef struct sys_bitarray sys_bitarray_t;
34 
35 /**
36  * @def SYS_BITARRAY_DEFINE
37  *
38  * @brief Create a bitarray object.
39  *
40  * @param name Name of the bitarray object.
41  * @param total_bits Total number of bits in this bitarray object.
42  */
43 #define SYS_BITARRAY_DEFINE(name, total_bits)				\
44 	uint32_t _sys_bitarray_bundles_##name				\
45 		[(((total_bits + 8 - 1) / 8) + sizeof(uint32_t) - 1)	\
46 		 / sizeof(uint32_t)] = {0U};				\
47 	sys_bitarray_t name = {						\
48 		.num_bits = total_bits,					\
49 		.num_bundles = (((total_bits + 8 - 1) / 8)		\
50 				+ sizeof(uint32_t) - 1)			\
51 			       / sizeof(uint32_t),			\
52 		.bundles = _sys_bitarray_bundles_##name,		\
53 	}
54 
55 /**
56  * Set a bit in a bit array
57  *
58  * @param[in] bitarray Bitarray struct
59  * @param[in] bit      The bit to be set
60  *
61  * @retval 0       Operation successful
62  * @retval -EINVAL Invalid argument (e.g. bit to set exceeds
63  *                 the number of bits in bit array, etc.)
64  */
65 int sys_bitarray_set_bit(sys_bitarray_t *bitarray, size_t bit);
66 
67 /**
68  * Clear a bit in a bit array
69  *
70  * @param[in] bitarray Bitarray struct
71  * @param[in] bit      The bit to be cleared
72  *
73  * @retval 0       Operation successful
74  * @retval -EINVAL Invalid argument (e.g. bit to clear exceeds
75  *                 the number of bits in bit array, etc.)
76  */
77 int sys_bitarray_clear_bit(sys_bitarray_t *bitarray, size_t bit);
78 
79 /**
80  * Test whether a bit is set or not
81  *
82  * @param[in]  bitarray Bitarray struct
83  * @param[in]  bit      The bit to be tested
84  * @param[out] val      The value of the bit (0 or 1)
85  *
86  * @retval 0       Operation successful
87  * @retval -EINVAL Invalid argument (e.g. bit to test exceeds
88  *                 the number of bits in bit array, etc.)
89  */
90 int sys_bitarray_test_bit(sys_bitarray_t *bitarray, size_t bit, int *val);
91 
92 /**
93  * Test the bit and set it
94  *
95  * @param[in]  bitarray Bitarray struct
96  * @param[in]  bit      The bit to be tested and set
97  * @param[out] prev_val Previous value of the bit (0 or 1)
98  *
99  * @retval 0       Operation successful
100  * @retval -EINVAL Invalid argument (e.g. bit to test exceeds
101  *                 the number of bits in bit array, etc.)
102  */
103 int sys_bitarray_test_and_set_bit(sys_bitarray_t *bitarray, size_t bit, int *prev_val);
104 
105 /**
106  * Test the bit and clear it
107  *
108  * @param[in]  bitarray Bitarray struct
109  * @param[in]  bit      The bit to be tested and cleared
110  * @param[out] prev_val Previous value of the bit (0 or 1)
111  *
112  * @retval 0       Operation successful
113  * @retval -EINVAL Invalid argument (e.g. bit to test exceeds
114  *                 the number of bits in bit array, etc.)
115  */
116 int sys_bitarray_test_and_clear_bit(sys_bitarray_t *bitarray, size_t bit, int *prev_val);
117 
118 /**
119  * Allocate bits in a bit array
120  *
121  * This finds a number of bits (@p num_bits) in a contiguous of
122  * previosly unallocated region. If such a region exists, the bits are
123  * marked as allocated and the offset to the start of this region is
124  * returned via @p offset.
125  *
126  * @param[in]  bitarray Bitarray struct
127  * @param[in]  num_bits Number of bits to allocate
128  * @param[out] offset   Offset to the start of allocated region if
129  *                      successful
130  *
131  * @retval 0       Allocation successful
132  * @retval -EINVAL Invalid argument (e.g. allocating more bits than
133  *                 the bitarray has, trying to allocate 0 bits, etc.)
134  * @retval -ENOSPC No contiguous region big enough to accommodate
135  *                 the allocation
136  */
137 int sys_bitarray_alloc(sys_bitarray_t *bitarray, size_t num_bits,
138 		       size_t *offset);
139 
140 /**
141  * Free bits in a bit array
142  *
143  * This marks the number of bits (@p num_bits) starting from @p offset
144  * as no longer allocated.
145  *
146  * @param bitarray Bitarray struct
147  * @param num_bits Number of bits to free
148  * @param offset   Starting bit position to free
149  *
150  * @retval 0       Free is successful
151  * @retval -EINVAL Invalid argument (e.g. try to free more bits than
152  *                 the bitarray has, trying to free 0 bits, etc.)
153  * @retval -EFAULT The bits in the indicated region are not all allocated.
154  */
155 int sys_bitarray_free(sys_bitarray_t *bitarray, size_t num_bits,
156 		      size_t offset);
157 
158 /**
159  * Test if bits in a region is all set.
160  *
161  * This tests if the number of bits (@p num_bits) in region starting
162  * from @p offset are all set.
163  *
164  * @param bitarray Bitarray struct
165  * @param num_bits Number of bits to test
166  * @param offset   Starting bit position to test
167  *
168  * @retval true    All bits are set.
169  * @retval false   Not all bits are set.
170  */
171 bool sys_bitarray_is_region_set(sys_bitarray_t *bitarray, size_t num_bits,
172 				size_t offset);
173 
174 /**
175  * Test if bits in a region is all cleared.
176  *
177  * This tests if the number of bits (@p num_bits) in region starting
178  * from @p offset are all cleared.
179  *
180  * @param bitarray Bitarray struct
181  * @param num_bits Number of bits to test
182  * @param offset   Starting bit position to test
183  *
184  * @retval true    All bits are cleared.
185  * @retval false   Not all bits are cleared.
186  */
187 bool sys_bitarray_is_region_cleared(sys_bitarray_t *bitarray, size_t num_bits,
188 				    size_t offset);
189 
190 /**
191  * Set all bits in a region.
192  *
193  * This sets the number of bits (@p num_bits) in region starting
194  * from @p offset.
195  *
196  * @param bitarray Bitarray struct
197  * @param num_bits Number of bits to test
198  * @param offset   Starting bit position to test
199  *
200  * @retval 0       Operation successful
201  * @retval -EINVAL Invalid argument (e.g. bit to set exceeds
202  *                 the number of bits in bit array, etc.)
203  */
204 int sys_bitarray_set_region(sys_bitarray_t *bitarray, size_t num_bits,
205 			    size_t offset);
206 
207 /**
208  * Clear all bits in a region.
209  *
210  * This clears the number of bits (@p num_bits) in region starting
211  * from @p offset.
212  *
213  * @param bitarray Bitarray struct
214  * @param num_bits Number of bits to test
215  * @param offset   Starting bit position to test
216  *
217  * @retval 0       Operation successful
218  * @retval -EINVAL Invalid argument (e.g. bit to set exceeds
219  *                 the number of bits in bit array, etc.)
220  */
221 int sys_bitarray_clear_region(sys_bitarray_t *bitarray, size_t num_bits,
222 			      size_t offset);
223 
224 #ifdef __cplusplus
225 }
226 #endif
227 
228 #endif /* ZEPHYR_INCLUDE_SYS_BITARRAY_H_ */
229