xref: /aosp_15_r20/external/jemalloc_new/src/bitmap.c (revision 1208bc7e437ced7eb82efac44ba17e3beba411da)
1*1208bc7eSAndroid Build Coastguard Worker #define JEMALLOC_BITMAP_C_
2*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/jemalloc_preamble.h"
3*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/jemalloc_internal_includes.h"
4*1208bc7eSAndroid Build Coastguard Worker 
5*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/assert.h"
6*1208bc7eSAndroid Build Coastguard Worker 
7*1208bc7eSAndroid Build Coastguard Worker /******************************************************************************/
8*1208bc7eSAndroid Build Coastguard Worker 
9*1208bc7eSAndroid Build Coastguard Worker #ifdef BITMAP_USE_TREE
10*1208bc7eSAndroid Build Coastguard Worker 
11*1208bc7eSAndroid Build Coastguard Worker void
bitmap_info_init(bitmap_info_t * binfo,size_t nbits)12*1208bc7eSAndroid Build Coastguard Worker bitmap_info_init(bitmap_info_t *binfo, size_t nbits) {
13*1208bc7eSAndroid Build Coastguard Worker 	unsigned i;
14*1208bc7eSAndroid Build Coastguard Worker 	size_t group_count;
15*1208bc7eSAndroid Build Coastguard Worker 
16*1208bc7eSAndroid Build Coastguard Worker 	assert(nbits > 0);
17*1208bc7eSAndroid Build Coastguard Worker 	assert(nbits <= (ZU(1) << LG_BITMAP_MAXBITS));
18*1208bc7eSAndroid Build Coastguard Worker 
19*1208bc7eSAndroid Build Coastguard Worker 	/*
20*1208bc7eSAndroid Build Coastguard Worker 	 * Compute the number of groups necessary to store nbits bits, and
21*1208bc7eSAndroid Build Coastguard Worker 	 * progressively work upward through the levels until reaching a level
22*1208bc7eSAndroid Build Coastguard Worker 	 * that requires only one group.
23*1208bc7eSAndroid Build Coastguard Worker 	 */
24*1208bc7eSAndroid Build Coastguard Worker 	binfo->levels[0].group_offset = 0;
25*1208bc7eSAndroid Build Coastguard Worker 	group_count = BITMAP_BITS2GROUPS(nbits);
26*1208bc7eSAndroid Build Coastguard Worker 	for (i = 1; group_count > 1; i++) {
27*1208bc7eSAndroid Build Coastguard Worker 		assert(i < BITMAP_MAX_LEVELS);
28*1208bc7eSAndroid Build Coastguard Worker 		binfo->levels[i].group_offset = binfo->levels[i-1].group_offset
29*1208bc7eSAndroid Build Coastguard Worker 		    + group_count;
30*1208bc7eSAndroid Build Coastguard Worker 		group_count = BITMAP_BITS2GROUPS(group_count);
31*1208bc7eSAndroid Build Coastguard Worker 	}
32*1208bc7eSAndroid Build Coastguard Worker 	binfo->levels[i].group_offset = binfo->levels[i-1].group_offset
33*1208bc7eSAndroid Build Coastguard Worker 	    + group_count;
34*1208bc7eSAndroid Build Coastguard Worker 	assert(binfo->levels[i].group_offset <= BITMAP_GROUPS_MAX);
35*1208bc7eSAndroid Build Coastguard Worker 	binfo->nlevels = i;
36*1208bc7eSAndroid Build Coastguard Worker 	binfo->nbits = nbits;
37*1208bc7eSAndroid Build Coastguard Worker }
38*1208bc7eSAndroid Build Coastguard Worker 
39*1208bc7eSAndroid Build Coastguard Worker static size_t
bitmap_info_ngroups(const bitmap_info_t * binfo)40*1208bc7eSAndroid Build Coastguard Worker bitmap_info_ngroups(const bitmap_info_t *binfo) {
41*1208bc7eSAndroid Build Coastguard Worker 	return binfo->levels[binfo->nlevels].group_offset;
42*1208bc7eSAndroid Build Coastguard Worker }
43*1208bc7eSAndroid Build Coastguard Worker 
44*1208bc7eSAndroid Build Coastguard Worker void
bitmap_init(bitmap_t * bitmap,const bitmap_info_t * binfo,bool fill)45*1208bc7eSAndroid Build Coastguard Worker bitmap_init(bitmap_t *bitmap, const bitmap_info_t *binfo, bool fill) {
46*1208bc7eSAndroid Build Coastguard Worker 	size_t extra;
47*1208bc7eSAndroid Build Coastguard Worker 	unsigned i;
48*1208bc7eSAndroid Build Coastguard Worker 
49*1208bc7eSAndroid Build Coastguard Worker 	/*
50*1208bc7eSAndroid Build Coastguard Worker 	 * Bits are actually inverted with regard to the external bitmap
51*1208bc7eSAndroid Build Coastguard Worker 	 * interface.
52*1208bc7eSAndroid Build Coastguard Worker 	 */
53*1208bc7eSAndroid Build Coastguard Worker 
54*1208bc7eSAndroid Build Coastguard Worker 	if (fill) {
55*1208bc7eSAndroid Build Coastguard Worker 		/* The "filled" bitmap starts out with all 0 bits. */
56*1208bc7eSAndroid Build Coastguard Worker 		memset(bitmap, 0, bitmap_size(binfo));
57*1208bc7eSAndroid Build Coastguard Worker 		return;
58*1208bc7eSAndroid Build Coastguard Worker 	}
59*1208bc7eSAndroid Build Coastguard Worker 
60*1208bc7eSAndroid Build Coastguard Worker 	/*
61*1208bc7eSAndroid Build Coastguard Worker 	 * The "empty" bitmap starts out with all 1 bits, except for trailing
62*1208bc7eSAndroid Build Coastguard Worker 	 * unused bits (if any).  Note that each group uses bit 0 to correspond
63*1208bc7eSAndroid Build Coastguard Worker 	 * to the first logical bit in the group, so extra bits are the most
64*1208bc7eSAndroid Build Coastguard Worker 	 * significant bits of the last group.
65*1208bc7eSAndroid Build Coastguard Worker 	 */
66*1208bc7eSAndroid Build Coastguard Worker 	memset(bitmap, 0xffU, bitmap_size(binfo));
67*1208bc7eSAndroid Build Coastguard Worker 	extra = (BITMAP_GROUP_NBITS - (binfo->nbits & BITMAP_GROUP_NBITS_MASK))
68*1208bc7eSAndroid Build Coastguard Worker 	    & BITMAP_GROUP_NBITS_MASK;
69*1208bc7eSAndroid Build Coastguard Worker 	if (extra != 0) {
70*1208bc7eSAndroid Build Coastguard Worker 		bitmap[binfo->levels[1].group_offset - 1] >>= extra;
71*1208bc7eSAndroid Build Coastguard Worker 	}
72*1208bc7eSAndroid Build Coastguard Worker 	for (i = 1; i < binfo->nlevels; i++) {
73*1208bc7eSAndroid Build Coastguard Worker 		size_t group_count = binfo->levels[i].group_offset -
74*1208bc7eSAndroid Build Coastguard Worker 		    binfo->levels[i-1].group_offset;
75*1208bc7eSAndroid Build Coastguard Worker 		extra = (BITMAP_GROUP_NBITS - (group_count &
76*1208bc7eSAndroid Build Coastguard Worker 		    BITMAP_GROUP_NBITS_MASK)) & BITMAP_GROUP_NBITS_MASK;
77*1208bc7eSAndroid Build Coastguard Worker 		if (extra != 0) {
78*1208bc7eSAndroid Build Coastguard Worker 			bitmap[binfo->levels[i+1].group_offset - 1] >>= extra;
79*1208bc7eSAndroid Build Coastguard Worker 		}
80*1208bc7eSAndroid Build Coastguard Worker 	}
81*1208bc7eSAndroid Build Coastguard Worker }
82*1208bc7eSAndroid Build Coastguard Worker 
83*1208bc7eSAndroid Build Coastguard Worker #else /* BITMAP_USE_TREE */
84*1208bc7eSAndroid Build Coastguard Worker 
85*1208bc7eSAndroid Build Coastguard Worker void
bitmap_info_init(bitmap_info_t * binfo,size_t nbits)86*1208bc7eSAndroid Build Coastguard Worker bitmap_info_init(bitmap_info_t *binfo, size_t nbits) {
87*1208bc7eSAndroid Build Coastguard Worker 	assert(nbits > 0);
88*1208bc7eSAndroid Build Coastguard Worker 	assert(nbits <= (ZU(1) << LG_BITMAP_MAXBITS));
89*1208bc7eSAndroid Build Coastguard Worker 
90*1208bc7eSAndroid Build Coastguard Worker 	binfo->ngroups = BITMAP_BITS2GROUPS(nbits);
91*1208bc7eSAndroid Build Coastguard Worker 	binfo->nbits = nbits;
92*1208bc7eSAndroid Build Coastguard Worker }
93*1208bc7eSAndroid Build Coastguard Worker 
94*1208bc7eSAndroid Build Coastguard Worker static size_t
bitmap_info_ngroups(const bitmap_info_t * binfo)95*1208bc7eSAndroid Build Coastguard Worker bitmap_info_ngroups(const bitmap_info_t *binfo) {
96*1208bc7eSAndroid Build Coastguard Worker 	return binfo->ngroups;
97*1208bc7eSAndroid Build Coastguard Worker }
98*1208bc7eSAndroid Build Coastguard Worker 
99*1208bc7eSAndroid Build Coastguard Worker void
bitmap_init(bitmap_t * bitmap,const bitmap_info_t * binfo,bool fill)100*1208bc7eSAndroid Build Coastguard Worker bitmap_init(bitmap_t *bitmap, const bitmap_info_t *binfo, bool fill) {
101*1208bc7eSAndroid Build Coastguard Worker 	size_t extra;
102*1208bc7eSAndroid Build Coastguard Worker 
103*1208bc7eSAndroid Build Coastguard Worker 	if (fill) {
104*1208bc7eSAndroid Build Coastguard Worker 		memset(bitmap, 0, bitmap_size(binfo));
105*1208bc7eSAndroid Build Coastguard Worker 		return;
106*1208bc7eSAndroid Build Coastguard Worker 	}
107*1208bc7eSAndroid Build Coastguard Worker 
108*1208bc7eSAndroid Build Coastguard Worker 	memset(bitmap, 0xffU, bitmap_size(binfo));
109*1208bc7eSAndroid Build Coastguard Worker 	extra = (BITMAP_GROUP_NBITS - (binfo->nbits & BITMAP_GROUP_NBITS_MASK))
110*1208bc7eSAndroid Build Coastguard Worker 	    & BITMAP_GROUP_NBITS_MASK;
111*1208bc7eSAndroid Build Coastguard Worker 	if (extra != 0) {
112*1208bc7eSAndroid Build Coastguard Worker 		bitmap[binfo->ngroups - 1] >>= extra;
113*1208bc7eSAndroid Build Coastguard Worker 	}
114*1208bc7eSAndroid Build Coastguard Worker }
115*1208bc7eSAndroid Build Coastguard Worker 
116*1208bc7eSAndroid Build Coastguard Worker #endif /* BITMAP_USE_TREE */
117*1208bc7eSAndroid Build Coastguard Worker 
118*1208bc7eSAndroid Build Coastguard Worker size_t
bitmap_size(const bitmap_info_t * binfo)119*1208bc7eSAndroid Build Coastguard Worker bitmap_size(const bitmap_info_t *binfo) {
120*1208bc7eSAndroid Build Coastguard Worker 	return (bitmap_info_ngroups(binfo) << LG_SIZEOF_BITMAP);
121*1208bc7eSAndroid Build Coastguard Worker }
122