xref: /dpdk/drivers/net/bnxt/tf_core/bitalloc.c (revision e6e8f03e5459f25153f1e4cd3e9ac30d3e473a61)
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