Arax -8d09c51940345c86062e8ef2427c705ae66e5926
A Runtime Framework for Decoupling Applications from Heterogeneous Accelerators
Loading...
Searching...
No Matches
bitmap.c
Go to the documentation of this file.
1#include "bitmap.h"
2#include <string.h>
3#include <stdio.h>
4
24
25utils_bitmap_s* utils_bitmap_init(void *mem, size_t size_bits)
26{
27 utils_bitmap_s *bmp = mem;
28
29 bmp->size_bits = size_bits;
30
31 size_bits += 63;
32 size_bits /= 64; // to uint64_t
33
34 bmp->free_p = bmp->bits;
35 bmp->end = bmp->free_p + size_bits;
36 bmp->used_bits = 0;
38 memset(bmp->bits, 0, size_bits * 8);
39
40 return bmp;
41}
42
44{
45 return bmp->size_bits;
46}
47
49{
50 return bmp->used_bits;
51}
52
54{
55 return bmp->size_bits - bmp->used_bits;
56}
57
61static inline int find_end_small(size_t bits, uint64_t *chunk)
62{
63 uint64_t mask = BITMAP_NOT_FOUND;
64
65 if (bits != 64)
66 mask = (((uint64_t) 1) << bits) - 1;
67
68 if ( (mask & (*chunk)) == 0) { // Yes free
69 *chunk |= mask;
70 return 1;
71 } else { // Nope, already allocated
72 return 0;
73 }
74}
75
76static inline size_t find_start_small(utils_bitmap_s *bmp, size_t bits, uint64_t *chunk)
77{
78 uint64_t usable_bits = *chunk;
79
80 if (chunk + 1 == bmp->end) { // Final chunk is partially usable
81 int shift = bmp->size_bits % 64;
82 if (shift)
83 usable_bits |= ((uint64_t) -1) << (shift);
84 }
85
86 if (!(usable_bits) ) { // Completely empty
87 if (bits == 64)
88 *chunk = BITMAP_NOT_FOUND; // Full allocation
89 else
90 *chunk = (((uint64_t) 1) << bits) - 1; // Partial allocation
91 bmp->used_bits += bits;
92 return ( ((size_t) chunk) - ((size_t) bmp->bits) ) * 8;
93 }
94
95 if (*chunk == BITMAP_NOT_FOUND) // Completely full
96 return BITMAP_NOT_FOUND;
97
98 int free_bits = 64 - __builtin_popcountl(usable_bits);
99
100 if (free_bits >= bits) {
101 // Not sure if we have it contigous
102 uint64_t mask = (((uint64_t) 1) << bits) - 1;
103 int shift;
104 for (shift = 0; shift <= 64 - bits; shift++) {
105 if ( (mask & (usable_bits) ) == 0)
106 goto FOUND; // Found a good gap
107 mask <<= 1;
108 }
109
110 return BITMAP_NOT_FOUND;
111
112FOUND:
113
114 *chunk |= mask;
115 bmp->used_bits += bits;
116
117 return ( ((size_t) chunk) - ((size_t) bmp->bits) ) * 8 + shift;
118 } else { // Not enough bits in this chunk
119 int free_end = (*chunk) ? __builtin_clzl(*chunk) : 64;
120 if (free_end == 0) // No free bits at end of chunk
121 return BITMAP_NOT_FOUND;
122
123 if (chunk + 1 == bmp->end) // Was on the last chunk
124 return BITMAP_NOT_FOUND;
125
126 int remainder = bits - free_end;
127
128 if (find_end_small(remainder, chunk + 1)) {
129 *chunk |= ((uint64_t) -1) << (64 - free_end);
130 bmp->used_bits += bits;
131 return ( ((size_t) chunk) - ((size_t) bmp->bits) ) * 8 + (64 - free_end);
132 }
133 }
134 return BITMAP_NOT_FOUND;
135} /* find_start_small */
136
137static inline size_t find_start_big(utils_bitmap_s *bmp, size_t bits, uint64_t *chunk)
138{
139 if (*chunk == BITMAP_NOT_FOUND)
140 return BITMAP_NOT_FOUND; // Already full
141
142 uint64_t first_mask = 0;
143 size_t remainder;
144 int free_end;
145
146 if (*chunk == 0) {
147 first_mask = BITMAP_NOT_FOUND; // Allocate the whole chunk
148 remainder = bits - 64;
149 free_end = 0;
150 } else {
151 free_end = __builtin_clzl(*chunk);
152 first_mask = (free_end) ? (((uint64_t) -1) << (64 - free_end)) : (0);
153 remainder = bits - free_end;
154 free_end = 64 - free_end;
155 }
156
157 if (!first_mask)
158 return BITMAP_NOT_FOUND; // No free space at end of chunk
159
160 if (chunk + 1 == bmp->end)
161 return BITMAP_NOT_FOUND; // No next chunk to allocate the remainder
162
163 if (remainder < 65) { // Remainder fits in one chunk
164 if (!find_end_small(remainder, chunk + 1))
165 return BITMAP_NOT_FOUND; // No free space at start of next chunk
166
167 *chunk |= first_mask;
168 bmp->used_bits += bits;
169 return ( ((size_t) chunk) - ((size_t) bmp->bits) ) * 8 + free_end;
170 } else {
171 size_t span = remainder / 64;
172 size_t last_remainder = remainder & 63;
173 uint64_t last_mask = (((uint64_t) (!!last_remainder)) << (last_remainder)) - 1;
174 (void) span;
175 (void) last_remainder;
176
177 if (chunk + span + (!!last_remainder) >= bmp->end)
178 return BITMAP_NOT_FOUND; // Not enough chunks
179
180 uint64_t *citr = chunk + 1;
181 int c = 0;
182 for (; c < span; c++) {
183 if (*citr)
184 return BITMAP_NOT_FOUND;
185
186 citr++;
187 }
188
189 if (last_remainder) {
190 if ( (*citr) & last_mask)
191 return BITMAP_NOT_FOUND;
192
193 *citr |= last_mask;
194 }
195
196 memset(chunk + 1, 0xFF, sizeof(uint64_t) * span);
197
198 *chunk |= first_mask;
199
200 bmp->used_bits += bits;
201
202 return ( ((size_t) chunk) - ((size_t) bmp->bits) ) * 8 + free_end;
203 }
204 return BITMAP_NOT_FOUND;
205} /* find_start_big */
206
207static inline size_t find_start(utils_bitmap_s *bmp, size_t bits, uint64_t *chunk)
208{
209 if (bits < 65)
210 return find_start_small(bmp, bits, chunk);
211 else
212 return find_start_big(bmp, bits, chunk);
213
214 return BITMAP_NOT_FOUND;
215}
216
218{
219 uint64_t *chunk;
220 size_t found = BITMAP_NOT_FOUND;
221
222 utils_spinlock_lock(&(bmp->lock));
223
224 if (bmp->free_p == bmp->end) {
225 bmp->free_p = bmp->bits;
226 }
227
228 if (utils_bitmap_free(bmp) < bits)
229 goto QUIT;
230
231 for (chunk = bmp->free_p; chunk < bmp->end; chunk++) {
232 found = find_start(bmp, bits, chunk);
233 if (found != BITMAP_NOT_FOUND)
234 goto FOUND;
235 }
236
237 for (chunk = bmp->bits; chunk < bmp->free_p; chunk++) {
238 found = find_start(bmp, bits, chunk);
239 if (found != BITMAP_NOT_FOUND)
240 goto FOUND;
241 }
242
243 if (found != BITMAP_NOT_FOUND) {
244FOUND:
245
246 bmp->free_p = bmp->bits + found / 64;
247 } else {
248 fprintf(stderr, "%s(%lu) failed (free: %lu)!\n", __func__, bits, utils_bitmap_free(bmp));
249 }
250QUIT:
252 return found;
253} /* utils_bitmap_alloc_bits */
254
255void utils_bitmap_free_bits(utils_bitmap_s *bmp, size_t start, size_t bits)
256{
257 utils_spinlock_lock(&(bmp->lock));
258 if (bits == 1) {
259 bmp->bits[start / 64] &= ~(((uint64_t) 1) << (start & 63));
260 bmp->used_bits -= 1;
261 } else {
262 size_t end = start + bits;
263 size_t start_chunk = start / 64;
264 size_t end_chunk = (end - 1) / 64;
265 start = start & 63;
266 end = end & 63;
267
268 if (start_chunk == end_chunk) { // Single chunk
269 size_t mask = BITMAP_NOT_FOUND;
270 if (bits != 64)
271 mask = ((((uint64_t) 1) << bits) - 1) << (start & 63);
272
273 arax_assert( (bmp->bits[start_chunk] & mask) == mask); // Dont try to free non allocated stuff
274
275 bmp->bits[start_chunk] &= ~mask;
276
277 bmp->used_bits -= bits;
278 } else {
279 size_t span = (end_chunk - start_chunk) - 1;
280 size_t start_mask = ((uint64_t) -1) << (start);
281 size_t end_mask = (end) ? (((uint64_t) -1) >> ((64 - end))) : (-1);
282
283 arax_assert( (bmp->bits[start_chunk] & start_mask) == start_mask);
284 arax_assert( (bmp->bits[end_chunk] & end_mask) == end_mask);
285
286 bmp->bits[start_chunk] &= ~start_mask;
287 bmp->bits[end_chunk] &= ~end_mask;
288
289 if (span)
290 memset(bmp->bits + start_chunk + 1, 0, sizeof(uint64_t) * span);
291
292 bmp->used_bits -= bits;
293 }
294 }
296} /* utils_bitmap_free_bits */
297
299{
300 size_t b = 0;
301 size_t allocated = 0;
302
303 for (b = 0; b < (bmp->size_bits + 63) / 64; b++)
304 if (bmp->bits[b])
305 allocated += __builtin_popcountl(bmp->bits[b]);
306 return allocated;
307}
308
309// GCOV_EXCL_START
310
312{
313 int b;
314 int s;
315
316 for (b = 0; b < (bmp->size_bits + 63) / 64; b++) {
317 uint64_t cchunk = bmp->bits[b];
318 for (s = 0; s < 64; s++) {
319 fprintf(stderr, "%d", (int) (cchunk & 1));
320 cchunk >>= 1;
321 }
322 fprintf(stderr, " ");
323 }
324 fprintf(stderr, "\n");
325}
326
327// GCOV_EXCL_STOP
#define arax_assert(EXPR)
Definition arax_assert.h:7
struct utils_bitmap utils_bitmap_s
#define BITMAP_NOT_FOUND
Definition bitmap.h:18
size_t utils_bitmap_alloc_bits(utils_bitmap_s *bmp, size_t bits)
Definition bitmap.c:217
utils_bitmap_s * utils_bitmap_init(void *mem, size_t size_bits)
Definition bitmap.c:25
static size_t find_start_big(utils_bitmap_s *bmp, size_t bits, uint64_t *chunk)
Definition bitmap.c:137
void utils_bitmap_free_bits(utils_bitmap_s *bmp, size_t start, size_t bits)
Definition bitmap.c:255
size_t utils_bitmap_free(utils_bitmap_s *bmp)
Definition bitmap.c:53
size_t utils_bitmap_count_allocated(utils_bitmap_s *bmp)
Definition bitmap.c:298
size_t utils_bitmap_used(utils_bitmap_s *bmp)
Definition bitmap.c:48
size_t utils_bitmap_size(utils_bitmap_s *bmp)
Definition bitmap.c:43
static size_t find_start(utils_bitmap_s *bmp, size_t bits, uint64_t *chunk)
Definition bitmap.c:207
void utils_bitmap_print_bits(utils_bitmap_s *bmp)
Definition bitmap.c:311
static int find_end_small(size_t bits, uint64_t *chunk)
Definition bitmap.c:61
static size_t find_start_small(utils_bitmap_s *bmp, size_t bits, uint64_t *chunk)
Definition bitmap.c:76
#define utils_spinlock_lock(V)
Definition queue.c:35
#define utils_spinlock_init(V)
Definition queue.c:34
#define utils_spinlock_unlock(V)
Definition queue.c:36
uint64_t * end
Definition bitmap.h:10
utils_spinlock lock
Definition bitmap.h:8
size_t used_bits
Definition bitmap.h:11
size_t size_bits
Definition bitmap.h:12
uint64_t * free_p
Definition bitmap.h:9
uint64_t bits[]
Definition bitmap.h:13