Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2016 Intel Corporation.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include "spdk/stdinc.h"
7 : :
8 : : #include "spdk/bit_array.h"
9 : : #include "spdk/bit_pool.h"
10 : : #include "spdk/env.h"
11 : :
12 : : #include "spdk/likely.h"
13 : : #include "spdk/util.h"
14 : :
15 : : typedef uint64_t spdk_bit_array_word;
16 : : #define SPDK_BIT_ARRAY_WORD_TZCNT(x) (__builtin_ctzll(x))
17 : : #define SPDK_BIT_ARRAY_WORD_POPCNT(x) (__builtin_popcountll(x))
18 : : #define SPDK_BIT_ARRAY_WORD_C(x) ((spdk_bit_array_word)(x))
19 : : #define SPDK_BIT_ARRAY_WORD_BYTES sizeof(spdk_bit_array_word)
20 : : #define SPDK_BIT_ARRAY_WORD_BITS (SPDK_BIT_ARRAY_WORD_BYTES * 8)
21 : : #define SPDK_BIT_ARRAY_WORD_INDEX_SHIFT spdk_u32log2(SPDK_BIT_ARRAY_WORD_BITS)
22 : : #define SPDK_BIT_ARRAY_WORD_INDEX_MASK ((1u << SPDK_BIT_ARRAY_WORD_INDEX_SHIFT) - 1)
23 : :
24 : : struct spdk_bit_array {
25 : : uint32_t bit_count;
26 : : spdk_bit_array_word words[];
27 : : };
28 : :
29 : : struct spdk_bit_array *
30 : 51100 : spdk_bit_array_create(uint32_t num_bits)
31 : : {
32 : 51100 : struct spdk_bit_array *ba = NULL;
33 : :
34 : 51100 : spdk_bit_array_resize(&ba, num_bits);
35 : :
36 : 51100 : return ba;
37 : : }
38 : :
39 : : void
40 : 54633 : spdk_bit_array_free(struct spdk_bit_array **bap)
41 : : {
42 : : struct spdk_bit_array *ba;
43 : :
44 [ + + ]: 54633 : if (!bap) {
45 : 6 : return;
46 : : }
47 : :
48 : 54627 : ba = *bap;
49 : 54627 : *bap = NULL;
50 : 54627 : spdk_free(ba);
51 : : }
52 : :
53 : : static inline uint32_t
54 : 105744 : bit_array_word_count(uint32_t num_bits)
55 : : {
56 [ - + ]: 105744 : return (num_bits + SPDK_BIT_ARRAY_WORD_BITS - 1) >> SPDK_BIT_ARRAY_WORD_INDEX_SHIFT;
57 : : }
58 : :
59 : : static inline spdk_bit_array_word
60 : 16530037 : bit_array_word_mask(uint32_t num_bits)
61 : : {
62 [ - + ]: 16530037 : assert(num_bits < SPDK_BIT_ARRAY_WORD_BITS);
63 [ - + ]: 16530037 : return (SPDK_BIT_ARRAY_WORD_C(1) << num_bits) - 1;
64 : : }
65 : :
66 : : int
67 : 69226 : spdk_bit_array_resize(struct spdk_bit_array **bap, uint32_t num_bits)
68 : : {
69 : : struct spdk_bit_array *new_ba;
70 : : uint32_t old_word_count, new_word_count;
71 : : size_t new_size;
72 : :
73 : : /*
74 : : * Max number of bits allowed is UINT32_MAX - 1, because we use UINT32_MAX to denote
75 : : * when a set or cleared bit cannot be found.
76 : : */
77 [ + + - + ]: 69226 : if (!bap || num_bits == UINT32_MAX) {
78 : 6 : return -EINVAL;
79 : : }
80 : :
81 : 69220 : new_word_count = bit_array_word_count(num_bits);
82 : 69220 : new_size = offsetof(struct spdk_bit_array, words) + new_word_count * SPDK_BIT_ARRAY_WORD_BYTES;
83 : :
84 : : /*
85 : : * Always keep one extra word with a 0 and a 1 past the actual required size so that the
86 : : * find_first functions can just keep going until they match.
87 : : */
88 : 69220 : new_size += SPDK_BIT_ARRAY_WORD_BYTES;
89 : :
90 : 69220 : new_ba = (struct spdk_bit_array *)spdk_realloc(*bap, new_size, 64);
91 [ - + ]: 69220 : if (!new_ba) {
92 : 0 : return -ENOMEM;
93 : : }
94 : :
95 : : /*
96 : : * Set up special extra word (see above comment about find_first_clear).
97 : : *
98 : : * This is set to 0b10 so that find_first_clear will find a 0 at the very first
99 : : * bit past the end of the buffer, and find_first_set will find a 1 at the next bit
100 : : * past that.
101 : : */
102 : 69220 : new_ba->words[new_word_count] = 0x2;
103 : :
104 [ + + ]: 69220 : if (*bap == NULL) {
105 : 51100 : old_word_count = 0;
106 : 51100 : new_ba->bit_count = 0;
107 : : } else {
108 : 18120 : old_word_count = bit_array_word_count(new_ba->bit_count);
109 : : }
110 : :
111 [ + + ]: 69220 : if (new_word_count > old_word_count) {
112 : : /* Zero out new entries */
113 [ - + ]: 37310 : memset(&new_ba->words[old_word_count], 0,
114 : 37310 : (new_word_count - old_word_count) * SPDK_BIT_ARRAY_WORD_BYTES);
115 [ + + + + ]: 31910 : } else if (new_word_count == old_word_count && num_bits < new_ba->bit_count) {
116 : : /* Make sure any existing partial last word is cleared beyond the new num_bits. */
117 : : uint32_t last_word_bits;
118 : : spdk_bit_array_word mask;
119 : :
120 [ - + ]: 33 : last_word_bits = num_bits & SPDK_BIT_ARRAY_WORD_INDEX_MASK;
121 : 33 : mask = bit_array_word_mask(last_word_bits);
122 : 33 : new_ba->words[old_word_count - 1] &= mask;
123 : : }
124 : :
125 : 69220 : new_ba->bit_count = num_bits;
126 : 69220 : *bap = new_ba;
127 : 69220 : return 0;
128 : : }
129 : :
130 : : uint32_t
131 : 2445973 : spdk_bit_array_capacity(const struct spdk_bit_array *ba)
132 : : {
133 : 2445973 : return ba->bit_count;
134 : : }
135 : :
136 : : static inline int
137 : 71606811 : bit_array_get_word(const struct spdk_bit_array *ba, uint32_t bit_index,
138 : : uint32_t *word_index, uint32_t *word_bit_index)
139 : : {
140 [ + + ]: 71606811 : if (spdk_unlikely(bit_index >= ba->bit_count)) {
141 : 705 : return -EINVAL;
142 : : }
143 : :
144 [ - + ]: 71606102 : *word_index = bit_index >> SPDK_BIT_ARRAY_WORD_INDEX_SHIFT;
145 [ - + ]: 71606102 : *word_bit_index = bit_index & SPDK_BIT_ARRAY_WORD_INDEX_MASK;
146 : :
147 : 71606102 : return 0;
148 : : }
149 : :
150 : : bool
151 : 38149789 : spdk_bit_array_get(const struct spdk_bit_array *ba, uint32_t bit_index)
152 : : {
153 : 14503894 : uint32_t word_index, word_bit_index;
154 : :
155 [ + + ]: 38149789 : if (bit_array_get_word(ba, bit_index, &word_index, &word_bit_index)) {
156 : 693 : return false;
157 : : }
158 : :
159 [ - + ]: 38149092 : return (ba->words[word_index] >> word_bit_index) & 1U;
160 : : }
161 : :
162 : : int
163 : 17197041 : spdk_bit_array_set(struct spdk_bit_array *ba, uint32_t bit_index)
164 : : {
165 : 4864875 : uint32_t word_index, word_bit_index;
166 : :
167 [ + + ]: 17197041 : if (bit_array_get_word(ba, bit_index, &word_index, &word_bit_index)) {
168 : 6 : return -EINVAL;
169 : : }
170 : :
171 [ - + ]: 17197035 : ba->words[word_index] |= (SPDK_BIT_ARRAY_WORD_C(1) << word_bit_index);
172 : 17197035 : return 0;
173 : : }
174 : :
175 : : void
176 : 16259984 : spdk_bit_array_clear(struct spdk_bit_array *ba, uint32_t bit_index)
177 : : {
178 : 4271199 : uint32_t word_index, word_bit_index;
179 : :
180 [ + + ]: 16259984 : if (bit_array_get_word(ba, bit_index, &word_index, &word_bit_index)) {
181 : : /*
182 : : * Clearing past the end of the bit array is a no-op, since bit past the end
183 : : * are implicitly 0.
184 : : */
185 : 6 : return;
186 : : }
187 : :
188 [ - + ]: 16259978 : ba->words[word_index] &= ~(SPDK_BIT_ARRAY_WORD_C(1) << word_bit_index);
189 : : }
190 : :
191 : : static inline uint32_t
192 : 16530022 : bit_array_find_first(const struct spdk_bit_array *ba, uint32_t start_bit_index,
193 : : spdk_bit_array_word xor_mask)
194 : : {
195 : : uint32_t word_index, first_word_bit_index;
196 : : spdk_bit_array_word word, first_word_mask;
197 : : const spdk_bit_array_word *words, *cur_word;
198 : :
199 [ + + ]: 16530022 : if (spdk_unlikely(start_bit_index >= ba->bit_count)) {
200 : 18 : return ba->bit_count;
201 : : }
202 : :
203 [ - + ]: 16530004 : word_index = start_bit_index >> SPDK_BIT_ARRAY_WORD_INDEX_SHIFT;
204 : 16530004 : words = ba->words;
205 : 16530004 : cur_word = &words[word_index];
206 : :
207 : : /*
208 : : * Special case for first word: skip start_bit_index % SPDK_BIT_ARRAY_WORD_BITS bits
209 : : * within the first word.
210 : : */
211 [ - + ]: 16530004 : first_word_bit_index = start_bit_index & SPDK_BIT_ARRAY_WORD_INDEX_MASK;
212 : 16530004 : first_word_mask = bit_array_word_mask(first_word_bit_index);
213 : :
214 : 16530004 : word = (*cur_word ^ xor_mask) & ~first_word_mask;
215 : :
216 : : /*
217 : : * spdk_bit_array_resize() guarantees that an extra word with a 1 and a 0 will always be
218 : : * at the end of the words[] array, so just keep going until a word matches.
219 : : */
220 [ + + ]: 92934397 : while (word == 0) {
221 : 76404393 : word = *++cur_word ^ xor_mask;
222 : : }
223 : :
224 [ - + ]: 16530004 : return ((uintptr_t)cur_word - (uintptr_t)words) * 8 + SPDK_BIT_ARRAY_WORD_TZCNT(word);
225 : : }
226 : :
227 : :
228 : : uint32_t
229 : 20818 : spdk_bit_array_find_first_set(const struct spdk_bit_array *ba, uint32_t start_bit_index)
230 : : {
231 : : uint32_t bit_index;
232 : :
233 : 20818 : bit_index = bit_array_find_first(ba, start_bit_index, 0);
234 : :
235 : : /*
236 : : * If we ran off the end of the array and found the 1 bit in the extra word,
237 : : * return UINT32_MAX to indicate no actual 1 bits were found.
238 : : */
239 [ + + ]: 20818 : if (bit_index >= ba->bit_count) {
240 : 1948 : bit_index = UINT32_MAX;
241 : : }
242 : :
243 : 20818 : return bit_index;
244 : : }
245 : :
246 : : uint32_t
247 : 16509204 : spdk_bit_array_find_first_clear(const struct spdk_bit_array *ba, uint32_t start_bit_index)
248 : : {
249 : : uint32_t bit_index;
250 : :
251 : 16509204 : bit_index = bit_array_find_first(ba, start_bit_index, SPDK_BIT_ARRAY_WORD_C(-1));
252 : :
253 : : /*
254 : : * If we ran off the end of the array and found the 0 bit in the extra word,
255 : : * return UINT32_MAX to indicate no actual 0 bits were found.
256 : : */
257 [ + + ]: 16509204 : if (bit_index >= ba->bit_count) {
258 : 2955 : bit_index = UINT32_MAX;
259 : : }
260 : :
261 : 16509204 : return bit_index;
262 : : }
263 : :
264 : : uint32_t
265 : 18404 : spdk_bit_array_count_set(const struct spdk_bit_array *ba)
266 : : {
267 : 18404 : const spdk_bit_array_word *cur_word = ba->words;
268 : 18404 : uint32_t word_count = bit_array_word_count(ba->bit_count);
269 : 18404 : uint32_t set_count = 0;
270 : :
271 [ + + ]: 2347651 : while (word_count--) {
272 : : /*
273 : : * No special treatment is needed for the last (potentially partial) word, since
274 : : * spdk_bit_array_resize() makes sure the bits past bit_count are cleared.
275 : : */
276 : 2329247 : set_count += SPDK_BIT_ARRAY_WORD_POPCNT(*cur_word++);
277 : : }
278 : :
279 : 18404 : return set_count;
280 : : }
281 : :
282 : : uint32_t
283 : 6233 : spdk_bit_array_count_clear(const struct spdk_bit_array *ba)
284 : : {
285 : 6233 : return ba->bit_count - spdk_bit_array_count_set(ba);
286 : : }
287 : :
288 : : void
289 : 13571 : spdk_bit_array_store_mask(const struct spdk_bit_array *ba, void *mask)
290 : : {
291 : : uint32_t size, i;
292 : 13571 : uint32_t num_bits = spdk_bit_array_capacity(ba);
293 : :
294 : 13571 : size = num_bits / CHAR_BIT;
295 [ - + - + ]: 13571 : memcpy(mask, ba->words, size);
296 : :
297 [ + + ]: 14461 : for (i = 0; i < num_bits % CHAR_BIT; i++) {
298 [ + + ]: 890 : if (spdk_bit_array_get(ba, i + size * CHAR_BIT)) {
299 [ - + ]: 176 : ((uint8_t *)mask)[size] |= (1U << i);
300 : : } else {
301 [ - + ]: 714 : ((uint8_t *)mask)[size] &= ~(1U << i);
302 : : }
303 : : }
304 : 13571 : }
305 : :
306 : : void
307 : 3431 : spdk_bit_array_load_mask(struct spdk_bit_array *ba, const void *mask)
308 : : {
309 : : uint32_t size, i;
310 : 3431 : uint32_t num_bits = spdk_bit_array_capacity(ba);
311 : :
312 : 3431 : size = num_bits / CHAR_BIT;
313 [ - + - + ]: 3431 : memcpy(ba->words, mask, size);
314 : :
315 [ + + ]: 3909 : for (i = 0; i < num_bits % CHAR_BIT; i++) {
316 [ + + + + ]: 478 : if (((uint8_t *)mask)[size] & (1U << i)) {
317 : 13 : spdk_bit_array_set(ba, i + size * CHAR_BIT);
318 : : } else {
319 : 465 : spdk_bit_array_clear(ba, i + size * CHAR_BIT);
320 : : }
321 : : }
322 : 3431 : }
323 : :
324 : : void
325 : 6 : spdk_bit_array_clear_mask(struct spdk_bit_array *ba)
326 : : {
327 : : uint32_t size, i;
328 : 6 : uint32_t num_bits = spdk_bit_array_capacity(ba);
329 : :
330 : 6 : size = num_bits / CHAR_BIT;
331 [ - + ]: 6 : memset(ba->words, 0, size);
332 : :
333 [ + + ]: 36 : for (i = 0; i < num_bits % CHAR_BIT; i++) {
334 : 30 : spdk_bit_array_clear(ba, i + size * CHAR_BIT);
335 : : }
336 : 6 : }
337 : :
338 : : struct spdk_bit_pool {
339 : : struct spdk_bit_array *array;
340 : : uint32_t lowest_free_bit;
341 : : uint32_t free_count;
342 : : };
343 : :
344 : : struct spdk_bit_pool *
345 : 50 : spdk_bit_pool_create(uint32_t num_bits)
346 : : {
347 : 50 : struct spdk_bit_pool *pool = NULL;
348 : 42 : struct spdk_bit_array *array;
349 : :
350 : 50 : array = spdk_bit_array_create(num_bits);
351 [ - + ]: 50 : if (array == NULL) {
352 : 0 : return NULL;
353 : : }
354 : :
355 : 50 : pool = calloc(1, sizeof(*pool));
356 [ - + ]: 50 : if (pool == NULL) {
357 : 0 : spdk_bit_array_free(&array);
358 : 0 : return NULL;
359 : : }
360 : :
361 : 50 : pool->array = array;
362 : 50 : pool->lowest_free_bit = 0;
363 : 50 : pool->free_count = num_bits;
364 : :
365 : 50 : return pool;
366 : : }
367 : :
368 : : struct spdk_bit_pool *
369 : 4614 : spdk_bit_pool_create_from_array(struct spdk_bit_array *array)
370 : : {
371 : 4614 : struct spdk_bit_pool *pool = NULL;
372 : :
373 : 4614 : pool = calloc(1, sizeof(*pool));
374 [ - + ]: 4614 : if (pool == NULL) {
375 : 0 : return NULL;
376 : : }
377 : :
378 : 4614 : pool->array = array;
379 : 4614 : pool->lowest_free_bit = spdk_bit_array_find_first_clear(array, 0);
380 : 4614 : pool->free_count = spdk_bit_array_count_clear(array);
381 : :
382 : 4614 : return pool;
383 : : }
384 : :
385 : : void
386 : 10601 : spdk_bit_pool_free(struct spdk_bit_pool **ppool)
387 : : {
388 : : struct spdk_bit_pool *pool;
389 : :
390 [ - + ]: 10601 : if (!ppool) {
391 : 0 : return;
392 : : }
393 : :
394 : 10601 : pool = *ppool;
395 : 10601 : *ppool = NULL;
396 [ + + ]: 10601 : if (pool != NULL) {
397 : 4664 : spdk_bit_array_free(&pool->array);
398 : 4664 : free(pool);
399 : : }
400 : : }
401 : :
402 : : int
403 : 0 : spdk_bit_pool_resize(struct spdk_bit_pool **ppool, uint32_t num_bits)
404 : : {
405 : : struct spdk_bit_pool *pool;
406 : : int rc;
407 : :
408 [ # # ]: 0 : assert(ppool != NULL);
409 : :
410 : 0 : pool = *ppool;
411 : 0 : rc = spdk_bit_array_resize(&pool->array, num_bits);
412 [ # # ]: 0 : if (rc) {
413 : 0 : return rc;
414 : : }
415 : :
416 : 0 : pool->lowest_free_bit = spdk_bit_array_find_first_clear(pool->array, 0);
417 : 0 : pool->free_count = spdk_bit_array_count_clear(pool->array);
418 : :
419 : 0 : return 0;
420 : : }
421 : :
422 : : uint32_t
423 : 2349495 : spdk_bit_pool_capacity(const struct spdk_bit_pool *pool)
424 : : {
425 : 2349495 : return spdk_bit_array_capacity(pool->array);
426 : : }
427 : :
428 : : bool
429 : 8147373 : spdk_bit_pool_is_allocated(const struct spdk_bit_pool *pool, uint32_t bit_index)
430 : : {
431 : 8147373 : return spdk_bit_array_get(pool->array, bit_index);
432 : : }
433 : :
434 : : uint32_t
435 : 2507800 : spdk_bit_pool_allocate_bit(struct spdk_bit_pool *pool)
436 : : {
437 : 2507800 : uint32_t bit_index = pool->lowest_free_bit;
438 : :
439 [ + + ]: 2507800 : if (bit_index == UINT32_MAX) {
440 : 1 : return UINT32_MAX;
441 : : }
442 : :
443 : 2507799 : spdk_bit_array_set(pool->array, bit_index);
444 : 2507799 : pool->lowest_free_bit = spdk_bit_array_find_first_clear(pool->array, bit_index);
445 : 2507799 : pool->free_count--;
446 : 2507799 : return bit_index;
447 : : }
448 : :
449 : : void
450 : 2345361 : spdk_bit_pool_free_bit(struct spdk_bit_pool *pool, uint32_t bit_index)
451 : : {
452 [ - + ]: 2345361 : assert(spdk_bit_array_get(pool->array, bit_index) == true);
453 : :
454 : 2345361 : spdk_bit_array_clear(pool->array, bit_index);
455 [ + + ]: 2345361 : if (pool->lowest_free_bit > bit_index) {
456 : 7890 : pool->lowest_free_bit = bit_index;
457 : : }
458 : 2345361 : pool->free_count++;
459 : 2345361 : }
460 : :
461 : : uint32_t
462 : 0 : spdk_bit_pool_count_allocated(const struct spdk_bit_pool *pool)
463 : : {
464 : 0 : return spdk_bit_array_capacity(pool->array) - pool->free_count;
465 : : }
466 : :
467 : : uint32_t
468 : 50 : spdk_bit_pool_count_free(const struct spdk_bit_pool *pool)
469 : : {
470 : 50 : return pool->free_count;
471 : : }
472 : :
473 : : void
474 : 3962 : spdk_bit_pool_store_mask(const struct spdk_bit_pool *pool, void *mask)
475 : : {
476 : 3962 : spdk_bit_array_store_mask(pool->array, mask);
477 : 3962 : }
478 : :
479 : : void
480 : 50 : spdk_bit_pool_load_mask(struct spdk_bit_pool *pool, const void *mask)
481 : : {
482 : 50 : spdk_bit_array_load_mask(pool->array, mask);
483 : 50 : pool->lowest_free_bit = spdk_bit_array_find_first_clear(pool->array, 0);
484 : 50 : pool->free_count = spdk_bit_array_count_clear(pool->array);
485 : 50 : }
486 : :
487 : : void
488 : 0 : spdk_bit_pool_free_all_bits(struct spdk_bit_pool *pool)
489 : : {
490 : 0 : spdk_bit_array_clear_mask(pool->array);
491 : 0 : pool->lowest_free_bit = 0;
492 : 0 : pool->free_count = spdk_bit_array_capacity(pool->array);
493 : 0 : }
|