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