xref: /freebsd/contrib/jemalloc/src/bitmap.c (revision 4198293b2568c3fa287e7bde71162e9d442f4305)
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