xref: /aosp_15_r20/external/jemalloc_new/include/jemalloc/internal/bitmap.h (revision 1208bc7e437ced7eb82efac44ba17e3beba411da)
1*1208bc7eSAndroid Build Coastguard Worker #ifndef JEMALLOC_INTERNAL_BITMAP_H
2*1208bc7eSAndroid Build Coastguard Worker #define JEMALLOC_INTERNAL_BITMAP_H
3*1208bc7eSAndroid Build Coastguard Worker 
4*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/arena_types.h"
5*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/bit_util.h"
6*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/size_classes.h"
7*1208bc7eSAndroid Build Coastguard Worker 
8*1208bc7eSAndroid Build Coastguard Worker typedef unsigned long bitmap_t;
9*1208bc7eSAndroid Build Coastguard Worker #define LG_SIZEOF_BITMAP	LG_SIZEOF_LONG
10*1208bc7eSAndroid Build Coastguard Worker 
11*1208bc7eSAndroid Build Coastguard Worker /* Maximum bitmap bit count is 2^LG_BITMAP_MAXBITS. */
12*1208bc7eSAndroid Build Coastguard Worker #if LG_SLAB_MAXREGS > LG_CEIL_NSIZES
13*1208bc7eSAndroid Build Coastguard Worker /* Maximum bitmap bit count is determined by maximum regions per slab. */
14*1208bc7eSAndroid Build Coastguard Worker #  define LG_BITMAP_MAXBITS	LG_SLAB_MAXREGS
15*1208bc7eSAndroid Build Coastguard Worker #else
16*1208bc7eSAndroid Build Coastguard Worker /* Maximum bitmap bit count is determined by number of extent size classes. */
17*1208bc7eSAndroid Build Coastguard Worker #  define LG_BITMAP_MAXBITS	LG_CEIL_NSIZES
18*1208bc7eSAndroid Build Coastguard Worker #endif
19*1208bc7eSAndroid Build Coastguard Worker #define BITMAP_MAXBITS		(ZU(1) << LG_BITMAP_MAXBITS)
20*1208bc7eSAndroid Build Coastguard Worker 
21*1208bc7eSAndroid Build Coastguard Worker /* Number of bits per group. */
22*1208bc7eSAndroid Build Coastguard Worker #define LG_BITMAP_GROUP_NBITS		(LG_SIZEOF_BITMAP + 3)
23*1208bc7eSAndroid Build Coastguard Worker #define BITMAP_GROUP_NBITS		(1U << LG_BITMAP_GROUP_NBITS)
24*1208bc7eSAndroid Build Coastguard Worker #define BITMAP_GROUP_NBITS_MASK		(BITMAP_GROUP_NBITS-1)
25*1208bc7eSAndroid Build Coastguard Worker 
26*1208bc7eSAndroid Build Coastguard Worker /*
27*1208bc7eSAndroid Build Coastguard Worker  * Do some analysis on how big the bitmap is before we use a tree.  For a brute
28*1208bc7eSAndroid Build Coastguard Worker  * force linear search, if we would have to call ffs_lu() more than 2^3 times,
29*1208bc7eSAndroid Build Coastguard Worker  * use a tree instead.
30*1208bc7eSAndroid Build Coastguard Worker  */
31*1208bc7eSAndroid Build Coastguard Worker #if LG_BITMAP_MAXBITS - LG_BITMAP_GROUP_NBITS > 3
32*1208bc7eSAndroid Build Coastguard Worker #  define BITMAP_USE_TREE
33*1208bc7eSAndroid Build Coastguard Worker #endif
34*1208bc7eSAndroid Build Coastguard Worker 
35*1208bc7eSAndroid Build Coastguard Worker /* Number of groups required to store a given number of bits. */
36*1208bc7eSAndroid Build Coastguard Worker #define BITMAP_BITS2GROUPS(nbits)					\
37*1208bc7eSAndroid Build Coastguard Worker     (((nbits) + BITMAP_GROUP_NBITS_MASK) >> LG_BITMAP_GROUP_NBITS)
38*1208bc7eSAndroid Build Coastguard Worker 
39*1208bc7eSAndroid Build Coastguard Worker /*
40*1208bc7eSAndroid Build Coastguard Worker  * Number of groups required at a particular level for a given number of bits.
41*1208bc7eSAndroid Build Coastguard Worker  */
42*1208bc7eSAndroid Build Coastguard Worker #define BITMAP_GROUPS_L0(nbits)						\
43*1208bc7eSAndroid Build Coastguard Worker     BITMAP_BITS2GROUPS(nbits)
44*1208bc7eSAndroid Build Coastguard Worker #define BITMAP_GROUPS_L1(nbits)						\
45*1208bc7eSAndroid Build Coastguard Worker     BITMAP_BITS2GROUPS(BITMAP_BITS2GROUPS(nbits))
46*1208bc7eSAndroid Build Coastguard Worker #define BITMAP_GROUPS_L2(nbits)						\
47*1208bc7eSAndroid Build Coastguard Worker     BITMAP_BITS2GROUPS(BITMAP_BITS2GROUPS(BITMAP_BITS2GROUPS((nbits))))
48*1208bc7eSAndroid Build Coastguard Worker #define BITMAP_GROUPS_L3(nbits)						\
49*1208bc7eSAndroid Build Coastguard Worker     BITMAP_BITS2GROUPS(BITMAP_BITS2GROUPS(BITMAP_BITS2GROUPS(		\
50*1208bc7eSAndroid Build Coastguard Worker 	BITMAP_BITS2GROUPS((nbits)))))
51*1208bc7eSAndroid Build Coastguard Worker #define BITMAP_GROUPS_L4(nbits)						\
52*1208bc7eSAndroid Build Coastguard Worker     BITMAP_BITS2GROUPS(BITMAP_BITS2GROUPS(BITMAP_BITS2GROUPS(		\
53*1208bc7eSAndroid Build Coastguard Worker 	BITMAP_BITS2GROUPS(BITMAP_BITS2GROUPS((nbits))))))
54*1208bc7eSAndroid Build Coastguard Worker 
55*1208bc7eSAndroid Build Coastguard Worker /*
56*1208bc7eSAndroid Build Coastguard Worker  * Assuming the number of levels, number of groups required for a given number
57*1208bc7eSAndroid Build Coastguard Worker  * of bits.
58*1208bc7eSAndroid Build Coastguard Worker  */
59*1208bc7eSAndroid Build Coastguard Worker #define BITMAP_GROUPS_1_LEVEL(nbits)					\
60*1208bc7eSAndroid Build Coastguard Worker     BITMAP_GROUPS_L0(nbits)
61*1208bc7eSAndroid Build Coastguard Worker #define BITMAP_GROUPS_2_LEVEL(nbits)					\
62*1208bc7eSAndroid Build Coastguard Worker     (BITMAP_GROUPS_1_LEVEL(nbits) + BITMAP_GROUPS_L1(nbits))
63*1208bc7eSAndroid Build Coastguard Worker #define BITMAP_GROUPS_3_LEVEL(nbits)					\
64*1208bc7eSAndroid Build Coastguard Worker     (BITMAP_GROUPS_2_LEVEL(nbits) + BITMAP_GROUPS_L2(nbits))
65*1208bc7eSAndroid Build Coastguard Worker #define BITMAP_GROUPS_4_LEVEL(nbits)					\
66*1208bc7eSAndroid Build Coastguard Worker     (BITMAP_GROUPS_3_LEVEL(nbits) + BITMAP_GROUPS_L3(nbits))
67*1208bc7eSAndroid Build Coastguard Worker #define BITMAP_GROUPS_5_LEVEL(nbits)					\
68*1208bc7eSAndroid Build Coastguard Worker     (BITMAP_GROUPS_4_LEVEL(nbits) + BITMAP_GROUPS_L4(nbits))
69*1208bc7eSAndroid Build Coastguard Worker 
70*1208bc7eSAndroid Build Coastguard Worker /*
71*1208bc7eSAndroid Build Coastguard Worker  * Maximum number of groups required to support LG_BITMAP_MAXBITS.
72*1208bc7eSAndroid Build Coastguard Worker  */
73*1208bc7eSAndroid Build Coastguard Worker #ifdef BITMAP_USE_TREE
74*1208bc7eSAndroid Build Coastguard Worker 
75*1208bc7eSAndroid Build Coastguard Worker #if LG_BITMAP_MAXBITS <= LG_BITMAP_GROUP_NBITS
76*1208bc7eSAndroid Build Coastguard Worker #  define BITMAP_GROUPS(nbits)	BITMAP_GROUPS_1_LEVEL(nbits)
77*1208bc7eSAndroid Build Coastguard Worker #  define BITMAP_GROUPS_MAX	BITMAP_GROUPS_1_LEVEL(BITMAP_MAXBITS)
78*1208bc7eSAndroid Build Coastguard Worker #elif LG_BITMAP_MAXBITS <= LG_BITMAP_GROUP_NBITS * 2
79*1208bc7eSAndroid Build Coastguard Worker #  define BITMAP_GROUPS(nbits)	BITMAP_GROUPS_2_LEVEL(nbits)
80*1208bc7eSAndroid Build Coastguard Worker #  define BITMAP_GROUPS_MAX	BITMAP_GROUPS_2_LEVEL(BITMAP_MAXBITS)
81*1208bc7eSAndroid Build Coastguard Worker #elif LG_BITMAP_MAXBITS <= LG_BITMAP_GROUP_NBITS * 3
82*1208bc7eSAndroid Build Coastguard Worker #  define BITMAP_GROUPS(nbits)	BITMAP_GROUPS_3_LEVEL(nbits)
83*1208bc7eSAndroid Build Coastguard Worker #  define BITMAP_GROUPS_MAX	BITMAP_GROUPS_3_LEVEL(BITMAP_MAXBITS)
84*1208bc7eSAndroid Build Coastguard Worker #elif LG_BITMAP_MAXBITS <= LG_BITMAP_GROUP_NBITS * 4
85*1208bc7eSAndroid Build Coastguard Worker #  define BITMAP_GROUPS(nbits)	BITMAP_GROUPS_4_LEVEL(nbits)
86*1208bc7eSAndroid Build Coastguard Worker #  define BITMAP_GROUPS_MAX	BITMAP_GROUPS_4_LEVEL(BITMAP_MAXBITS)
87*1208bc7eSAndroid Build Coastguard Worker #elif LG_BITMAP_MAXBITS <= LG_BITMAP_GROUP_NBITS * 5
88*1208bc7eSAndroid Build Coastguard Worker #  define BITMAP_GROUPS(nbits)	BITMAP_GROUPS_5_LEVEL(nbits)
89*1208bc7eSAndroid Build Coastguard Worker #  define BITMAP_GROUPS_MAX	BITMAP_GROUPS_5_LEVEL(BITMAP_MAXBITS)
90*1208bc7eSAndroid Build Coastguard Worker #else
91*1208bc7eSAndroid Build Coastguard Worker #  error "Unsupported bitmap size"
92*1208bc7eSAndroid Build Coastguard Worker #endif
93*1208bc7eSAndroid Build Coastguard Worker 
94*1208bc7eSAndroid Build Coastguard Worker /*
95*1208bc7eSAndroid Build Coastguard Worker  * Maximum number of levels possible.  This could be statically computed based
96*1208bc7eSAndroid Build Coastguard Worker  * on LG_BITMAP_MAXBITS:
97*1208bc7eSAndroid Build Coastguard Worker  *
98*1208bc7eSAndroid Build Coastguard Worker  * #define BITMAP_MAX_LEVELS \
99*1208bc7eSAndroid Build Coastguard Worker  *     (LG_BITMAP_MAXBITS / LG_SIZEOF_BITMAP) \
100*1208bc7eSAndroid Build Coastguard Worker  *     + !!(LG_BITMAP_MAXBITS % LG_SIZEOF_BITMAP)
101*1208bc7eSAndroid Build Coastguard Worker  *
102*1208bc7eSAndroid Build Coastguard Worker  * However, that would not allow the generic BITMAP_INFO_INITIALIZER() macro, so
103*1208bc7eSAndroid Build Coastguard Worker  * instead hardcode BITMAP_MAX_LEVELS to the largest number supported by the
104*1208bc7eSAndroid Build Coastguard Worker  * various cascading macros.  The only additional cost this incurs is some
105*1208bc7eSAndroid Build Coastguard Worker  * unused trailing entries in bitmap_info_t structures; the bitmaps themselves
106*1208bc7eSAndroid Build Coastguard Worker  * are not impacted.
107*1208bc7eSAndroid Build Coastguard Worker  */
108*1208bc7eSAndroid Build Coastguard Worker #define BITMAP_MAX_LEVELS	5
109*1208bc7eSAndroid Build Coastguard Worker 
110*1208bc7eSAndroid Build Coastguard Worker #define BITMAP_INFO_INITIALIZER(nbits) {				\
111*1208bc7eSAndroid Build Coastguard Worker 	/* nbits. */							\
112*1208bc7eSAndroid Build Coastguard Worker 	nbits,								\
113*1208bc7eSAndroid Build Coastguard Worker 	/* nlevels. */							\
114*1208bc7eSAndroid Build Coastguard Worker 	(BITMAP_GROUPS_L0(nbits) > BITMAP_GROUPS_L1(nbits)) +		\
115*1208bc7eSAndroid Build Coastguard Worker 	    (BITMAP_GROUPS_L1(nbits) > BITMAP_GROUPS_L2(nbits)) +	\
116*1208bc7eSAndroid Build Coastguard Worker 	    (BITMAP_GROUPS_L2(nbits) > BITMAP_GROUPS_L3(nbits)) +	\
117*1208bc7eSAndroid Build Coastguard Worker 	    (BITMAP_GROUPS_L3(nbits) > BITMAP_GROUPS_L4(nbits)) + 1,	\
118*1208bc7eSAndroid Build Coastguard Worker 	/* levels. */							\
119*1208bc7eSAndroid Build Coastguard Worker 	{								\
120*1208bc7eSAndroid Build Coastguard Worker 		{0},							\
121*1208bc7eSAndroid Build Coastguard Worker 		{BITMAP_GROUPS_L0(nbits)},				\
122*1208bc7eSAndroid Build Coastguard Worker 		{BITMAP_GROUPS_L1(nbits) + BITMAP_GROUPS_L0(nbits)},	\
123*1208bc7eSAndroid Build Coastguard Worker 		{BITMAP_GROUPS_L2(nbits) + BITMAP_GROUPS_L1(nbits) +	\
124*1208bc7eSAndroid Build Coastguard Worker 		    BITMAP_GROUPS_L0(nbits)},				\
125*1208bc7eSAndroid Build Coastguard Worker 		{BITMAP_GROUPS_L3(nbits) + BITMAP_GROUPS_L2(nbits) +	\
126*1208bc7eSAndroid Build Coastguard Worker 		    BITMAP_GROUPS_L1(nbits) + BITMAP_GROUPS_L0(nbits)},	\
127*1208bc7eSAndroid Build Coastguard Worker 		{BITMAP_GROUPS_L4(nbits) + BITMAP_GROUPS_L3(nbits) +	\
128*1208bc7eSAndroid Build Coastguard Worker 		     BITMAP_GROUPS_L2(nbits) + BITMAP_GROUPS_L1(nbits)	\
129*1208bc7eSAndroid Build Coastguard Worker 		     + BITMAP_GROUPS_L0(nbits)}				\
130*1208bc7eSAndroid Build Coastguard Worker 	}								\
131*1208bc7eSAndroid Build Coastguard Worker }
132*1208bc7eSAndroid Build Coastguard Worker 
133*1208bc7eSAndroid Build Coastguard Worker #else /* BITMAP_USE_TREE */
134*1208bc7eSAndroid Build Coastguard Worker 
135*1208bc7eSAndroid Build Coastguard Worker #define BITMAP_GROUPS(nbits)	BITMAP_BITS2GROUPS(nbits)
136*1208bc7eSAndroid Build Coastguard Worker #define BITMAP_GROUPS_MAX	BITMAP_BITS2GROUPS(BITMAP_MAXBITS)
137*1208bc7eSAndroid Build Coastguard Worker 
138*1208bc7eSAndroid Build Coastguard Worker #define BITMAP_INFO_INITIALIZER(nbits) {				\
139*1208bc7eSAndroid Build Coastguard Worker 	/* nbits. */							\
140*1208bc7eSAndroid Build Coastguard Worker 	nbits,								\
141*1208bc7eSAndroid Build Coastguard Worker 	/* ngroups. */							\
142*1208bc7eSAndroid Build Coastguard Worker 	BITMAP_BITS2GROUPS(nbits)					\
143*1208bc7eSAndroid Build Coastguard Worker }
144*1208bc7eSAndroid Build Coastguard Worker 
145*1208bc7eSAndroid Build Coastguard Worker #endif /* BITMAP_USE_TREE */
146*1208bc7eSAndroid Build Coastguard Worker 
147*1208bc7eSAndroid Build Coastguard Worker typedef struct bitmap_level_s {
148*1208bc7eSAndroid Build Coastguard Worker 	/* Offset of this level's groups within the array of groups. */
149*1208bc7eSAndroid Build Coastguard Worker 	size_t group_offset;
150*1208bc7eSAndroid Build Coastguard Worker } bitmap_level_t;
151*1208bc7eSAndroid Build Coastguard Worker 
152*1208bc7eSAndroid Build Coastguard Worker typedef struct bitmap_info_s {
153*1208bc7eSAndroid Build Coastguard Worker 	/* Logical number of bits in bitmap (stored at bottom level). */
154*1208bc7eSAndroid Build Coastguard Worker 	size_t nbits;
155*1208bc7eSAndroid Build Coastguard Worker 
156*1208bc7eSAndroid Build Coastguard Worker #ifdef BITMAP_USE_TREE
157*1208bc7eSAndroid Build Coastguard Worker 	/* Number of levels necessary for nbits. */
158*1208bc7eSAndroid Build Coastguard Worker 	unsigned nlevels;
159*1208bc7eSAndroid Build Coastguard Worker 
160*1208bc7eSAndroid Build Coastguard Worker 	/*
161*1208bc7eSAndroid Build Coastguard Worker 	 * Only the first (nlevels+1) elements are used, and levels are ordered
162*1208bc7eSAndroid Build Coastguard Worker 	 * bottom to top (e.g. the bottom level is stored in levels[0]).
163*1208bc7eSAndroid Build Coastguard Worker 	 */
164*1208bc7eSAndroid Build Coastguard Worker 	bitmap_level_t levels[BITMAP_MAX_LEVELS+1];
165*1208bc7eSAndroid Build Coastguard Worker #else /* BITMAP_USE_TREE */
166*1208bc7eSAndroid Build Coastguard Worker 	/* Number of groups necessary for nbits. */
167*1208bc7eSAndroid Build Coastguard Worker 	size_t ngroups;
168*1208bc7eSAndroid Build Coastguard Worker #endif /* BITMAP_USE_TREE */
169*1208bc7eSAndroid Build Coastguard Worker } bitmap_info_t;
170*1208bc7eSAndroid Build Coastguard Worker 
171*1208bc7eSAndroid Build Coastguard Worker void bitmap_info_init(bitmap_info_t *binfo, size_t nbits);
172*1208bc7eSAndroid Build Coastguard Worker void bitmap_init(bitmap_t *bitmap, const bitmap_info_t *binfo, bool fill);
173*1208bc7eSAndroid Build Coastguard Worker size_t bitmap_size(const bitmap_info_t *binfo);
174*1208bc7eSAndroid Build Coastguard Worker 
175*1208bc7eSAndroid Build Coastguard Worker static inline bool
bitmap_full(bitmap_t * bitmap,const bitmap_info_t * binfo)176*1208bc7eSAndroid Build Coastguard Worker bitmap_full(bitmap_t *bitmap, const bitmap_info_t *binfo) {
177*1208bc7eSAndroid Build Coastguard Worker #ifdef BITMAP_USE_TREE
178*1208bc7eSAndroid Build Coastguard Worker 	size_t rgoff = binfo->levels[binfo->nlevels].group_offset - 1;
179*1208bc7eSAndroid Build Coastguard Worker 	bitmap_t rg = bitmap[rgoff];
180*1208bc7eSAndroid Build Coastguard Worker 	/* The bitmap is full iff the root group is 0. */
181*1208bc7eSAndroid Build Coastguard Worker 	return (rg == 0);
182*1208bc7eSAndroid Build Coastguard Worker #else
183*1208bc7eSAndroid Build Coastguard Worker 	size_t i;
184*1208bc7eSAndroid Build Coastguard Worker 
185*1208bc7eSAndroid Build Coastguard Worker 	for (i = 0; i < binfo->ngroups; i++) {
186*1208bc7eSAndroid Build Coastguard Worker 		if (bitmap[i] != 0) {
187*1208bc7eSAndroid Build Coastguard Worker 			return false;
188*1208bc7eSAndroid Build Coastguard Worker 		}
189*1208bc7eSAndroid Build Coastguard Worker 	}
190*1208bc7eSAndroid Build Coastguard Worker 	return true;
191*1208bc7eSAndroid Build Coastguard Worker #endif
192*1208bc7eSAndroid Build Coastguard Worker }
193*1208bc7eSAndroid Build Coastguard Worker 
194*1208bc7eSAndroid Build Coastguard Worker static inline bool
bitmap_get(bitmap_t * bitmap,const bitmap_info_t * binfo,size_t bit)195*1208bc7eSAndroid Build Coastguard Worker bitmap_get(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit) {
196*1208bc7eSAndroid Build Coastguard Worker 	size_t goff;
197*1208bc7eSAndroid Build Coastguard Worker 	bitmap_t g;
198*1208bc7eSAndroid Build Coastguard Worker 
199*1208bc7eSAndroid Build Coastguard Worker 	assert(bit < binfo->nbits);
200*1208bc7eSAndroid Build Coastguard Worker 	goff = bit >> LG_BITMAP_GROUP_NBITS;
201*1208bc7eSAndroid Build Coastguard Worker 	g = bitmap[goff];
202*1208bc7eSAndroid Build Coastguard Worker 	return !(g & (ZU(1) << (bit & BITMAP_GROUP_NBITS_MASK)));
203*1208bc7eSAndroid Build Coastguard Worker }
204*1208bc7eSAndroid Build Coastguard Worker 
205*1208bc7eSAndroid Build Coastguard Worker static inline void
bitmap_set(bitmap_t * bitmap,const bitmap_info_t * binfo,size_t bit)206*1208bc7eSAndroid Build Coastguard Worker bitmap_set(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit) {
207*1208bc7eSAndroid Build Coastguard Worker 	size_t goff;
208*1208bc7eSAndroid Build Coastguard Worker 	bitmap_t *gp;
209*1208bc7eSAndroid Build Coastguard Worker 	bitmap_t g;
210*1208bc7eSAndroid Build Coastguard Worker 
211*1208bc7eSAndroid Build Coastguard Worker 	assert(bit < binfo->nbits);
212*1208bc7eSAndroid Build Coastguard Worker 	assert(!bitmap_get(bitmap, binfo, bit));
213*1208bc7eSAndroid Build Coastguard Worker 	goff = bit >> LG_BITMAP_GROUP_NBITS;
214*1208bc7eSAndroid Build Coastguard Worker 	gp = &bitmap[goff];
215*1208bc7eSAndroid Build Coastguard Worker 	g = *gp;
216*1208bc7eSAndroid Build Coastguard Worker 	assert(g & (ZU(1) << (bit & BITMAP_GROUP_NBITS_MASK)));
217*1208bc7eSAndroid Build Coastguard Worker 	g ^= ZU(1) << (bit & BITMAP_GROUP_NBITS_MASK);
218*1208bc7eSAndroid Build Coastguard Worker 	*gp = g;
219*1208bc7eSAndroid Build Coastguard Worker 	assert(bitmap_get(bitmap, binfo, bit));
220*1208bc7eSAndroid Build Coastguard Worker #ifdef BITMAP_USE_TREE
221*1208bc7eSAndroid Build Coastguard Worker 	/* Propagate group state transitions up the tree. */
222*1208bc7eSAndroid Build Coastguard Worker 	if (g == 0) {
223*1208bc7eSAndroid Build Coastguard Worker 		unsigned i;
224*1208bc7eSAndroid Build Coastguard Worker 		for (i = 1; i < binfo->nlevels; i++) {
225*1208bc7eSAndroid Build Coastguard Worker 			bit = goff;
226*1208bc7eSAndroid Build Coastguard Worker 			goff = bit >> LG_BITMAP_GROUP_NBITS;
227*1208bc7eSAndroid Build Coastguard Worker 			gp = &bitmap[binfo->levels[i].group_offset + goff];
228*1208bc7eSAndroid Build Coastguard Worker 			g = *gp;
229*1208bc7eSAndroid Build Coastguard Worker 			assert(g & (ZU(1) << (bit & BITMAP_GROUP_NBITS_MASK)));
230*1208bc7eSAndroid Build Coastguard Worker 			g ^= ZU(1) << (bit & BITMAP_GROUP_NBITS_MASK);
231*1208bc7eSAndroid Build Coastguard Worker 			*gp = g;
232*1208bc7eSAndroid Build Coastguard Worker 			if (g != 0) {
233*1208bc7eSAndroid Build Coastguard Worker 				break;
234*1208bc7eSAndroid Build Coastguard Worker 			}
235*1208bc7eSAndroid Build Coastguard Worker 		}
236*1208bc7eSAndroid Build Coastguard Worker 	}
237*1208bc7eSAndroid Build Coastguard Worker #endif
238*1208bc7eSAndroid Build Coastguard Worker }
239*1208bc7eSAndroid Build Coastguard Worker 
240*1208bc7eSAndroid Build Coastguard Worker /* ffu: find first unset >= bit. */
241*1208bc7eSAndroid Build Coastguard Worker static inline size_t
bitmap_ffu(const bitmap_t * bitmap,const bitmap_info_t * binfo,size_t min_bit)242*1208bc7eSAndroid Build Coastguard Worker bitmap_ffu(const bitmap_t *bitmap, const bitmap_info_t *binfo, size_t min_bit) {
243*1208bc7eSAndroid Build Coastguard Worker 	assert(min_bit < binfo->nbits);
244*1208bc7eSAndroid Build Coastguard Worker 
245*1208bc7eSAndroid Build Coastguard Worker #ifdef BITMAP_USE_TREE
246*1208bc7eSAndroid Build Coastguard Worker 	size_t bit = 0;
247*1208bc7eSAndroid Build Coastguard Worker 	for (unsigned level = binfo->nlevels; level--;) {
248*1208bc7eSAndroid Build Coastguard Worker 		size_t lg_bits_per_group = (LG_BITMAP_GROUP_NBITS * (level +
249*1208bc7eSAndroid Build Coastguard Worker 		    1));
250*1208bc7eSAndroid Build Coastguard Worker 		bitmap_t group = bitmap[binfo->levels[level].group_offset + (bit
251*1208bc7eSAndroid Build Coastguard Worker 		    >> lg_bits_per_group)];
252*1208bc7eSAndroid Build Coastguard Worker 		unsigned group_nmask = (unsigned)(((min_bit > bit) ? (min_bit -
253*1208bc7eSAndroid Build Coastguard Worker 		    bit) : 0) >> (lg_bits_per_group - LG_BITMAP_GROUP_NBITS));
254*1208bc7eSAndroid Build Coastguard Worker 		assert(group_nmask <= BITMAP_GROUP_NBITS);
255*1208bc7eSAndroid Build Coastguard Worker 		bitmap_t group_mask = ~((1LU << group_nmask) - 1);
256*1208bc7eSAndroid Build Coastguard Worker 		bitmap_t group_masked = group & group_mask;
257*1208bc7eSAndroid Build Coastguard Worker 		if (group_masked == 0LU) {
258*1208bc7eSAndroid Build Coastguard Worker 			if (group == 0LU) {
259*1208bc7eSAndroid Build Coastguard Worker 				return binfo->nbits;
260*1208bc7eSAndroid Build Coastguard Worker 			}
261*1208bc7eSAndroid Build Coastguard Worker 			/*
262*1208bc7eSAndroid Build Coastguard Worker 			 * min_bit was preceded by one or more unset bits in
263*1208bc7eSAndroid Build Coastguard Worker 			 * this group, but there are no other unset bits in this
264*1208bc7eSAndroid Build Coastguard Worker 			 * group.  Try again starting at the first bit of the
265*1208bc7eSAndroid Build Coastguard Worker 			 * next sibling.  This will recurse at most once per
266*1208bc7eSAndroid Build Coastguard Worker 			 * non-root level.
267*1208bc7eSAndroid Build Coastguard Worker 			 */
268*1208bc7eSAndroid Build Coastguard Worker 			size_t sib_base = bit + (ZU(1) << lg_bits_per_group);
269*1208bc7eSAndroid Build Coastguard Worker 			assert(sib_base > min_bit);
270*1208bc7eSAndroid Build Coastguard Worker 			assert(sib_base > bit);
271*1208bc7eSAndroid Build Coastguard Worker 			if (sib_base >= binfo->nbits) {
272*1208bc7eSAndroid Build Coastguard Worker 				return binfo->nbits;
273*1208bc7eSAndroid Build Coastguard Worker 			}
274*1208bc7eSAndroid Build Coastguard Worker 			return bitmap_ffu(bitmap, binfo, sib_base);
275*1208bc7eSAndroid Build Coastguard Worker 		}
276*1208bc7eSAndroid Build Coastguard Worker 		bit += ((size_t)(ffs_lu(group_masked) - 1)) <<
277*1208bc7eSAndroid Build Coastguard Worker 		    (lg_bits_per_group - LG_BITMAP_GROUP_NBITS);
278*1208bc7eSAndroid Build Coastguard Worker 	}
279*1208bc7eSAndroid Build Coastguard Worker 	assert(bit >= min_bit);
280*1208bc7eSAndroid Build Coastguard Worker 	assert(bit < binfo->nbits);
281*1208bc7eSAndroid Build Coastguard Worker 	return bit;
282*1208bc7eSAndroid Build Coastguard Worker #else
283*1208bc7eSAndroid Build Coastguard Worker 	size_t i = min_bit >> LG_BITMAP_GROUP_NBITS;
284*1208bc7eSAndroid Build Coastguard Worker 	bitmap_t g = bitmap[i] & ~((1LU << (min_bit & BITMAP_GROUP_NBITS_MASK))
285*1208bc7eSAndroid Build Coastguard Worker 	    - 1);
286*1208bc7eSAndroid Build Coastguard Worker 	size_t bit;
287*1208bc7eSAndroid Build Coastguard Worker 	do {
288*1208bc7eSAndroid Build Coastguard Worker 		bit = ffs_lu(g);
289*1208bc7eSAndroid Build Coastguard Worker 		if (bit != 0) {
290*1208bc7eSAndroid Build Coastguard Worker 			return (i << LG_BITMAP_GROUP_NBITS) + (bit - 1);
291*1208bc7eSAndroid Build Coastguard Worker 		}
292*1208bc7eSAndroid Build Coastguard Worker 		i++;
293*1208bc7eSAndroid Build Coastguard Worker 		g = bitmap[i];
294*1208bc7eSAndroid Build Coastguard Worker 	} while (i < binfo->ngroups);
295*1208bc7eSAndroid Build Coastguard Worker 	return binfo->nbits;
296*1208bc7eSAndroid Build Coastguard Worker #endif
297*1208bc7eSAndroid Build Coastguard Worker }
298*1208bc7eSAndroid Build Coastguard Worker 
299*1208bc7eSAndroid Build Coastguard Worker /* sfu: set first unset. */
300*1208bc7eSAndroid Build Coastguard Worker static inline size_t
bitmap_sfu(bitmap_t * bitmap,const bitmap_info_t * binfo)301*1208bc7eSAndroid Build Coastguard Worker bitmap_sfu(bitmap_t *bitmap, const bitmap_info_t *binfo) {
302*1208bc7eSAndroid Build Coastguard Worker 	size_t bit;
303*1208bc7eSAndroid Build Coastguard Worker 	bitmap_t g;
304*1208bc7eSAndroid Build Coastguard Worker 	unsigned i;
305*1208bc7eSAndroid Build Coastguard Worker 
306*1208bc7eSAndroid Build Coastguard Worker 	assert(!bitmap_full(bitmap, binfo));
307*1208bc7eSAndroid Build Coastguard Worker 
308*1208bc7eSAndroid Build Coastguard Worker #ifdef BITMAP_USE_TREE
309*1208bc7eSAndroid Build Coastguard Worker 	i = binfo->nlevels - 1;
310*1208bc7eSAndroid Build Coastguard Worker 	g = bitmap[binfo->levels[i].group_offset];
311*1208bc7eSAndroid Build Coastguard Worker 	bit = ffs_lu(g) - 1;
312*1208bc7eSAndroid Build Coastguard Worker 	while (i > 0) {
313*1208bc7eSAndroid Build Coastguard Worker 		i--;
314*1208bc7eSAndroid Build Coastguard Worker 		g = bitmap[binfo->levels[i].group_offset + bit];
315*1208bc7eSAndroid Build Coastguard Worker 		bit = (bit << LG_BITMAP_GROUP_NBITS) + (ffs_lu(g) - 1);
316*1208bc7eSAndroid Build Coastguard Worker 	}
317*1208bc7eSAndroid Build Coastguard Worker #else
318*1208bc7eSAndroid Build Coastguard Worker 	i = 0;
319*1208bc7eSAndroid Build Coastguard Worker 	g = bitmap[0];
320*1208bc7eSAndroid Build Coastguard Worker 	while ((bit = ffs_lu(g)) == 0) {
321*1208bc7eSAndroid Build Coastguard Worker 		i++;
322*1208bc7eSAndroid Build Coastguard Worker 		g = bitmap[i];
323*1208bc7eSAndroid Build Coastguard Worker 	}
324*1208bc7eSAndroid Build Coastguard Worker 	bit = (i << LG_BITMAP_GROUP_NBITS) + (bit - 1);
325*1208bc7eSAndroid Build Coastguard Worker #endif
326*1208bc7eSAndroid Build Coastguard Worker 	bitmap_set(bitmap, binfo, bit);
327*1208bc7eSAndroid Build Coastguard Worker 	return bit;
328*1208bc7eSAndroid Build Coastguard Worker }
329*1208bc7eSAndroid Build Coastguard Worker 
330*1208bc7eSAndroid Build Coastguard Worker static inline void
bitmap_unset(bitmap_t * bitmap,const bitmap_info_t * binfo,size_t bit)331*1208bc7eSAndroid Build Coastguard Worker bitmap_unset(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit) {
332*1208bc7eSAndroid Build Coastguard Worker 	size_t goff;
333*1208bc7eSAndroid Build Coastguard Worker 	bitmap_t *gp;
334*1208bc7eSAndroid Build Coastguard Worker 	bitmap_t g;
335*1208bc7eSAndroid Build Coastguard Worker 	UNUSED bool propagate;
336*1208bc7eSAndroid Build Coastguard Worker 
337*1208bc7eSAndroid Build Coastguard Worker 	assert(bit < binfo->nbits);
338*1208bc7eSAndroid Build Coastguard Worker 	assert(bitmap_get(bitmap, binfo, bit));
339*1208bc7eSAndroid Build Coastguard Worker 	goff = bit >> LG_BITMAP_GROUP_NBITS;
340*1208bc7eSAndroid Build Coastguard Worker 	gp = &bitmap[goff];
341*1208bc7eSAndroid Build Coastguard Worker 	g = *gp;
342*1208bc7eSAndroid Build Coastguard Worker 	propagate = (g == 0);
343*1208bc7eSAndroid Build Coastguard Worker 	assert((g & (ZU(1) << (bit & BITMAP_GROUP_NBITS_MASK))) == 0);
344*1208bc7eSAndroid Build Coastguard Worker 	g ^= ZU(1) << (bit & BITMAP_GROUP_NBITS_MASK);
345*1208bc7eSAndroid Build Coastguard Worker 	*gp = g;
346*1208bc7eSAndroid Build Coastguard Worker 	assert(!bitmap_get(bitmap, binfo, bit));
347*1208bc7eSAndroid Build Coastguard Worker #ifdef BITMAP_USE_TREE
348*1208bc7eSAndroid Build Coastguard Worker 	/* Propagate group state transitions up the tree. */
349*1208bc7eSAndroid Build Coastguard Worker 	if (propagate) {
350*1208bc7eSAndroid Build Coastguard Worker 		unsigned i;
351*1208bc7eSAndroid Build Coastguard Worker 		for (i = 1; i < binfo->nlevels; i++) {
352*1208bc7eSAndroid Build Coastguard Worker 			bit = goff;
353*1208bc7eSAndroid Build Coastguard Worker 			goff = bit >> LG_BITMAP_GROUP_NBITS;
354*1208bc7eSAndroid Build Coastguard Worker 			gp = &bitmap[binfo->levels[i].group_offset + goff];
355*1208bc7eSAndroid Build Coastguard Worker 			g = *gp;
356*1208bc7eSAndroid Build Coastguard Worker 			propagate = (g == 0);
357*1208bc7eSAndroid Build Coastguard Worker 			assert((g & (ZU(1) << (bit & BITMAP_GROUP_NBITS_MASK)))
358*1208bc7eSAndroid Build Coastguard Worker 			    == 0);
359*1208bc7eSAndroid Build Coastguard Worker 			g ^= ZU(1) << (bit & BITMAP_GROUP_NBITS_MASK);
360*1208bc7eSAndroid Build Coastguard Worker 			*gp = g;
361*1208bc7eSAndroid Build Coastguard Worker 			if (!propagate) {
362*1208bc7eSAndroid Build Coastguard Worker 				break;
363*1208bc7eSAndroid Build Coastguard Worker 			}
364*1208bc7eSAndroid Build Coastguard Worker 		}
365*1208bc7eSAndroid Build Coastguard Worker 	}
366*1208bc7eSAndroid Build Coastguard Worker #endif /* BITMAP_USE_TREE */
367*1208bc7eSAndroid Build Coastguard Worker }
368*1208bc7eSAndroid Build Coastguard Worker 
369*1208bc7eSAndroid Build Coastguard Worker #endif /* JEMALLOC_INTERNAL_BITMAP_H */
370