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