PatchworkOS
Loading...
Searching...
No Matches
bitmap.h
Go to the documentation of this file.
1#ifndef _SYS_BITMAP_H
2#define _SYS_BITMAP_H 1
3
4#include <errno.h>
5#include <stdbool.h>
6#include <stdint.h>
7#include <sys/math.h>
8
27
34#define BITMAP_BITS_TO_QWORDS(bits) (((bits) + 63) / 64)
35
42#define BITMAP_BITS_TO_BYTES(bits) (BITMAP_BITS_TO_QWORDS(bits) * sizeof(uint64_t))
43
50#define BITMAP_QWORDS_TO_BITS(qwords) ((qwords) * 64)
51
58#define BITMAP_FOR_EACH_SET(idx, map) \
59 for (uint64_t qwordIdx = 0; qwordIdx < BITMAP_BITS_TO_QWORDS((map)->length); qwordIdx++) \
60 for (uint64_t tempQword = (map)->buffer[qwordIdx]; tempQword != 0; tempQword &= (tempQword - 1)) \
61 if (({ \
62 uint64_t bit = __builtin_ctzll(tempQword); \
63 *(idx) = qwordIdx * 64 + bit; \
64 *(idx) < (map)->length; \
65 }))
66
74static inline void bitmap_init(bitmap_t* map, void* buffer, uint64_t length)
75{
76 map->firstZeroIdx = 0;
77 map->length = length;
78 map->buffer = (uint64_t*)buffer;
79}
80
88static inline bool bitmap_is_set(bitmap_t* map, uint64_t idx)
89{
90 if (idx >= map->length)
91 {
92 return false;
93 }
94
95 uint64_t qwordIdx = idx / 64;
96 uint64_t bitInQword = idx % 64;
97 return (map->buffer[qwordIdx] & (1ULL << bitInQword));
98}
99
106static inline void bitmap_set(bitmap_t* map, uint64_t index)
107{
108 if (index >= map->length)
109 {
110 return;
111 }
112
113 uint64_t qwordIdx = index / 64;
114 uint64_t bitInQword = index % 64;
115 map->buffer[qwordIdx] |= (1ULL << bitInQword);
116}
117
125static inline void bitmap_set_range(bitmap_t* map, uint64_t low, uint64_t high)
126{
127 if (low >= high || high > map->length)
128 {
129 return;
130 }
131
132 for (uint64_t i = low; i < high; i++)
133 {
134 bitmap_set(map, i);
135 }
136}
137
148 uint64_t align)
149{
150 if (length == 0 || align == 0 || maxIdx > map->length)
151 {
152 return map->length;
153 }
154
155 for (uint64_t i = map->firstZeroIdx; i < maxIdx; i += align)
156 {
157 if (!bitmap_is_set(map, i))
158 {
159 uint64_t j = i + 1;
160 for (; j < maxIdx; j++)
161 {
162 if (j - i == length)
163 {
164 bitmap_set_range(map, i, j);
165 return i;
166 }
167
168 if (bitmap_is_set(map, j))
169 {
170 i = MAX(ROUND_UP(j, align), align) - align;
171 break;
172 }
173 }
174 }
175 }
176
177 return map->length;
178}
179
186static inline void bitmap_clear(bitmap_t* map, uint64_t index)
187{
188 if (index >= map->length)
189 {
190 return;
191 }
192
193 uint64_t qwordIdx = index / 64;
194 uint64_t bitInQword = index % 64;
195 map->buffer[qwordIdx] &= ~(1ULL << bitInQword);
196 map->firstZeroIdx = MIN(map->firstZeroIdx, index);
197}
198
206static inline void bitmap_clear_range(bitmap_t* map, uint64_t low, uint64_t high)
207{
208 if (low >= high || high > map->length)
209 {
210 return;
211 }
212
213 for (uint64_t i = low; i < high; i++)
214 {
215 uint64_t qwordIdx = i / 64;
216 uint64_t bitInQword = i % 64;
217 map->buffer[qwordIdx] &= ~(1ULL << bitInQword);
218 }
219 map->firstZeroIdx = MIN(map->firstZeroIdx, low);
220}
221
231{
232 if (low >= high || high > map->length)
233 {
234 return 0;
235 }
236
237 uint64_t sum = 0;
238
239 uint64_t firstQwordIdx = low / 64;
240 uint64_t firstBitInQword = low % 64;
241
242 uint64_t lastQwordIdx = (high - 1) / 64;
243 uint64_t lastBitInQword = (high - 1) % 64;
244
245 if (firstQwordIdx == lastQwordIdx)
246 {
247 uint64_t qword = map->buffer[firstQwordIdx];
248 uint64_t startMask = ~((1ULL << firstBitInQword) - 1);
249 uint64_t endMask = (1ULL << (lastBitInQword + 1)) - 1;
250 sum += __builtin_popcountll(qword & startMask & endMask);
251 return sum;
252 }
253
254 if (firstBitInQword != 0)
255 {
256 uint64_t qword = map->buffer[firstQwordIdx];
257 uint64_t mask = ~((1ULL << firstBitInQword) - 1);
258 sum += __builtin_popcountll(qword & mask);
259 firstQwordIdx++;
260 }
261
262 for (uint64_t i = firstQwordIdx; i < lastQwordIdx; ++i)
263 {
264 sum += __builtin_popcountll(map->buffer[i]);
265 }
266
267 if (lastBitInQword != 63)
268 {
269 uint64_t qword = map->buffer[lastQwordIdx];
270 uint64_t mask = (1ULL << (lastBitInQword + 1)) - 1;
271 sum += __builtin_popcountll(qword & mask);
272 }
273
274 return sum;
275}
276
284{
285 if (map->firstZeroIdx >= map->length)
286 {
287 return map->length;
288 }
289
290 uint64_t qwordIdx = map->firstZeroIdx / 64;
291 uint64_t bitIdx = map->firstZeroIdx % 64;
293
294 if (bitIdx != 0)
295 {
296 uint64_t qword = map->buffer[qwordIdx];
297 uint64_t maskedQword = qword | ((1ULL << bitIdx) - 1);
298 if (maskedQword != ~0ULL)
299 {
300 return qwordIdx * 64 + __builtin_ctzll(~maskedQword);
301 }
302 qwordIdx++;
303 }
304
305 for (uint64_t i = qwordIdx; i < endQwordIdx; ++i)
306 {
307 if (map->buffer[i] != ~0ULL)
308 {
309 return i * 64 + __builtin_ctzll(~map->buffer[i]);
310 }
311 }
312
313 return map->length;
314}
315
324{
325 if (startIdx >= map->length)
326 {
327 return map->length;
328 }
329
330 uint64_t startQwordIdx = startIdx / 64;
331 uint64_t startBitIdx = startIdx % 64;
333
334 while (startQwordIdx < endQwordIdx)
335 {
336 uint64_t qword = map->buffer[startQwordIdx];
337 if (startBitIdx != 0)
338 {
339 qword &= ~((1ULL << startBitIdx) - 1);
340 }
341
342 if (qword != 0)
343 {
344 return startQwordIdx * 64 + __builtin_ctzll(qword);
345 }
346
347 startQwordIdx++;
348 startBitIdx = 0;
349 }
350
351 return map->length;
352}
353
356#endif // _SYS_BITMAP_H
static uint64_t bitmap_find_first_clear(bitmap_t *map)
Find the first clear bit in the bitmap.
Definition bitmap.h:283
static void bitmap_clear(bitmap_t *map, uint64_t index)
Clear a bit in the bitmap.
Definition bitmap.h:186
static bool bitmap_is_set(bitmap_t *map, uint64_t idx)
Check if a bit is set in the bitmap.
Definition bitmap.h:88
static void bitmap_set(bitmap_t *map, uint64_t index)
Set a bit in the bitmap.
Definition bitmap.h:106
static void bitmap_init(bitmap_t *map, void *buffer, uint64_t length)
Initialize a bitmap.
Definition bitmap.h:74
#define BITMAP_BITS_TO_QWORDS(bits)
Convert number of bits to number of qwords.
Definition bitmap.h:34
static uint64_t bitmap_find_first_set(bitmap_t *map, uint64_t startIdx)
Find the first set bit in the bitmap.
Definition bitmap.h:323
static void bitmap_set_range(bitmap_t *map, uint64_t low, uint64_t high)
Set a range of bits in the bitmap.
Definition bitmap.h:125
static void bitmap_clear_range(bitmap_t *map, uint64_t low, uint64_t high)
Clear a range of bits in the bitmap.
Definition bitmap.h:206
static uint64_t bitmap_sum(bitmap_t *map, uint64_t low, uint64_t high)
Sum the number of set bits in a range.
Definition bitmap.h:230
static uint64_t bitmap_find_clear_region_and_set(bitmap_t *map, uint64_t length, uintptr_t maxIdx, uint64_t align)
Find a clear region of specified length and alignment, and set it.
Definition bitmap.h:147
#define MIN(x, y)
Definition math.h:16
#define ROUND_UP(number, multiple)
Definition math.h:19
#define MAX(x, y)
Definition math.h:15
boot_memory_map_t * map
Definition mem.c:19
EFI_PHYSICAL_ADDRESS buffer
Definition mem.c:15
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
__UINTPTR_TYPE__ uintptr_t
Definition stdint.h:43
Bitmap structure.
Definition bitmap.h:22
uint64_t * buffer
Definition bitmap.h:25
uint64_t length
Definition bitmap.h:24
uint64_t firstZeroIdx
Definition bitmap.h:23
uint64_t length
Definition boot_info.h:47