1a0dcaea2SMichael Wildt /* SPDX-License-Identifier: BSD-3-Clause
2*e6e8f03eSRandy Schacher * Copyright(c) 2019-2023 Broadcom
3a0dcaea2SMichael Wildt * All rights reserved.
4a0dcaea2SMichael Wildt */
5a0dcaea2SMichael Wildt
6a0dcaea2SMichael Wildt #include "bitalloc.h"
7a0dcaea2SMichael Wildt
8a0dcaea2SMichael Wildt #define BITALLOC_MAX_LEVELS 6
9a0dcaea2SMichael Wildt
10298dee27SJay Ding /* Finds the last bit set plus 1, equivalent to gcc __builtin_fls */
11298dee27SJay Ding static int
ba_fls(bitalloc_word_t v)12298dee27SJay Ding ba_fls(bitalloc_word_t v)
13298dee27SJay Ding {
14298dee27SJay Ding int c = 32;
15298dee27SJay Ding
16298dee27SJay Ding if (!v)
17298dee27SJay Ding return 0;
18298dee27SJay Ding
19298dee27SJay Ding if (!(v & 0xFFFF0000u)) {
20298dee27SJay Ding v <<= 16;
21298dee27SJay Ding c -= 16;
22298dee27SJay Ding }
23298dee27SJay Ding if (!(v & 0xFF000000u)) {
24298dee27SJay Ding v <<= 8;
25298dee27SJay Ding c -= 8;
26298dee27SJay Ding }
27298dee27SJay Ding if (!(v & 0xF0000000u)) {
28298dee27SJay Ding v <<= 4;
29298dee27SJay Ding c -= 4;
30298dee27SJay Ding }
31298dee27SJay Ding if (!(v & 0xC0000000u)) {
32298dee27SJay Ding v <<= 2;
33298dee27SJay Ding c -= 2;
34298dee27SJay Ding }
35298dee27SJay Ding if (!(v & 0x80000000u)) {
36298dee27SJay Ding v <<= 1;
37298dee27SJay Ding c -= 1;
38298dee27SJay Ding }
39298dee27SJay Ding
40298dee27SJay Ding return c;
41298dee27SJay Ding }
42298dee27SJay Ding
43a0dcaea2SMichael Wildt /* Finds the first bit set plus 1, equivalent to gcc __builtin_ffs */
44a0dcaea2SMichael Wildt static int
ba_ffs(bitalloc_word_t v)45a0dcaea2SMichael Wildt ba_ffs(bitalloc_word_t v)
46a0dcaea2SMichael Wildt {
47a0dcaea2SMichael Wildt int c; /* c will be the number of zero bits on the right plus 1 */
48a0dcaea2SMichael Wildt
49a0dcaea2SMichael Wildt v &= -v;
50a0dcaea2SMichael Wildt c = v ? 32 : 0;
51a0dcaea2SMichael Wildt
52a0dcaea2SMichael Wildt if (v & 0x0000FFFF)
53a0dcaea2SMichael Wildt c -= 16;
54a0dcaea2SMichael Wildt if (v & 0x00FF00FF)
55a0dcaea2SMichael Wildt c -= 8;
56a0dcaea2SMichael Wildt if (v & 0x0F0F0F0F)
57a0dcaea2SMichael Wildt c -= 4;
58a0dcaea2SMichael Wildt if (v & 0x33333333)
59a0dcaea2SMichael Wildt c -= 2;
60a0dcaea2SMichael Wildt if (v & 0x55555555)
61a0dcaea2SMichael Wildt c -= 1;
62a0dcaea2SMichael Wildt
63a0dcaea2SMichael Wildt return c;
64a0dcaea2SMichael Wildt }
65a0dcaea2SMichael Wildt
66a0dcaea2SMichael Wildt int
ba_init(struct bitalloc * pool,int size,bool free)67873661aaSJay Ding ba_init(struct bitalloc *pool, int size, bool free)
68a0dcaea2SMichael Wildt {
69a0dcaea2SMichael Wildt bitalloc_word_t *mem = (bitalloc_word_t *)pool;
70a0dcaea2SMichael Wildt int i;
71a0dcaea2SMichael Wildt
72a0dcaea2SMichael Wildt /* Initialize */
73a0dcaea2SMichael Wildt pool->size = 0;
74a0dcaea2SMichael Wildt
75a0dcaea2SMichael Wildt if (size < 1 || size > BITALLOC_MAX_SIZE)
76a0dcaea2SMichael Wildt return -1;
77a0dcaea2SMichael Wildt
78a0dcaea2SMichael Wildt /* Zero structure */
79a0dcaea2SMichael Wildt for (i = 0;
80a0dcaea2SMichael Wildt i < (int)(BITALLOC_SIZEOF(size) / sizeof(bitalloc_word_t));
81a0dcaea2SMichael Wildt i++)
82a0dcaea2SMichael Wildt mem[i] = 0;
83a0dcaea2SMichael Wildt
84a0dcaea2SMichael Wildt /* Initialize */
85a0dcaea2SMichael Wildt pool->size = size;
86a0dcaea2SMichael Wildt
87a0dcaea2SMichael Wildt /* Embed number of words of next level, after each level */
88a0dcaea2SMichael Wildt int words[BITALLOC_MAX_LEVELS];
89a0dcaea2SMichael Wildt int lev = 0;
90a0dcaea2SMichael Wildt int offset = 0;
91a0dcaea2SMichael Wildt
92a0dcaea2SMichael Wildt words[0] = (size + 31) / 32;
93a0dcaea2SMichael Wildt while (words[lev] > 1) {
94a0dcaea2SMichael Wildt lev++;
95a0dcaea2SMichael Wildt words[lev] = (words[lev - 1] + 31) / 32;
96a0dcaea2SMichael Wildt }
97a0dcaea2SMichael Wildt
98a0dcaea2SMichael Wildt while (lev) {
99a0dcaea2SMichael Wildt offset += words[lev];
100a0dcaea2SMichael Wildt pool->storage[offset++] = words[--lev];
101a0dcaea2SMichael Wildt }
102a0dcaea2SMichael Wildt
103873661aaSJay Ding /* Free the entire pool if it is required*/
104873661aaSJay Ding if (free) {
105a0dcaea2SMichael Wildt for (i = 0; i < size; i++)
106a0dcaea2SMichael Wildt ba_free(pool, i);
107873661aaSJay Ding }
108a0dcaea2SMichael Wildt
109a0dcaea2SMichael Wildt return 0;
110a0dcaea2SMichael Wildt }
111a0dcaea2SMichael Wildt
112a0dcaea2SMichael Wildt static int
ba_alloc_helper(struct bitalloc * pool,int offset,int words,unsigned int size,int index,int * clear)113a0dcaea2SMichael Wildt ba_alloc_helper(struct bitalloc *pool,
114a0dcaea2SMichael Wildt int offset,
115a0dcaea2SMichael Wildt int words,
116a0dcaea2SMichael Wildt unsigned int size,
117a0dcaea2SMichael Wildt int index,
118a0dcaea2SMichael Wildt int *clear)
119a0dcaea2SMichael Wildt {
120a0dcaea2SMichael Wildt bitalloc_word_t *storage = &pool->storage[offset];
121a0dcaea2SMichael Wildt int loc = ba_ffs(storage[index]);
122a0dcaea2SMichael Wildt int r;
123a0dcaea2SMichael Wildt
124a0dcaea2SMichael Wildt if (loc == 0)
125a0dcaea2SMichael Wildt return -1;
126a0dcaea2SMichael Wildt
127a0dcaea2SMichael Wildt loc--;
128a0dcaea2SMichael Wildt
129a0dcaea2SMichael Wildt if (pool->size > size) {
130a0dcaea2SMichael Wildt r = ba_alloc_helper(pool,
131a0dcaea2SMichael Wildt offset + words + 1,
132a0dcaea2SMichael Wildt storage[words],
133a0dcaea2SMichael Wildt size * 32,
134a0dcaea2SMichael Wildt index * 32 + loc,
135a0dcaea2SMichael Wildt clear);
136a0dcaea2SMichael Wildt } else {
137a0dcaea2SMichael Wildt r = index * 32 + loc;
138a0dcaea2SMichael Wildt *clear = 1;
139a0dcaea2SMichael Wildt pool->free_count--;
140a0dcaea2SMichael Wildt }
141a0dcaea2SMichael Wildt
142a0dcaea2SMichael Wildt if (*clear) {
143a0dcaea2SMichael Wildt storage[index] &= ~(1 << loc);
144a0dcaea2SMichael Wildt *clear = (storage[index] == 0);
145a0dcaea2SMichael Wildt }
146a0dcaea2SMichael Wildt
147a0dcaea2SMichael Wildt return r;
148a0dcaea2SMichael Wildt }
149a0dcaea2SMichael Wildt
150a0dcaea2SMichael Wildt int
ba_alloc(struct bitalloc * pool)151a0dcaea2SMichael Wildt ba_alloc(struct bitalloc *pool)
152a0dcaea2SMichael Wildt {
153a0dcaea2SMichael Wildt int clear = 0;
154a0dcaea2SMichael Wildt
155a0dcaea2SMichael Wildt return ba_alloc_helper(pool, 0, 1, 32, 0, &clear);
156a0dcaea2SMichael Wildt }
157a0dcaea2SMichael Wildt
158298dee27SJay Ding /**
159298dee27SJay Ding * Help function to alloc entry from highest available index
160298dee27SJay Ding *
161298dee27SJay Ding * Searching the pool from highest index for the empty entry.
162298dee27SJay Ding *
163298dee27SJay Ding * [in] pool
164298dee27SJay Ding * Pointer to the resource pool
165298dee27SJay Ding *
166298dee27SJay Ding * [in] offset
167298dee27SJay Ding * Offset of the storage in the pool
168298dee27SJay Ding *
169298dee27SJay Ding * [in] words
170298dee27SJay Ding * Number of words in this level
171298dee27SJay Ding *
172298dee27SJay Ding * [in] size
173298dee27SJay Ding * Number of entries in this level
174298dee27SJay Ding *
175298dee27SJay Ding * [in] index
176298dee27SJay Ding * Index of words that has the entry
177298dee27SJay Ding *
178298dee27SJay Ding * [in] clear
179298dee27SJay Ding * Indicate if a bit needs to be clear due to the entry is allocated
180298dee27SJay Ding *
181298dee27SJay Ding * Returns:
182298dee27SJay Ding * 0 - Success
183298dee27SJay Ding * -1 - Failure
184298dee27SJay Ding */
185298dee27SJay Ding static int
ba_alloc_reverse_helper(struct bitalloc * pool,int offset,int words,unsigned int size,int index,int * clear)186298dee27SJay Ding ba_alloc_reverse_helper(struct bitalloc *pool,
187298dee27SJay Ding int offset,
188298dee27SJay Ding int words,
189298dee27SJay Ding unsigned int size,
190298dee27SJay Ding int index,
191298dee27SJay Ding int *clear)
192298dee27SJay Ding {
193298dee27SJay Ding bitalloc_word_t *storage = &pool->storage[offset];
194298dee27SJay Ding int loc = ba_fls(storage[index]);
195298dee27SJay Ding int r;
196298dee27SJay Ding
197298dee27SJay Ding if (loc == 0)
198298dee27SJay Ding return -1;
199298dee27SJay Ding
200298dee27SJay Ding loc--;
201298dee27SJay Ding
202298dee27SJay Ding if (pool->size > size) {
203298dee27SJay Ding r = ba_alloc_reverse_helper(pool,
204298dee27SJay Ding offset + words + 1,
205298dee27SJay Ding storage[words],
206298dee27SJay Ding size * 32,
207298dee27SJay Ding index * 32 + loc,
208298dee27SJay Ding clear);
209298dee27SJay Ding } else {
210298dee27SJay Ding r = index * 32 + loc;
211298dee27SJay Ding *clear = 1;
212298dee27SJay Ding pool->free_count--;
213298dee27SJay Ding }
214298dee27SJay Ding
215298dee27SJay Ding if (*clear) {
216298dee27SJay Ding storage[index] &= ~(1 << loc);
217298dee27SJay Ding *clear = (storage[index] == 0);
218298dee27SJay Ding }
219298dee27SJay Ding
220298dee27SJay Ding return r;
221298dee27SJay Ding }
222298dee27SJay Ding
223298dee27SJay Ding int
ba_alloc_reverse(struct bitalloc * pool)224298dee27SJay Ding ba_alloc_reverse(struct bitalloc *pool)
225298dee27SJay Ding {
226298dee27SJay Ding int clear = 0;
227298dee27SJay Ding
228298dee27SJay Ding return ba_alloc_reverse_helper(pool, 0, 1, 32, 0, &clear);
229298dee27SJay Ding }
230298dee27SJay Ding
231a0dcaea2SMichael Wildt static int
ba_alloc_index_helper(struct bitalloc * pool,int offset,int words,unsigned int size,int * index,int * clear)232a0dcaea2SMichael Wildt ba_alloc_index_helper(struct bitalloc *pool,
233a0dcaea2SMichael Wildt int offset,
234a0dcaea2SMichael Wildt int words,
235a0dcaea2SMichael Wildt unsigned int size,
236a0dcaea2SMichael Wildt int *index,
237a0dcaea2SMichael Wildt int *clear)
238a0dcaea2SMichael Wildt {
239a0dcaea2SMichael Wildt bitalloc_word_t *storage = &pool->storage[offset];
240a0dcaea2SMichael Wildt int loc;
241a0dcaea2SMichael Wildt int r;
242a0dcaea2SMichael Wildt
243a0dcaea2SMichael Wildt if (pool->size > size)
244a0dcaea2SMichael Wildt r = ba_alloc_index_helper(pool,
245a0dcaea2SMichael Wildt offset + words + 1,
246a0dcaea2SMichael Wildt storage[words],
247a0dcaea2SMichael Wildt size * 32,
248a0dcaea2SMichael Wildt index,
249a0dcaea2SMichael Wildt clear);
250a0dcaea2SMichael Wildt else
251a0dcaea2SMichael Wildt r = 1; /* Check if already allocated */
252a0dcaea2SMichael Wildt
253a0dcaea2SMichael Wildt loc = (*index % 32);
254a0dcaea2SMichael Wildt *index = *index / 32;
255a0dcaea2SMichael Wildt
256a0dcaea2SMichael Wildt if (r == 1) {
257a0dcaea2SMichael Wildt r = (storage[*index] & (1 << loc)) ? 0 : -1;
258a0dcaea2SMichael Wildt if (r == 0) {
259a0dcaea2SMichael Wildt *clear = 1;
260a0dcaea2SMichael Wildt pool->free_count--;
261a0dcaea2SMichael Wildt }
262a0dcaea2SMichael Wildt }
263a0dcaea2SMichael Wildt
264a0dcaea2SMichael Wildt if (*clear) {
265a0dcaea2SMichael Wildt storage[*index] &= ~(1 << loc);
266a0dcaea2SMichael Wildt *clear = (storage[*index] == 0);
267a0dcaea2SMichael Wildt }
268a0dcaea2SMichael Wildt
269a0dcaea2SMichael Wildt return r;
270a0dcaea2SMichael Wildt }
271a0dcaea2SMichael Wildt
272a0dcaea2SMichael Wildt int
ba_alloc_index(struct bitalloc * pool,int index)273a0dcaea2SMichael Wildt ba_alloc_index(struct bitalloc *pool, int index)
274a0dcaea2SMichael Wildt {
275a0dcaea2SMichael Wildt int clear = 0;
276a0dcaea2SMichael Wildt int index_copy = index;
277a0dcaea2SMichael Wildt
278a0dcaea2SMichael Wildt if (index < 0 || index >= (int)pool->size)
279a0dcaea2SMichael Wildt return -1;
280a0dcaea2SMichael Wildt
281a0dcaea2SMichael Wildt if (ba_alloc_index_helper(pool, 0, 1, 32, &index_copy, &clear) >= 0)
282a0dcaea2SMichael Wildt return index;
283a0dcaea2SMichael Wildt else
284a0dcaea2SMichael Wildt return -1;
285a0dcaea2SMichael Wildt }
286a0dcaea2SMichael Wildt
287a0dcaea2SMichael Wildt static int
ba_inuse_helper(struct bitalloc * pool,int offset,int words,unsigned int size,int * index)288a0dcaea2SMichael Wildt ba_inuse_helper(struct bitalloc *pool,
289a0dcaea2SMichael Wildt int offset,
290a0dcaea2SMichael Wildt int words,
291a0dcaea2SMichael Wildt unsigned int size,
292a0dcaea2SMichael Wildt int *index)
293a0dcaea2SMichael Wildt {
294a0dcaea2SMichael Wildt bitalloc_word_t *storage = &pool->storage[offset];
295a0dcaea2SMichael Wildt int loc;
296a0dcaea2SMichael Wildt int r;
297a0dcaea2SMichael Wildt
298a0dcaea2SMichael Wildt if (pool->size > size)
299a0dcaea2SMichael Wildt r = ba_inuse_helper(pool,
300a0dcaea2SMichael Wildt offset + words + 1,
301a0dcaea2SMichael Wildt storage[words],
302a0dcaea2SMichael Wildt size * 32,
303a0dcaea2SMichael Wildt index);
304a0dcaea2SMichael Wildt else
305a0dcaea2SMichael Wildt r = 1; /* Check if in use */
306a0dcaea2SMichael Wildt
307a0dcaea2SMichael Wildt loc = (*index % 32);
308a0dcaea2SMichael Wildt *index = *index / 32;
309a0dcaea2SMichael Wildt
310a0dcaea2SMichael Wildt if (r == 1)
311a0dcaea2SMichael Wildt r = (storage[*index] & (1 << loc)) ? -1 : 0;
312a0dcaea2SMichael Wildt
313a0dcaea2SMichael Wildt return r;
314a0dcaea2SMichael Wildt }
315a0dcaea2SMichael Wildt
316a0dcaea2SMichael Wildt int
ba_inuse(struct bitalloc * pool,int index)317a0dcaea2SMichael Wildt ba_inuse(struct bitalloc *pool, int index)
318a0dcaea2SMichael Wildt {
319a0dcaea2SMichael Wildt if (index < 0 || index >= (int)pool->size)
320a0dcaea2SMichael Wildt return -1;
321a0dcaea2SMichael Wildt
322a0dcaea2SMichael Wildt return ba_inuse_helper(pool, 0, 1, 32, &index) == 0;
323a0dcaea2SMichael Wildt }
324a0dcaea2SMichael Wildt
325a0dcaea2SMichael Wildt static int
ba_free_helper(struct bitalloc * pool,int offset,int words,unsigned int size,int * index)326a0dcaea2SMichael Wildt ba_free_helper(struct bitalloc *pool,
327a0dcaea2SMichael Wildt int offset,
328a0dcaea2SMichael Wildt int words,
329a0dcaea2SMichael Wildt unsigned int size,
330a0dcaea2SMichael Wildt int *index)
331a0dcaea2SMichael Wildt {
332a0dcaea2SMichael Wildt bitalloc_word_t *storage = &pool->storage[offset];
333a0dcaea2SMichael Wildt int loc;
334a0dcaea2SMichael Wildt int r;
335a0dcaea2SMichael Wildt
336a0dcaea2SMichael Wildt if (pool->size > size)
337a0dcaea2SMichael Wildt r = ba_free_helper(pool,
338a0dcaea2SMichael Wildt offset + words + 1,
339a0dcaea2SMichael Wildt storage[words],
340a0dcaea2SMichael Wildt size * 32,
341a0dcaea2SMichael Wildt index);
342a0dcaea2SMichael Wildt else
343a0dcaea2SMichael Wildt r = 1; /* Check if already free */
344a0dcaea2SMichael Wildt
345a0dcaea2SMichael Wildt loc = (*index % 32);
346a0dcaea2SMichael Wildt *index = *index / 32;
347a0dcaea2SMichael Wildt
348a0dcaea2SMichael Wildt if (r == 1) {
349a0dcaea2SMichael Wildt r = (storage[*index] & (1 << loc)) ? -1 : 0;
350a0dcaea2SMichael Wildt if (r == 0)
351a0dcaea2SMichael Wildt pool->free_count++;
352a0dcaea2SMichael Wildt }
353a0dcaea2SMichael Wildt
354a0dcaea2SMichael Wildt if (r == 0)
355a0dcaea2SMichael Wildt storage[*index] |= (1 << loc);
356a0dcaea2SMichael Wildt
357a0dcaea2SMichael Wildt return r;
358a0dcaea2SMichael Wildt }
359a0dcaea2SMichael Wildt
360a0dcaea2SMichael Wildt int
ba_free(struct bitalloc * pool,int index)361a0dcaea2SMichael Wildt ba_free(struct bitalloc *pool, int index)
362a0dcaea2SMichael Wildt {
363a0dcaea2SMichael Wildt if (index < 0 || index >= (int)pool->size)
364a0dcaea2SMichael Wildt return -1;
365a0dcaea2SMichael Wildt
366a0dcaea2SMichael Wildt return ba_free_helper(pool, 0, 1, 32, &index);
367a0dcaea2SMichael Wildt }
368a0dcaea2SMichael Wildt
369a0dcaea2SMichael Wildt int
ba_inuse_free(struct bitalloc * pool,int index)370a0dcaea2SMichael Wildt ba_inuse_free(struct bitalloc *pool, int index)
371a0dcaea2SMichael Wildt {
372a0dcaea2SMichael Wildt if (index < 0 || index >= (int)pool->size)
373a0dcaea2SMichael Wildt return -1;
374a0dcaea2SMichael Wildt
375a0dcaea2SMichael Wildt return ba_free_helper(pool, 0, 1, 32, &index) + 1;
376a0dcaea2SMichael Wildt }
377a0dcaea2SMichael Wildt
378a0dcaea2SMichael Wildt int
ba_free_count(struct bitalloc * pool)379a0dcaea2SMichael Wildt ba_free_count(struct bitalloc *pool)
380a0dcaea2SMichael Wildt {
381a0dcaea2SMichael Wildt return (int)pool->free_count;
382a0dcaea2SMichael Wildt }
383a0dcaea2SMichael Wildt
ba_inuse_count(struct bitalloc * pool)384a0dcaea2SMichael Wildt int ba_inuse_count(struct bitalloc *pool)
385a0dcaea2SMichael Wildt {
386a0dcaea2SMichael Wildt return (int)(pool->size) - (int)(pool->free_count);
387a0dcaea2SMichael Wildt }
388a0dcaea2SMichael Wildt
389a0dcaea2SMichael Wildt static int
ba_find_next_helper(struct bitalloc * pool,int offset,int words,unsigned int size,int * index,int free)390a0dcaea2SMichael Wildt ba_find_next_helper(struct bitalloc *pool,
391a0dcaea2SMichael Wildt int offset,
392a0dcaea2SMichael Wildt int words,
393a0dcaea2SMichael Wildt unsigned int size,
394a0dcaea2SMichael Wildt int *index,
395a0dcaea2SMichael Wildt int free)
396a0dcaea2SMichael Wildt {
397a0dcaea2SMichael Wildt bitalloc_word_t *storage = &pool->storage[offset];
398a0dcaea2SMichael Wildt int loc, r, bottom = 0;
399a0dcaea2SMichael Wildt
400a0dcaea2SMichael Wildt if (pool->size > size)
401a0dcaea2SMichael Wildt r = ba_find_next_helper(pool,
402a0dcaea2SMichael Wildt offset + words + 1,
403a0dcaea2SMichael Wildt storage[words],
404a0dcaea2SMichael Wildt size * 32,
405a0dcaea2SMichael Wildt index,
406a0dcaea2SMichael Wildt free);
407a0dcaea2SMichael Wildt else
408a0dcaea2SMichael Wildt bottom = 1; /* Bottom of tree */
409a0dcaea2SMichael Wildt
410a0dcaea2SMichael Wildt loc = (*index % 32);
411a0dcaea2SMichael Wildt *index = *index / 32;
412a0dcaea2SMichael Wildt
413a0dcaea2SMichael Wildt if (bottom) {
414a0dcaea2SMichael Wildt int bit_index = *index * 32;
415a0dcaea2SMichael Wildt
416a0dcaea2SMichael Wildt loc = ba_ffs(~storage[*index] & ((bitalloc_word_t)-1 << loc));
417a0dcaea2SMichael Wildt if (loc > 0) {
418a0dcaea2SMichael Wildt loc--;
419a0dcaea2SMichael Wildt r = (bit_index + loc);
420a0dcaea2SMichael Wildt if (r >= (int)pool->size)
421a0dcaea2SMichael Wildt r = -1;
422a0dcaea2SMichael Wildt } else {
423a0dcaea2SMichael Wildt /* Loop over array at bottom of tree */
424a0dcaea2SMichael Wildt r = -1;
425a0dcaea2SMichael Wildt bit_index += 32;
426a0dcaea2SMichael Wildt *index = *index + 1;
427a0dcaea2SMichael Wildt while ((int)pool->size > bit_index) {
428a0dcaea2SMichael Wildt loc = ba_ffs(~storage[*index]);
429a0dcaea2SMichael Wildt
430a0dcaea2SMichael Wildt if (loc > 0) {
431a0dcaea2SMichael Wildt loc--;
432a0dcaea2SMichael Wildt r = (bit_index + loc);
433a0dcaea2SMichael Wildt if (r >= (int)pool->size)
434a0dcaea2SMichael Wildt r = -1;
435a0dcaea2SMichael Wildt break;
436a0dcaea2SMichael Wildt }
437a0dcaea2SMichael Wildt bit_index += 32;
438a0dcaea2SMichael Wildt *index = *index + 1;
439a0dcaea2SMichael Wildt }
440a0dcaea2SMichael Wildt }
441a0dcaea2SMichael Wildt }
442a0dcaea2SMichael Wildt
443a0dcaea2SMichael Wildt if (r >= 0 && (free)) {
444a0dcaea2SMichael Wildt if (bottom)
445a0dcaea2SMichael Wildt pool->free_count++;
446a0dcaea2SMichael Wildt storage[*index] |= (1 << loc);
447a0dcaea2SMichael Wildt }
448a0dcaea2SMichael Wildt
449a0dcaea2SMichael Wildt return r;
450a0dcaea2SMichael Wildt }
451a0dcaea2SMichael Wildt
452a0dcaea2SMichael Wildt int
ba_find_next_inuse(struct bitalloc * pool,int index)453a0dcaea2SMichael Wildt ba_find_next_inuse(struct bitalloc *pool, int index)
454a0dcaea2SMichael Wildt {
455a0dcaea2SMichael Wildt if (index < 0 ||
456a0dcaea2SMichael Wildt index >= (int)pool->size ||
457a0dcaea2SMichael Wildt pool->free_count == pool->size)
458a0dcaea2SMichael Wildt return -1;
459a0dcaea2SMichael Wildt
460a0dcaea2SMichael Wildt return ba_find_next_helper(pool, 0, 1, 32, &index, 0);
461a0dcaea2SMichael Wildt }
462a0dcaea2SMichael Wildt
463a0dcaea2SMichael Wildt int
ba_find_next_inuse_free(struct bitalloc * pool,int index)464a0dcaea2SMichael Wildt ba_find_next_inuse_free(struct bitalloc *pool, int index)
465a0dcaea2SMichael Wildt {
466a0dcaea2SMichael Wildt if (index < 0 ||
467a0dcaea2SMichael Wildt index >= (int)pool->size ||
468a0dcaea2SMichael Wildt pool->free_count == pool->size)
469a0dcaea2SMichael Wildt return -1;
470a0dcaea2SMichael Wildt
471a0dcaea2SMichael Wildt return ba_find_next_helper(pool, 0, 1, 32, &index, 1);
472a0dcaea2SMichael Wildt }
473