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