xref: /f-stack/dpdk/drivers/net/bnxt/tf_core/bitalloc.c (revision 2d9fd380)
1*2d9fd380Sjfb8856606 /* SPDX-License-Identifier: BSD-3-Clause
2*2d9fd380Sjfb8856606  * Copyright(c) 2019-2020 Broadcom
3*2d9fd380Sjfb8856606  * All rights reserved.
4*2d9fd380Sjfb8856606  */
5*2d9fd380Sjfb8856606 
6*2d9fd380Sjfb8856606 #include "bitalloc.h"
7*2d9fd380Sjfb8856606 
8*2d9fd380Sjfb8856606 #define BITALLOC_MAX_LEVELS 6
9*2d9fd380Sjfb8856606 
10*2d9fd380Sjfb8856606 
11*2d9fd380Sjfb8856606 /* Finds the last bit set plus 1, equivalent to gcc __builtin_fls */
12*2d9fd380Sjfb8856606 static int
ba_fls(bitalloc_word_t v)13*2d9fd380Sjfb8856606 ba_fls(bitalloc_word_t v)
14*2d9fd380Sjfb8856606 {
15*2d9fd380Sjfb8856606 	int c = 32;
16*2d9fd380Sjfb8856606 
17*2d9fd380Sjfb8856606 	if (!v)
18*2d9fd380Sjfb8856606 		return 0;
19*2d9fd380Sjfb8856606 
20*2d9fd380Sjfb8856606 	if (!(v & 0xFFFF0000u)) {
21*2d9fd380Sjfb8856606 		v <<= 16;
22*2d9fd380Sjfb8856606 		c -= 16;
23*2d9fd380Sjfb8856606 	}
24*2d9fd380Sjfb8856606 	if (!(v & 0xFF000000u)) {
25*2d9fd380Sjfb8856606 		v <<= 8;
26*2d9fd380Sjfb8856606 		c -= 8;
27*2d9fd380Sjfb8856606 	}
28*2d9fd380Sjfb8856606 	if (!(v & 0xF0000000u)) {
29*2d9fd380Sjfb8856606 		v <<= 4;
30*2d9fd380Sjfb8856606 		c -= 4;
31*2d9fd380Sjfb8856606 	}
32*2d9fd380Sjfb8856606 	if (!(v & 0xC0000000u)) {
33*2d9fd380Sjfb8856606 		v <<= 2;
34*2d9fd380Sjfb8856606 		c -= 2;
35*2d9fd380Sjfb8856606 	}
36*2d9fd380Sjfb8856606 	if (!(v & 0x80000000u)) {
37*2d9fd380Sjfb8856606 		v <<= 1;
38*2d9fd380Sjfb8856606 		c -= 1;
39*2d9fd380Sjfb8856606 	}
40*2d9fd380Sjfb8856606 
41*2d9fd380Sjfb8856606 	return c;
42*2d9fd380Sjfb8856606 }
43*2d9fd380Sjfb8856606 
44*2d9fd380Sjfb8856606 /* Finds the first bit set plus 1, equivalent to gcc __builtin_ffs */
45*2d9fd380Sjfb8856606 static int
ba_ffs(bitalloc_word_t v)46*2d9fd380Sjfb8856606 ba_ffs(bitalloc_word_t v)
47*2d9fd380Sjfb8856606 {
48*2d9fd380Sjfb8856606 	int c; /* c will be the number of zero bits on the right plus 1 */
49*2d9fd380Sjfb8856606 
50*2d9fd380Sjfb8856606 	v &= -v;
51*2d9fd380Sjfb8856606 	c = v ? 32 : 0;
52*2d9fd380Sjfb8856606 
53*2d9fd380Sjfb8856606 	if (v & 0x0000FFFF)
54*2d9fd380Sjfb8856606 		c -= 16;
55*2d9fd380Sjfb8856606 	if (v & 0x00FF00FF)
56*2d9fd380Sjfb8856606 		c -= 8;
57*2d9fd380Sjfb8856606 	if (v & 0x0F0F0F0F)
58*2d9fd380Sjfb8856606 		c -= 4;
59*2d9fd380Sjfb8856606 	if (v & 0x33333333)
60*2d9fd380Sjfb8856606 		c -= 2;
61*2d9fd380Sjfb8856606 	if (v & 0x55555555)
62*2d9fd380Sjfb8856606 		c -= 1;
63*2d9fd380Sjfb8856606 
64*2d9fd380Sjfb8856606 	return c;
65*2d9fd380Sjfb8856606 }
66*2d9fd380Sjfb8856606 
67*2d9fd380Sjfb8856606 int
ba_init(struct bitalloc * pool,int size)68*2d9fd380Sjfb8856606 ba_init(struct bitalloc *pool, int size)
69*2d9fd380Sjfb8856606 {
70*2d9fd380Sjfb8856606 	bitalloc_word_t *mem = (bitalloc_word_t *)pool;
71*2d9fd380Sjfb8856606 	int       i;
72*2d9fd380Sjfb8856606 
73*2d9fd380Sjfb8856606 	/* Initialize */
74*2d9fd380Sjfb8856606 	pool->size = 0;
75*2d9fd380Sjfb8856606 
76*2d9fd380Sjfb8856606 	if (size < 1 || size > BITALLOC_MAX_SIZE)
77*2d9fd380Sjfb8856606 		return -1;
78*2d9fd380Sjfb8856606 
79*2d9fd380Sjfb8856606 	/* Zero structure */
80*2d9fd380Sjfb8856606 	for (i = 0;
81*2d9fd380Sjfb8856606 	     i < (int)(BITALLOC_SIZEOF(size) / sizeof(bitalloc_word_t));
82*2d9fd380Sjfb8856606 	     i++)
83*2d9fd380Sjfb8856606 		mem[i] = 0;
84*2d9fd380Sjfb8856606 
85*2d9fd380Sjfb8856606 	/* Initialize */
86*2d9fd380Sjfb8856606 	pool->size = size;
87*2d9fd380Sjfb8856606 
88*2d9fd380Sjfb8856606 	/* Embed number of words of next level, after each level */
89*2d9fd380Sjfb8856606 	int words[BITALLOC_MAX_LEVELS];
90*2d9fd380Sjfb8856606 	int lev = 0;
91*2d9fd380Sjfb8856606 	int offset = 0;
92*2d9fd380Sjfb8856606 
93*2d9fd380Sjfb8856606 	words[0] = (size + 31) / 32;
94*2d9fd380Sjfb8856606 	while (words[lev] > 1) {
95*2d9fd380Sjfb8856606 		lev++;
96*2d9fd380Sjfb8856606 		words[lev] = (words[lev - 1] + 31) / 32;
97*2d9fd380Sjfb8856606 	}
98*2d9fd380Sjfb8856606 
99*2d9fd380Sjfb8856606 	while (lev) {
100*2d9fd380Sjfb8856606 		offset += words[lev];
101*2d9fd380Sjfb8856606 		pool->storage[offset++] = words[--lev];
102*2d9fd380Sjfb8856606 	}
103*2d9fd380Sjfb8856606 
104*2d9fd380Sjfb8856606 	/* Free the entire pool */
105*2d9fd380Sjfb8856606 	for (i = 0; i < size; i++)
106*2d9fd380Sjfb8856606 		ba_free(pool, i);
107*2d9fd380Sjfb8856606 
108*2d9fd380Sjfb8856606 	return 0;
109*2d9fd380Sjfb8856606 }
110*2d9fd380Sjfb8856606 
111*2d9fd380Sjfb8856606 static int
ba_alloc_helper(struct bitalloc * pool,int offset,int words,unsigned int size,int index,int * clear)112*2d9fd380Sjfb8856606 ba_alloc_helper(struct bitalloc *pool,
113*2d9fd380Sjfb8856606 		int              offset,
114*2d9fd380Sjfb8856606 		int              words,
115*2d9fd380Sjfb8856606 		unsigned int     size,
116*2d9fd380Sjfb8856606 		int              index,
117*2d9fd380Sjfb8856606 		int             *clear)
118*2d9fd380Sjfb8856606 {
119*2d9fd380Sjfb8856606 	bitalloc_word_t *storage = &pool->storage[offset];
120*2d9fd380Sjfb8856606 	int       loc = ba_ffs(storage[index]);
121*2d9fd380Sjfb8856606 	int       r;
122*2d9fd380Sjfb8856606 
123*2d9fd380Sjfb8856606 	if (loc == 0)
124*2d9fd380Sjfb8856606 		return -1;
125*2d9fd380Sjfb8856606 
126*2d9fd380Sjfb8856606 	loc--;
127*2d9fd380Sjfb8856606 
128*2d9fd380Sjfb8856606 	if (pool->size > size) {
129*2d9fd380Sjfb8856606 		r = ba_alloc_helper(pool,
130*2d9fd380Sjfb8856606 				    offset + words + 1,
131*2d9fd380Sjfb8856606 				    storage[words],
132*2d9fd380Sjfb8856606 				    size * 32,
133*2d9fd380Sjfb8856606 				    index * 32 + loc,
134*2d9fd380Sjfb8856606 				    clear);
135*2d9fd380Sjfb8856606 	} else {
136*2d9fd380Sjfb8856606 		r = index * 32 + loc;
137*2d9fd380Sjfb8856606 		*clear = 1;
138*2d9fd380Sjfb8856606 		pool->free_count--;
139*2d9fd380Sjfb8856606 	}
140*2d9fd380Sjfb8856606 
141*2d9fd380Sjfb8856606 	if (*clear) {
142*2d9fd380Sjfb8856606 		storage[index] &= ~(1 << loc);
143*2d9fd380Sjfb8856606 		*clear = (storage[index] == 0);
144*2d9fd380Sjfb8856606 	}
145*2d9fd380Sjfb8856606 
146*2d9fd380Sjfb8856606 	return r;
147*2d9fd380Sjfb8856606 }
148*2d9fd380Sjfb8856606 
149*2d9fd380Sjfb8856606 int
ba_alloc(struct bitalloc * pool)150*2d9fd380Sjfb8856606 ba_alloc(struct bitalloc *pool)
151*2d9fd380Sjfb8856606 {
152*2d9fd380Sjfb8856606 	int clear = 0;
153*2d9fd380Sjfb8856606 
154*2d9fd380Sjfb8856606 	return ba_alloc_helper(pool, 0, 1, 32, 0, &clear);
155*2d9fd380Sjfb8856606 }
156*2d9fd380Sjfb8856606 
157*2d9fd380Sjfb8856606 /**
158*2d9fd380Sjfb8856606  * Help function to alloc entry from highest available index
159*2d9fd380Sjfb8856606  *
160*2d9fd380Sjfb8856606  * Searching the pool from highest index for the empty entry.
161*2d9fd380Sjfb8856606  *
162*2d9fd380Sjfb8856606  * [in] pool
163*2d9fd380Sjfb8856606  *   Pointer to the resource pool
164*2d9fd380Sjfb8856606  *
165*2d9fd380Sjfb8856606  * [in] offset
166*2d9fd380Sjfb8856606  *   Offset of the storage in the pool
167*2d9fd380Sjfb8856606  *
168*2d9fd380Sjfb8856606  * [in] words
169*2d9fd380Sjfb8856606  *   Number of words in this level
170*2d9fd380Sjfb8856606  *
171*2d9fd380Sjfb8856606  * [in] size
172*2d9fd380Sjfb8856606  *   Number of entries in this level
173*2d9fd380Sjfb8856606  *
174*2d9fd380Sjfb8856606  * [in] index
175*2d9fd380Sjfb8856606  *   Index of words that has the entry
176*2d9fd380Sjfb8856606  *
177*2d9fd380Sjfb8856606  * [in] clear
178*2d9fd380Sjfb8856606  *   Indicate if a bit needs to be clear due to the entry is allocated
179*2d9fd380Sjfb8856606  *
180*2d9fd380Sjfb8856606  * Returns:
181*2d9fd380Sjfb8856606  *     0 - Success
182*2d9fd380Sjfb8856606  *    -1 - Failure
183*2d9fd380Sjfb8856606  */
184*2d9fd380Sjfb8856606 static int
ba_alloc_reverse_helper(struct bitalloc * pool,int offset,int words,unsigned int size,int index,int * clear)185*2d9fd380Sjfb8856606 ba_alloc_reverse_helper(struct bitalloc *pool,
186*2d9fd380Sjfb8856606 			int offset,
187*2d9fd380Sjfb8856606 			int words,
188*2d9fd380Sjfb8856606 			unsigned int size,
189*2d9fd380Sjfb8856606 			int index,
190*2d9fd380Sjfb8856606 			int *clear)
191*2d9fd380Sjfb8856606 {
192*2d9fd380Sjfb8856606 	bitalloc_word_t *storage = &pool->storage[offset];
193*2d9fd380Sjfb8856606 	int loc = ba_fls(storage[index]);
194*2d9fd380Sjfb8856606 	int r;
195*2d9fd380Sjfb8856606 
196*2d9fd380Sjfb8856606 	if (loc == 0)
197*2d9fd380Sjfb8856606 		return -1;
198*2d9fd380Sjfb8856606 
199*2d9fd380Sjfb8856606 	loc--;
200*2d9fd380Sjfb8856606 
201*2d9fd380Sjfb8856606 	if (pool->size > size) {
202*2d9fd380Sjfb8856606 		r = ba_alloc_reverse_helper(pool,
203*2d9fd380Sjfb8856606 					    offset + words + 1,
204*2d9fd380Sjfb8856606 					    storage[words],
205*2d9fd380Sjfb8856606 					    size * 32,
206*2d9fd380Sjfb8856606 					    index * 32 + loc,
207*2d9fd380Sjfb8856606 					    clear);
208*2d9fd380Sjfb8856606 	} else {
209*2d9fd380Sjfb8856606 		r = index * 32 + loc;
210*2d9fd380Sjfb8856606 		*clear = 1;
211*2d9fd380Sjfb8856606 		pool->free_count--;
212*2d9fd380Sjfb8856606 	}
213*2d9fd380Sjfb8856606 
214*2d9fd380Sjfb8856606 	if (*clear) {
215*2d9fd380Sjfb8856606 		storage[index] &= ~(1 << loc);
216*2d9fd380Sjfb8856606 		*clear = (storage[index] == 0);
217*2d9fd380Sjfb8856606 	}
218*2d9fd380Sjfb8856606 
219*2d9fd380Sjfb8856606 	return r;
220*2d9fd380Sjfb8856606 }
221*2d9fd380Sjfb8856606 
222*2d9fd380Sjfb8856606 int
ba_alloc_reverse(struct bitalloc * pool)223*2d9fd380Sjfb8856606 ba_alloc_reverse(struct bitalloc *pool)
224*2d9fd380Sjfb8856606 {
225*2d9fd380Sjfb8856606 	int clear = 0;
226*2d9fd380Sjfb8856606 
227*2d9fd380Sjfb8856606 	return ba_alloc_reverse_helper(pool, 0, 1, 32, 0, &clear);
228*2d9fd380Sjfb8856606 }
229*2d9fd380Sjfb8856606 
230*2d9fd380Sjfb8856606 static int
ba_alloc_index_helper(struct bitalloc * pool,int offset,int words,unsigned int size,int * index,int * clear)231*2d9fd380Sjfb8856606 ba_alloc_index_helper(struct bitalloc *pool,
232*2d9fd380Sjfb8856606 		      int              offset,
233*2d9fd380Sjfb8856606 		      int              words,
234*2d9fd380Sjfb8856606 		      unsigned int     size,
235*2d9fd380Sjfb8856606 		      int             *index,
236*2d9fd380Sjfb8856606 		      int             *clear)
237*2d9fd380Sjfb8856606 {
238*2d9fd380Sjfb8856606 	bitalloc_word_t *storage = &pool->storage[offset];
239*2d9fd380Sjfb8856606 	int       loc;
240*2d9fd380Sjfb8856606 	int       r;
241*2d9fd380Sjfb8856606 
242*2d9fd380Sjfb8856606 	if (pool->size > size)
243*2d9fd380Sjfb8856606 		r = ba_alloc_index_helper(pool,
244*2d9fd380Sjfb8856606 					  offset + words + 1,
245*2d9fd380Sjfb8856606 					  storage[words],
246*2d9fd380Sjfb8856606 					  size * 32,
247*2d9fd380Sjfb8856606 					  index,
248*2d9fd380Sjfb8856606 					  clear);
249*2d9fd380Sjfb8856606 	else
250*2d9fd380Sjfb8856606 		r = 1; /* Check if already allocated */
251*2d9fd380Sjfb8856606 
252*2d9fd380Sjfb8856606 	loc = (*index % 32);
253*2d9fd380Sjfb8856606 	*index = *index / 32;
254*2d9fd380Sjfb8856606 
255*2d9fd380Sjfb8856606 	if (r == 1) {
256*2d9fd380Sjfb8856606 		r = (storage[*index] & (1 << loc)) ? 0 : -1;
257*2d9fd380Sjfb8856606 		if (r == 0) {
258*2d9fd380Sjfb8856606 			*clear = 1;
259*2d9fd380Sjfb8856606 			pool->free_count--;
260*2d9fd380Sjfb8856606 		}
261*2d9fd380Sjfb8856606 	}
262*2d9fd380Sjfb8856606 
263*2d9fd380Sjfb8856606 	if (*clear) {
264*2d9fd380Sjfb8856606 		storage[*index] &= ~(1 << loc);
265*2d9fd380Sjfb8856606 		*clear = (storage[*index] == 0);
266*2d9fd380Sjfb8856606 	}
267*2d9fd380Sjfb8856606 
268*2d9fd380Sjfb8856606 	return r;
269*2d9fd380Sjfb8856606 }
270*2d9fd380Sjfb8856606 
271*2d9fd380Sjfb8856606 int
ba_alloc_index(struct bitalloc * pool,int index)272*2d9fd380Sjfb8856606 ba_alloc_index(struct bitalloc *pool, int index)
273*2d9fd380Sjfb8856606 {
274*2d9fd380Sjfb8856606 	int clear = 0;
275*2d9fd380Sjfb8856606 	int index_copy = index;
276*2d9fd380Sjfb8856606 
277*2d9fd380Sjfb8856606 	if (index < 0 || index >= (int)pool->size)
278*2d9fd380Sjfb8856606 		return -1;
279*2d9fd380Sjfb8856606 
280*2d9fd380Sjfb8856606 	if (ba_alloc_index_helper(pool, 0, 1, 32, &index_copy, &clear) >= 0)
281*2d9fd380Sjfb8856606 		return index;
282*2d9fd380Sjfb8856606 	else
283*2d9fd380Sjfb8856606 		return -1;
284*2d9fd380Sjfb8856606 }
285*2d9fd380Sjfb8856606 
286*2d9fd380Sjfb8856606 static int
ba_inuse_helper(struct bitalloc * pool,int offset,int words,unsigned int size,int * index)287*2d9fd380Sjfb8856606 ba_inuse_helper(struct bitalloc *pool,
288*2d9fd380Sjfb8856606 		int              offset,
289*2d9fd380Sjfb8856606 		int              words,
290*2d9fd380Sjfb8856606 		unsigned int     size,
291*2d9fd380Sjfb8856606 		int             *index)
292*2d9fd380Sjfb8856606 {
293*2d9fd380Sjfb8856606 	bitalloc_word_t *storage = &pool->storage[offset];
294*2d9fd380Sjfb8856606 	int       loc;
295*2d9fd380Sjfb8856606 	int       r;
296*2d9fd380Sjfb8856606 
297*2d9fd380Sjfb8856606 	if (pool->size > size)
298*2d9fd380Sjfb8856606 		r = ba_inuse_helper(pool,
299*2d9fd380Sjfb8856606 				    offset + words + 1,
300*2d9fd380Sjfb8856606 				    storage[words],
301*2d9fd380Sjfb8856606 				    size * 32,
302*2d9fd380Sjfb8856606 				    index);
303*2d9fd380Sjfb8856606 	else
304*2d9fd380Sjfb8856606 		r = 1; /* Check if in use */
305*2d9fd380Sjfb8856606 
306*2d9fd380Sjfb8856606 	loc = (*index % 32);
307*2d9fd380Sjfb8856606 	*index = *index / 32;
308*2d9fd380Sjfb8856606 
309*2d9fd380Sjfb8856606 	if (r == 1)
310*2d9fd380Sjfb8856606 		r = (storage[*index] & (1 << loc)) ? -1 : 0;
311*2d9fd380Sjfb8856606 
312*2d9fd380Sjfb8856606 	return r;
313*2d9fd380Sjfb8856606 }
314*2d9fd380Sjfb8856606 
315*2d9fd380Sjfb8856606 int
ba_inuse(struct bitalloc * pool,int index)316*2d9fd380Sjfb8856606 ba_inuse(struct bitalloc *pool, int index)
317*2d9fd380Sjfb8856606 {
318*2d9fd380Sjfb8856606 	if (index < 0 || index >= (int)pool->size)
319*2d9fd380Sjfb8856606 		return -1;
320*2d9fd380Sjfb8856606 
321*2d9fd380Sjfb8856606 	return ba_inuse_helper(pool, 0, 1, 32, &index) == 0;
322*2d9fd380Sjfb8856606 }
323*2d9fd380Sjfb8856606 
324*2d9fd380Sjfb8856606 static int
ba_free_helper(struct bitalloc * pool,int offset,int words,unsigned int size,int * index)325*2d9fd380Sjfb8856606 ba_free_helper(struct bitalloc *pool,
326*2d9fd380Sjfb8856606 	       int              offset,
327*2d9fd380Sjfb8856606 	       int              words,
328*2d9fd380Sjfb8856606 	       unsigned int     size,
329*2d9fd380Sjfb8856606 	       int             *index)
330*2d9fd380Sjfb8856606 {
331*2d9fd380Sjfb8856606 	bitalloc_word_t *storage = &pool->storage[offset];
332*2d9fd380Sjfb8856606 	int       loc;
333*2d9fd380Sjfb8856606 	int       r;
334*2d9fd380Sjfb8856606 
335*2d9fd380Sjfb8856606 	if (pool->size > size)
336*2d9fd380Sjfb8856606 		r = ba_free_helper(pool,
337*2d9fd380Sjfb8856606 				   offset + words + 1,
338*2d9fd380Sjfb8856606 				   storage[words],
339*2d9fd380Sjfb8856606 				   size * 32,
340*2d9fd380Sjfb8856606 				   index);
341*2d9fd380Sjfb8856606 	else
342*2d9fd380Sjfb8856606 		r = 1; /* Check if already free */
343*2d9fd380Sjfb8856606 
344*2d9fd380Sjfb8856606 	loc = (*index % 32);
345*2d9fd380Sjfb8856606 	*index = *index / 32;
346*2d9fd380Sjfb8856606 
347*2d9fd380Sjfb8856606 	if (r == 1) {
348*2d9fd380Sjfb8856606 		r = (storage[*index] & (1 << loc)) ? -1 : 0;
349*2d9fd380Sjfb8856606 		if (r == 0)
350*2d9fd380Sjfb8856606 			pool->free_count++;
351*2d9fd380Sjfb8856606 	}
352*2d9fd380Sjfb8856606 
353*2d9fd380Sjfb8856606 	if (r == 0)
354*2d9fd380Sjfb8856606 		storage[*index] |= (1 << loc);
355*2d9fd380Sjfb8856606 
356*2d9fd380Sjfb8856606 	return r;
357*2d9fd380Sjfb8856606 }
358*2d9fd380Sjfb8856606 
359*2d9fd380Sjfb8856606 int
ba_free(struct bitalloc * pool,int index)360*2d9fd380Sjfb8856606 ba_free(struct bitalloc *pool, int index)
361*2d9fd380Sjfb8856606 {
362*2d9fd380Sjfb8856606 	if (index < 0 || index >= (int)pool->size)
363*2d9fd380Sjfb8856606 		return -1;
364*2d9fd380Sjfb8856606 
365*2d9fd380Sjfb8856606 	return ba_free_helper(pool, 0, 1, 32, &index);
366*2d9fd380Sjfb8856606 }
367*2d9fd380Sjfb8856606 
368*2d9fd380Sjfb8856606 int
ba_inuse_free(struct bitalloc * pool,int index)369*2d9fd380Sjfb8856606 ba_inuse_free(struct bitalloc *pool, int index)
370*2d9fd380Sjfb8856606 {
371*2d9fd380Sjfb8856606 	if (index < 0 || index >= (int)pool->size)
372*2d9fd380Sjfb8856606 		return -1;
373*2d9fd380Sjfb8856606 
374*2d9fd380Sjfb8856606 	return ba_free_helper(pool, 0, 1, 32, &index) + 1;
375*2d9fd380Sjfb8856606 }
376*2d9fd380Sjfb8856606 
377*2d9fd380Sjfb8856606 int
ba_free_count(struct bitalloc * pool)378*2d9fd380Sjfb8856606 ba_free_count(struct bitalloc *pool)
379*2d9fd380Sjfb8856606 {
380*2d9fd380Sjfb8856606 	return (int)pool->free_count;
381*2d9fd380Sjfb8856606 }
382*2d9fd380Sjfb8856606 
ba_inuse_count(struct bitalloc * pool)383*2d9fd380Sjfb8856606 int ba_inuse_count(struct bitalloc *pool)
384*2d9fd380Sjfb8856606 {
385*2d9fd380Sjfb8856606 	return (int)(pool->size) - (int)(pool->free_count);
386*2d9fd380Sjfb8856606 }
387*2d9fd380Sjfb8856606 
388*2d9fd380Sjfb8856606 static int
ba_find_next_helper(struct bitalloc * pool,int offset,int words,unsigned int size,int * index,int free)389*2d9fd380Sjfb8856606 ba_find_next_helper(struct bitalloc *pool,
390*2d9fd380Sjfb8856606 		    int              offset,
391*2d9fd380Sjfb8856606 		    int              words,
392*2d9fd380Sjfb8856606 		    unsigned int     size,
393*2d9fd380Sjfb8856606 		    int             *index,
394*2d9fd380Sjfb8856606 		    int              free)
395*2d9fd380Sjfb8856606 {
396*2d9fd380Sjfb8856606 	bitalloc_word_t *storage = &pool->storage[offset];
397*2d9fd380Sjfb8856606 	int       loc, r, bottom = 0;
398*2d9fd380Sjfb8856606 
399*2d9fd380Sjfb8856606 	if (pool->size > size)
400*2d9fd380Sjfb8856606 		r = ba_find_next_helper(pool,
401*2d9fd380Sjfb8856606 					offset + words + 1,
402*2d9fd380Sjfb8856606 					storage[words],
403*2d9fd380Sjfb8856606 					size * 32,
404*2d9fd380Sjfb8856606 					index,
405*2d9fd380Sjfb8856606 					free);
406*2d9fd380Sjfb8856606 	else
407*2d9fd380Sjfb8856606 		bottom = 1; /* Bottom of tree */
408*2d9fd380Sjfb8856606 
409*2d9fd380Sjfb8856606 	loc = (*index % 32);
410*2d9fd380Sjfb8856606 	*index = *index / 32;
411*2d9fd380Sjfb8856606 
412*2d9fd380Sjfb8856606 	if (bottom) {
413*2d9fd380Sjfb8856606 		int bit_index = *index * 32;
414*2d9fd380Sjfb8856606 
415*2d9fd380Sjfb8856606 		loc = ba_ffs(~storage[*index] & ((bitalloc_word_t)-1 << loc));
416*2d9fd380Sjfb8856606 		if (loc > 0) {
417*2d9fd380Sjfb8856606 			loc--;
418*2d9fd380Sjfb8856606 			r = (bit_index + loc);
419*2d9fd380Sjfb8856606 			if (r >= (int)pool->size)
420*2d9fd380Sjfb8856606 				r = -1;
421*2d9fd380Sjfb8856606 		} else {
422*2d9fd380Sjfb8856606 			/* Loop over array at bottom of tree */
423*2d9fd380Sjfb8856606 			r = -1;
424*2d9fd380Sjfb8856606 			bit_index += 32;
425*2d9fd380Sjfb8856606 			*index = *index + 1;
426*2d9fd380Sjfb8856606 			while ((int)pool->size > bit_index) {
427*2d9fd380Sjfb8856606 				loc = ba_ffs(~storage[*index]);
428*2d9fd380Sjfb8856606 
429*2d9fd380Sjfb8856606 				if (loc > 0) {
430*2d9fd380Sjfb8856606 					loc--;
431*2d9fd380Sjfb8856606 					r = (bit_index + loc);
432*2d9fd380Sjfb8856606 					if (r >= (int)pool->size)
433*2d9fd380Sjfb8856606 						r = -1;
434*2d9fd380Sjfb8856606 					break;
435*2d9fd380Sjfb8856606 				}
436*2d9fd380Sjfb8856606 				bit_index += 32;
437*2d9fd380Sjfb8856606 				*index = *index + 1;
438*2d9fd380Sjfb8856606 			}
439*2d9fd380Sjfb8856606 		}
440*2d9fd380Sjfb8856606 	}
441*2d9fd380Sjfb8856606 
442*2d9fd380Sjfb8856606 	if (r >= 0 && (free)) {
443*2d9fd380Sjfb8856606 		if (bottom)
444*2d9fd380Sjfb8856606 			pool->free_count++;
445*2d9fd380Sjfb8856606 		storage[*index] |= (1 << loc);
446*2d9fd380Sjfb8856606 	}
447*2d9fd380Sjfb8856606 
448*2d9fd380Sjfb8856606 	return r;
449*2d9fd380Sjfb8856606 }
450*2d9fd380Sjfb8856606 
451*2d9fd380Sjfb8856606 int
ba_find_next_inuse(struct bitalloc * pool,int index)452*2d9fd380Sjfb8856606 ba_find_next_inuse(struct bitalloc *pool, int index)
453*2d9fd380Sjfb8856606 {
454*2d9fd380Sjfb8856606 	if (index < 0 ||
455*2d9fd380Sjfb8856606 	    index >= (int)pool->size ||
456*2d9fd380Sjfb8856606 	    pool->free_count == pool->size)
457*2d9fd380Sjfb8856606 		return -1;
458*2d9fd380Sjfb8856606 
459*2d9fd380Sjfb8856606 	return ba_find_next_helper(pool, 0, 1, 32, &index, 0);
460*2d9fd380Sjfb8856606 }
461*2d9fd380Sjfb8856606 
462*2d9fd380Sjfb8856606 int
ba_find_next_inuse_free(struct bitalloc * pool,int index)463*2d9fd380Sjfb8856606 ba_find_next_inuse_free(struct bitalloc *pool, int index)
464*2d9fd380Sjfb8856606 {
465*2d9fd380Sjfb8856606 	if (index < 0 ||
466*2d9fd380Sjfb8856606 	    index >= (int)pool->size ||
467*2d9fd380Sjfb8856606 	    pool->free_count == pool->size)
468*2d9fd380Sjfb8856606 		return -1;
469*2d9fd380Sjfb8856606 
470*2d9fd380Sjfb8856606 	return ba_find_next_helper(pool, 0, 1, 32, &index, 1);
471*2d9fd380Sjfb8856606 }
472