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