Statistics
| Branch: | Revision:

root / util / hbitmap.c @ 626187d8

History | View | Annotate | Download (12.5 kB)

1 e7c033c3 Paolo Bonzini
/*
2 e7c033c3 Paolo Bonzini
 * Hierarchical Bitmap Data Type
3 e7c033c3 Paolo Bonzini
 *
4 e7c033c3 Paolo Bonzini
 * Copyright Red Hat, Inc., 2012
5 e7c033c3 Paolo Bonzini
 *
6 e7c033c3 Paolo Bonzini
 * Author: Paolo Bonzini <pbonzini@redhat.com>
7 e7c033c3 Paolo Bonzini
 *
8 e7c033c3 Paolo Bonzini
 * This work is licensed under the terms of the GNU GPL, version 2 or
9 e7c033c3 Paolo Bonzini
 * later.  See the COPYING file in the top-level directory.
10 e7c033c3 Paolo Bonzini
 */
11 e7c033c3 Paolo Bonzini
12 e7c033c3 Paolo Bonzini
#include <string.h>
13 e7c033c3 Paolo Bonzini
#include <glib.h>
14 e7c033c3 Paolo Bonzini
#include <assert.h>
15 e7c033c3 Paolo Bonzini
#include "qemu/osdep.h"
16 e7c033c3 Paolo Bonzini
#include "qemu/hbitmap.h"
17 e7c033c3 Paolo Bonzini
#include "qemu/host-utils.h"
18 e7c033c3 Paolo Bonzini
#include "trace.h"
19 e7c033c3 Paolo Bonzini
20 e7c033c3 Paolo Bonzini
/* HBitmaps provides an array of bits.  The bits are stored as usual in an
21 e7c033c3 Paolo Bonzini
 * array of unsigned longs, but HBitmap is also optimized to provide fast
22 e7c033c3 Paolo Bonzini
 * iteration over set bits; going from one bit to the next is O(logB n)
23 e7c033c3 Paolo Bonzini
 * worst case, with B = sizeof(long) * CHAR_BIT: the result is low enough
24 e7c033c3 Paolo Bonzini
 * that the number of levels is in fact fixed.
25 e7c033c3 Paolo Bonzini
 *
26 e7c033c3 Paolo Bonzini
 * In order to do this, it stacks multiple bitmaps with progressively coarser
27 e7c033c3 Paolo Bonzini
 * granularity; in all levels except the last, bit N is set iff the N-th
28 e7c033c3 Paolo Bonzini
 * unsigned long is nonzero in the immediately next level.  When iteration
29 e7c033c3 Paolo Bonzini
 * completes on the last level it can examine the 2nd-last level to quickly
30 e7c033c3 Paolo Bonzini
 * skip entire words, and even do so recursively to skip blocks of 64 words or
31 e7c033c3 Paolo Bonzini
 * powers thereof (32 on 32-bit machines).
32 e7c033c3 Paolo Bonzini
 *
33 e7c033c3 Paolo Bonzini
 * Given an index in the bitmap, it can be split in group of bits like
34 e7c033c3 Paolo Bonzini
 * this (for the 64-bit case):
35 e7c033c3 Paolo Bonzini
 *
36 e7c033c3 Paolo Bonzini
 *   bits 0-57 => word in the last bitmap     | bits 58-63 => bit in the word
37 e7c033c3 Paolo Bonzini
 *   bits 0-51 => word in the 2nd-last bitmap | bits 52-57 => bit in the word
38 e7c033c3 Paolo Bonzini
 *   bits 0-45 => word in the 3rd-last bitmap | bits 46-51 => bit in the word
39 e7c033c3 Paolo Bonzini
 *
40 e7c033c3 Paolo Bonzini
 * So it is easy to move up simply by shifting the index right by
41 e7c033c3 Paolo Bonzini
 * log2(BITS_PER_LONG) bits.  To move down, you shift the index left
42 e7c033c3 Paolo Bonzini
 * similarly, and add the word index within the group.  Iteration uses
43 e7c033c3 Paolo Bonzini
 * ffs (find first set bit) to find the next word to examine; this
44 e7c033c3 Paolo Bonzini
 * operation can be done in constant time in most current architectures.
45 e7c033c3 Paolo Bonzini
 *
46 e7c033c3 Paolo Bonzini
 * Setting or clearing a range of m bits on all levels, the work to perform
47 e7c033c3 Paolo Bonzini
 * is O(m + m/W + m/W^2 + ...), which is O(m) like on a regular bitmap.
48 e7c033c3 Paolo Bonzini
 *
49 e7c033c3 Paolo Bonzini
 * When iterating on a bitmap, each bit (on any level) is only visited
50 e7c033c3 Paolo Bonzini
 * once.  Hence, The total cost of visiting a bitmap with m bits in it is
51 e7c033c3 Paolo Bonzini
 * the number of bits that are set in all bitmaps.  Unless the bitmap is
52 e7c033c3 Paolo Bonzini
 * extremely sparse, this is also O(m + m/W + m/W^2 + ...), so the amortized
53 e7c033c3 Paolo Bonzini
 * cost of advancing from one bit to the next is usually constant (worst case
54 e7c033c3 Paolo Bonzini
 * O(logB n) as in the non-amortized complexity).
55 e7c033c3 Paolo Bonzini
 */
56 e7c033c3 Paolo Bonzini
57 e7c033c3 Paolo Bonzini
struct HBitmap {
58 e7c033c3 Paolo Bonzini
    /* Number of total bits in the bottom level.  */
59 e7c033c3 Paolo Bonzini
    uint64_t size;
60 e7c033c3 Paolo Bonzini
61 e7c033c3 Paolo Bonzini
    /* Number of set bits in the bottom level.  */
62 e7c033c3 Paolo Bonzini
    uint64_t count;
63 e7c033c3 Paolo Bonzini
64 e7c033c3 Paolo Bonzini
    /* A scaling factor.  Given a granularity of G, each bit in the bitmap will
65 e7c033c3 Paolo Bonzini
     * will actually represent a group of 2^G elements.  Each operation on a
66 e7c033c3 Paolo Bonzini
     * range of bits first rounds the bits to determine which group they land
67 e7c033c3 Paolo Bonzini
     * in, and then affect the entire page; iteration will only visit the first
68 e7c033c3 Paolo Bonzini
     * bit of each group.  Here is an example of operations in a size-16,
69 e7c033c3 Paolo Bonzini
     * granularity-1 HBitmap:
70 e7c033c3 Paolo Bonzini
     *
71 e7c033c3 Paolo Bonzini
     *    initial state            00000000
72 e7c033c3 Paolo Bonzini
     *    set(start=0, count=9)    11111000 (iter: 0, 2, 4, 6, 8)
73 e7c033c3 Paolo Bonzini
     *    reset(start=1, count=3)  00111000 (iter: 4, 6, 8)
74 e7c033c3 Paolo Bonzini
     *    set(start=9, count=2)    00111100 (iter: 4, 6, 8, 10)
75 e7c033c3 Paolo Bonzini
     *    reset(start=5, count=5)  00000000
76 e7c033c3 Paolo Bonzini
     *
77 e7c033c3 Paolo Bonzini
     * From an implementation point of view, when setting or resetting bits,
78 e7c033c3 Paolo Bonzini
     * the bitmap will scale bit numbers right by this amount of bits.  When
79 e7c033c3 Paolo Bonzini
     * iterating, the bitmap will scale bit numbers left by this amount of
80 e7c033c3 Paolo Bonzini
     * bits.
81 e7c033c3 Paolo Bonzini
     */
82 e7c033c3 Paolo Bonzini
    int granularity;
83 e7c033c3 Paolo Bonzini
84 e7c033c3 Paolo Bonzini
    /* A number of progressively less coarse bitmaps (i.e. level 0 is the
85 e7c033c3 Paolo Bonzini
     * coarsest).  Each bit in level N represents a word in level N+1 that
86 e7c033c3 Paolo Bonzini
     * has a set bit, except the last level where each bit represents the
87 e7c033c3 Paolo Bonzini
     * actual bitmap.
88 e7c033c3 Paolo Bonzini
     *
89 e7c033c3 Paolo Bonzini
     * Note that all bitmaps have the same number of levels.  Even a 1-bit
90 e7c033c3 Paolo Bonzini
     * bitmap will still allocate HBITMAP_LEVELS arrays.
91 e7c033c3 Paolo Bonzini
     */
92 e7c033c3 Paolo Bonzini
    unsigned long *levels[HBITMAP_LEVELS];
93 e7c033c3 Paolo Bonzini
};
94 e7c033c3 Paolo Bonzini
95 e7c033c3 Paolo Bonzini
static inline int popcountl(unsigned long l)
96 e7c033c3 Paolo Bonzini
{
97 e7c033c3 Paolo Bonzini
    return BITS_PER_LONG == 32 ? ctpop32(l) : ctpop64(l);
98 e7c033c3 Paolo Bonzini
}
99 e7c033c3 Paolo Bonzini
100 e7c033c3 Paolo Bonzini
/* Advance hbi to the next nonzero word and return it.  hbi->pos
101 e7c033c3 Paolo Bonzini
 * is updated.  Returns zero if we reach the end of the bitmap.
102 e7c033c3 Paolo Bonzini
 */
103 e7c033c3 Paolo Bonzini
unsigned long hbitmap_iter_skip_words(HBitmapIter *hbi)
104 e7c033c3 Paolo Bonzini
{
105 e7c033c3 Paolo Bonzini
    size_t pos = hbi->pos;
106 e7c033c3 Paolo Bonzini
    const HBitmap *hb = hbi->hb;
107 e7c033c3 Paolo Bonzini
    unsigned i = HBITMAP_LEVELS - 1;
108 e7c033c3 Paolo Bonzini
109 e7c033c3 Paolo Bonzini
    unsigned long cur;
110 e7c033c3 Paolo Bonzini
    do {
111 e7c033c3 Paolo Bonzini
        cur = hbi->cur[--i];
112 e7c033c3 Paolo Bonzini
        pos >>= BITS_PER_LEVEL;
113 e7c033c3 Paolo Bonzini
    } while (cur == 0);
114 e7c033c3 Paolo Bonzini
115 e7c033c3 Paolo Bonzini
    /* Check for end of iteration.  We always use fewer than BITS_PER_LONG
116 e7c033c3 Paolo Bonzini
     * bits in the level 0 bitmap; thus we can repurpose the most significant
117 e7c033c3 Paolo Bonzini
     * bit as a sentinel.  The sentinel is set in hbitmap_alloc and ensures
118 e7c033c3 Paolo Bonzini
     * that the above loop ends even without an explicit check on i.
119 e7c033c3 Paolo Bonzini
     */
120 e7c033c3 Paolo Bonzini
121 e7c033c3 Paolo Bonzini
    if (i == 0 && cur == (1UL << (BITS_PER_LONG - 1))) {
122 e7c033c3 Paolo Bonzini
        return 0;
123 e7c033c3 Paolo Bonzini
    }
124 e7c033c3 Paolo Bonzini
    for (; i < HBITMAP_LEVELS - 1; i++) {
125 e7c033c3 Paolo Bonzini
        /* Shift back pos to the left, matching the right shifts above.
126 e7c033c3 Paolo Bonzini
         * The index of this word's least significant set bit provides
127 e7c033c3 Paolo Bonzini
         * the low-order bits.
128 e7c033c3 Paolo Bonzini
         */
129 18331e7c Richard Henderson
        assert(cur);
130 18331e7c Richard Henderson
        pos = (pos << BITS_PER_LEVEL) + ctzl(cur);
131 e7c033c3 Paolo Bonzini
        hbi->cur[i] = cur & (cur - 1);
132 e7c033c3 Paolo Bonzini
133 e7c033c3 Paolo Bonzini
        /* Set up next level for iteration.  */
134 e7c033c3 Paolo Bonzini
        cur = hb->levels[i + 1][pos];
135 e7c033c3 Paolo Bonzini
    }
136 e7c033c3 Paolo Bonzini
137 e7c033c3 Paolo Bonzini
    hbi->pos = pos;
138 e7c033c3 Paolo Bonzini
    trace_hbitmap_iter_skip_words(hbi->hb, hbi, pos, cur);
139 e7c033c3 Paolo Bonzini
140 e7c033c3 Paolo Bonzini
    assert(cur);
141 e7c033c3 Paolo Bonzini
    return cur;
142 e7c033c3 Paolo Bonzini
}
143 e7c033c3 Paolo Bonzini
144 e7c033c3 Paolo Bonzini
void hbitmap_iter_init(HBitmapIter *hbi, const HBitmap *hb, uint64_t first)
145 e7c033c3 Paolo Bonzini
{
146 e7c033c3 Paolo Bonzini
    unsigned i, bit;
147 e7c033c3 Paolo Bonzini
    uint64_t pos;
148 e7c033c3 Paolo Bonzini
149 e7c033c3 Paolo Bonzini
    hbi->hb = hb;
150 e7c033c3 Paolo Bonzini
    pos = first >> hb->granularity;
151 1b095244 Paolo Bonzini
    assert(pos < hb->size);
152 e7c033c3 Paolo Bonzini
    hbi->pos = pos >> BITS_PER_LEVEL;
153 e7c033c3 Paolo Bonzini
    hbi->granularity = hb->granularity;
154 e7c033c3 Paolo Bonzini
155 e7c033c3 Paolo Bonzini
    for (i = HBITMAP_LEVELS; i-- > 0; ) {
156 e7c033c3 Paolo Bonzini
        bit = pos & (BITS_PER_LONG - 1);
157 e7c033c3 Paolo Bonzini
        pos >>= BITS_PER_LEVEL;
158 e7c033c3 Paolo Bonzini
159 e7c033c3 Paolo Bonzini
        /* Drop bits representing items before first.  */
160 e7c033c3 Paolo Bonzini
        hbi->cur[i] = hb->levels[i][pos] & ~((1UL << bit) - 1);
161 e7c033c3 Paolo Bonzini
162 e7c033c3 Paolo Bonzini
        /* We have already added level i+1, so the lowest set bit has
163 e7c033c3 Paolo Bonzini
         * been processed.  Clear it.
164 e7c033c3 Paolo Bonzini
         */
165 e7c033c3 Paolo Bonzini
        if (i != HBITMAP_LEVELS - 1) {
166 e7c033c3 Paolo Bonzini
            hbi->cur[i] &= ~(1UL << bit);
167 e7c033c3 Paolo Bonzini
        }
168 e7c033c3 Paolo Bonzini
    }
169 e7c033c3 Paolo Bonzini
}
170 e7c033c3 Paolo Bonzini
171 e7c033c3 Paolo Bonzini
bool hbitmap_empty(const HBitmap *hb)
172 e7c033c3 Paolo Bonzini
{
173 e7c033c3 Paolo Bonzini
    return hb->count == 0;
174 e7c033c3 Paolo Bonzini
}
175 e7c033c3 Paolo Bonzini
176 e7c033c3 Paolo Bonzini
int hbitmap_granularity(const HBitmap *hb)
177 e7c033c3 Paolo Bonzini
{
178 e7c033c3 Paolo Bonzini
    return hb->granularity;
179 e7c033c3 Paolo Bonzini
}
180 e7c033c3 Paolo Bonzini
181 e7c033c3 Paolo Bonzini
uint64_t hbitmap_count(const HBitmap *hb)
182 e7c033c3 Paolo Bonzini
{
183 e7c033c3 Paolo Bonzini
    return hb->count << hb->granularity;
184 e7c033c3 Paolo Bonzini
}
185 e7c033c3 Paolo Bonzini
186 e7c033c3 Paolo Bonzini
/* Count the number of set bits between start and end, not accounting for
187 e7c033c3 Paolo Bonzini
 * the granularity.  Also an example of how to use hbitmap_iter_next_word.
188 e7c033c3 Paolo Bonzini
 */
189 e7c033c3 Paolo Bonzini
static uint64_t hb_count_between(HBitmap *hb, uint64_t start, uint64_t last)
190 e7c033c3 Paolo Bonzini
{
191 e7c033c3 Paolo Bonzini
    HBitmapIter hbi;
192 e7c033c3 Paolo Bonzini
    uint64_t count = 0;
193 e7c033c3 Paolo Bonzini
    uint64_t end = last + 1;
194 e7c033c3 Paolo Bonzini
    unsigned long cur;
195 e7c033c3 Paolo Bonzini
    size_t pos;
196 e7c033c3 Paolo Bonzini
197 e7c033c3 Paolo Bonzini
    hbitmap_iter_init(&hbi, hb, start << hb->granularity);
198 e7c033c3 Paolo Bonzini
    for (;;) {
199 e7c033c3 Paolo Bonzini
        pos = hbitmap_iter_next_word(&hbi, &cur);
200 e7c033c3 Paolo Bonzini
        if (pos >= (end >> BITS_PER_LEVEL)) {
201 e7c033c3 Paolo Bonzini
            break;
202 e7c033c3 Paolo Bonzini
        }
203 e7c033c3 Paolo Bonzini
        count += popcountl(cur);
204 e7c033c3 Paolo Bonzini
    }
205 e7c033c3 Paolo Bonzini
206 e7c033c3 Paolo Bonzini
    if (pos == (end >> BITS_PER_LEVEL)) {
207 e7c033c3 Paolo Bonzini
        /* Drop bits representing the END-th and subsequent items.  */
208 e7c033c3 Paolo Bonzini
        int bit = end & (BITS_PER_LONG - 1);
209 e7c033c3 Paolo Bonzini
        cur &= (1UL << bit) - 1;
210 e7c033c3 Paolo Bonzini
        count += popcountl(cur);
211 e7c033c3 Paolo Bonzini
    }
212 e7c033c3 Paolo Bonzini
213 e7c033c3 Paolo Bonzini
    return count;
214 e7c033c3 Paolo Bonzini
}
215 e7c033c3 Paolo Bonzini
216 e7c033c3 Paolo Bonzini
/* Setting starts at the last layer and propagates up if an element
217 e7c033c3 Paolo Bonzini
 * changes from zero to non-zero.
218 e7c033c3 Paolo Bonzini
 */
219 e7c033c3 Paolo Bonzini
static inline bool hb_set_elem(unsigned long *elem, uint64_t start, uint64_t last)
220 e7c033c3 Paolo Bonzini
{
221 e7c033c3 Paolo Bonzini
    unsigned long mask;
222 e7c033c3 Paolo Bonzini
    bool changed;
223 e7c033c3 Paolo Bonzini
224 e7c033c3 Paolo Bonzini
    assert((last >> BITS_PER_LEVEL) == (start >> BITS_PER_LEVEL));
225 e7c033c3 Paolo Bonzini
    assert(start <= last);
226 e7c033c3 Paolo Bonzini
227 e7c033c3 Paolo Bonzini
    mask = 2UL << (last & (BITS_PER_LONG - 1));
228 e7c033c3 Paolo Bonzini
    mask -= 1UL << (start & (BITS_PER_LONG - 1));
229 e7c033c3 Paolo Bonzini
    changed = (*elem == 0);
230 e7c033c3 Paolo Bonzini
    *elem |= mask;
231 e7c033c3 Paolo Bonzini
    return changed;
232 e7c033c3 Paolo Bonzini
}
233 e7c033c3 Paolo Bonzini
234 e7c033c3 Paolo Bonzini
/* The recursive workhorse (the depth is limited to HBITMAP_LEVELS)... */
235 e7c033c3 Paolo Bonzini
static void hb_set_between(HBitmap *hb, int level, uint64_t start, uint64_t last)
236 e7c033c3 Paolo Bonzini
{
237 e7c033c3 Paolo Bonzini
    size_t pos = start >> BITS_PER_LEVEL;
238 e7c033c3 Paolo Bonzini
    size_t lastpos = last >> BITS_PER_LEVEL;
239 e7c033c3 Paolo Bonzini
    bool changed = false;
240 e7c033c3 Paolo Bonzini
    size_t i;
241 e7c033c3 Paolo Bonzini
242 e7c033c3 Paolo Bonzini
    i = pos;
243 e7c033c3 Paolo Bonzini
    if (i < lastpos) {
244 e7c033c3 Paolo Bonzini
        uint64_t next = (start | (BITS_PER_LONG - 1)) + 1;
245 e7c033c3 Paolo Bonzini
        changed |= hb_set_elem(&hb->levels[level][i], start, next - 1);
246 e7c033c3 Paolo Bonzini
        for (;;) {
247 e7c033c3 Paolo Bonzini
            start = next;
248 e7c033c3 Paolo Bonzini
            next += BITS_PER_LONG;
249 e7c033c3 Paolo Bonzini
            if (++i == lastpos) {
250 e7c033c3 Paolo Bonzini
                break;
251 e7c033c3 Paolo Bonzini
            }
252 e7c033c3 Paolo Bonzini
            changed |= (hb->levels[level][i] == 0);
253 e7c033c3 Paolo Bonzini
            hb->levels[level][i] = ~0UL;
254 e7c033c3 Paolo Bonzini
        }
255 e7c033c3 Paolo Bonzini
    }
256 e7c033c3 Paolo Bonzini
    changed |= hb_set_elem(&hb->levels[level][i], start, last);
257 e7c033c3 Paolo Bonzini
258 e7c033c3 Paolo Bonzini
    /* If there was any change in this layer, we may have to update
259 e7c033c3 Paolo Bonzini
     * the one above.
260 e7c033c3 Paolo Bonzini
     */
261 e7c033c3 Paolo Bonzini
    if (level > 0 && changed) {
262 e7c033c3 Paolo Bonzini
        hb_set_between(hb, level - 1, pos, lastpos);
263 e7c033c3 Paolo Bonzini
    }
264 e7c033c3 Paolo Bonzini
}
265 e7c033c3 Paolo Bonzini
266 e7c033c3 Paolo Bonzini
void hbitmap_set(HBitmap *hb, uint64_t start, uint64_t count)
267 e7c033c3 Paolo Bonzini
{
268 e7c033c3 Paolo Bonzini
    /* Compute range in the last layer.  */
269 e7c033c3 Paolo Bonzini
    uint64_t last = start + count - 1;
270 e7c033c3 Paolo Bonzini
271 e7c033c3 Paolo Bonzini
    trace_hbitmap_set(hb, start, count,
272 e7c033c3 Paolo Bonzini
                      start >> hb->granularity, last >> hb->granularity);
273 e7c033c3 Paolo Bonzini
274 e7c033c3 Paolo Bonzini
    start >>= hb->granularity;
275 e7c033c3 Paolo Bonzini
    last >>= hb->granularity;
276 e7c033c3 Paolo Bonzini
    count = last - start + 1;
277 e7c033c3 Paolo Bonzini
278 e7c033c3 Paolo Bonzini
    hb->count += count - hb_count_between(hb, start, last);
279 e7c033c3 Paolo Bonzini
    hb_set_between(hb, HBITMAP_LEVELS - 1, start, last);
280 e7c033c3 Paolo Bonzini
}
281 e7c033c3 Paolo Bonzini
282 e7c033c3 Paolo Bonzini
/* Resetting works the other way round: propagate up if the new
283 e7c033c3 Paolo Bonzini
 * value is zero.
284 e7c033c3 Paolo Bonzini
 */
285 e7c033c3 Paolo Bonzini
static inline bool hb_reset_elem(unsigned long *elem, uint64_t start, uint64_t last)
286 e7c033c3 Paolo Bonzini
{
287 e7c033c3 Paolo Bonzini
    unsigned long mask;
288 e7c033c3 Paolo Bonzini
    bool blanked;
289 e7c033c3 Paolo Bonzini
290 e7c033c3 Paolo Bonzini
    assert((last >> BITS_PER_LEVEL) == (start >> BITS_PER_LEVEL));
291 e7c033c3 Paolo Bonzini
    assert(start <= last);
292 e7c033c3 Paolo Bonzini
293 e7c033c3 Paolo Bonzini
    mask = 2UL << (last & (BITS_PER_LONG - 1));
294 e7c033c3 Paolo Bonzini
    mask -= 1UL << (start & (BITS_PER_LONG - 1));
295 e7c033c3 Paolo Bonzini
    blanked = *elem != 0 && ((*elem & ~mask) == 0);
296 e7c033c3 Paolo Bonzini
    *elem &= ~mask;
297 e7c033c3 Paolo Bonzini
    return blanked;
298 e7c033c3 Paolo Bonzini
}
299 e7c033c3 Paolo Bonzini
300 e7c033c3 Paolo Bonzini
/* The recursive workhorse (the depth is limited to HBITMAP_LEVELS)... */
301 e7c033c3 Paolo Bonzini
static void hb_reset_between(HBitmap *hb, int level, uint64_t start, uint64_t last)
302 e7c033c3 Paolo Bonzini
{
303 e7c033c3 Paolo Bonzini
    size_t pos = start >> BITS_PER_LEVEL;
304 e7c033c3 Paolo Bonzini
    size_t lastpos = last >> BITS_PER_LEVEL;
305 e7c033c3 Paolo Bonzini
    bool changed = false;
306 e7c033c3 Paolo Bonzini
    size_t i;
307 e7c033c3 Paolo Bonzini
308 e7c033c3 Paolo Bonzini
    i = pos;
309 e7c033c3 Paolo Bonzini
    if (i < lastpos) {
310 e7c033c3 Paolo Bonzini
        uint64_t next = (start | (BITS_PER_LONG - 1)) + 1;
311 e7c033c3 Paolo Bonzini
312 e7c033c3 Paolo Bonzini
        /* Here we need a more complex test than when setting bits.  Even if
313 e7c033c3 Paolo Bonzini
         * something was changed, we must not blank bits in the upper level
314 e7c033c3 Paolo Bonzini
         * unless the lower-level word became entirely zero.  So, remove pos
315 e7c033c3 Paolo Bonzini
         * from the upper-level range if bits remain set.
316 e7c033c3 Paolo Bonzini
         */
317 e7c033c3 Paolo Bonzini
        if (hb_reset_elem(&hb->levels[level][i], start, next - 1)) {
318 e7c033c3 Paolo Bonzini
            changed = true;
319 e7c033c3 Paolo Bonzini
        } else {
320 e7c033c3 Paolo Bonzini
            pos++;
321 e7c033c3 Paolo Bonzini
        }
322 e7c033c3 Paolo Bonzini
323 e7c033c3 Paolo Bonzini
        for (;;) {
324 e7c033c3 Paolo Bonzini
            start = next;
325 e7c033c3 Paolo Bonzini
            next += BITS_PER_LONG;
326 e7c033c3 Paolo Bonzini
            if (++i == lastpos) {
327 e7c033c3 Paolo Bonzini
                break;
328 e7c033c3 Paolo Bonzini
            }
329 e7c033c3 Paolo Bonzini
            changed |= (hb->levels[level][i] != 0);
330 e7c033c3 Paolo Bonzini
            hb->levels[level][i] = 0UL;
331 e7c033c3 Paolo Bonzini
        }
332 e7c033c3 Paolo Bonzini
    }
333 e7c033c3 Paolo Bonzini
334 e7c033c3 Paolo Bonzini
    /* Same as above, this time for lastpos.  */
335 e7c033c3 Paolo Bonzini
    if (hb_reset_elem(&hb->levels[level][i], start, last)) {
336 e7c033c3 Paolo Bonzini
        changed = true;
337 e7c033c3 Paolo Bonzini
    } else {
338 e7c033c3 Paolo Bonzini
        lastpos--;
339 e7c033c3 Paolo Bonzini
    }
340 e7c033c3 Paolo Bonzini
341 e7c033c3 Paolo Bonzini
    if (level > 0 && changed) {
342 e7c033c3 Paolo Bonzini
        hb_reset_between(hb, level - 1, pos, lastpos);
343 e7c033c3 Paolo Bonzini
    }
344 e7c033c3 Paolo Bonzini
}
345 e7c033c3 Paolo Bonzini
346 e7c033c3 Paolo Bonzini
void hbitmap_reset(HBitmap *hb, uint64_t start, uint64_t count)
347 e7c033c3 Paolo Bonzini
{
348 e7c033c3 Paolo Bonzini
    /* Compute range in the last layer.  */
349 e7c033c3 Paolo Bonzini
    uint64_t last = start + count - 1;
350 e7c033c3 Paolo Bonzini
351 e7c033c3 Paolo Bonzini
    trace_hbitmap_reset(hb, start, count,
352 e7c033c3 Paolo Bonzini
                        start >> hb->granularity, last >> hb->granularity);
353 e7c033c3 Paolo Bonzini
354 e7c033c3 Paolo Bonzini
    start >>= hb->granularity;
355 e7c033c3 Paolo Bonzini
    last >>= hb->granularity;
356 e7c033c3 Paolo Bonzini
357 e7c033c3 Paolo Bonzini
    hb->count -= hb_count_between(hb, start, last);
358 e7c033c3 Paolo Bonzini
    hb_reset_between(hb, HBITMAP_LEVELS - 1, start, last);
359 e7c033c3 Paolo Bonzini
}
360 e7c033c3 Paolo Bonzini
361 e7c033c3 Paolo Bonzini
bool hbitmap_get(const HBitmap *hb, uint64_t item)
362 e7c033c3 Paolo Bonzini
{
363 e7c033c3 Paolo Bonzini
    /* Compute position and bit in the last layer.  */
364 e7c033c3 Paolo Bonzini
    uint64_t pos = item >> hb->granularity;
365 e7c033c3 Paolo Bonzini
    unsigned long bit = 1UL << (pos & (BITS_PER_LONG - 1));
366 e7c033c3 Paolo Bonzini
367 e7c033c3 Paolo Bonzini
    return (hb->levels[HBITMAP_LEVELS - 1][pos >> BITS_PER_LEVEL] & bit) != 0;
368 e7c033c3 Paolo Bonzini
}
369 e7c033c3 Paolo Bonzini
370 e7c033c3 Paolo Bonzini
void hbitmap_free(HBitmap *hb)
371 e7c033c3 Paolo Bonzini
{
372 e7c033c3 Paolo Bonzini
    unsigned i;
373 e7c033c3 Paolo Bonzini
    for (i = HBITMAP_LEVELS; i-- > 0; ) {
374 e7c033c3 Paolo Bonzini
        g_free(hb->levels[i]);
375 e7c033c3 Paolo Bonzini
    }
376 e7c033c3 Paolo Bonzini
    g_free(hb);
377 e7c033c3 Paolo Bonzini
}
378 e7c033c3 Paolo Bonzini
379 e7c033c3 Paolo Bonzini
HBitmap *hbitmap_alloc(uint64_t size, int granularity)
380 e7c033c3 Paolo Bonzini
{
381 e7c033c3 Paolo Bonzini
    HBitmap *hb = g_malloc0(sizeof (struct HBitmap));
382 e7c033c3 Paolo Bonzini
    unsigned i;
383 e7c033c3 Paolo Bonzini
384 e7c033c3 Paolo Bonzini
    assert(granularity >= 0 && granularity < 64);
385 e7c033c3 Paolo Bonzini
    size = (size + (1ULL << granularity) - 1) >> granularity;
386 e7c033c3 Paolo Bonzini
    assert(size <= ((uint64_t)1 << HBITMAP_LOG_MAX_SIZE));
387 e7c033c3 Paolo Bonzini
388 e7c033c3 Paolo Bonzini
    hb->size = size;
389 e7c033c3 Paolo Bonzini
    hb->granularity = granularity;
390 e7c033c3 Paolo Bonzini
    for (i = HBITMAP_LEVELS; i-- > 0; ) {
391 e7c033c3 Paolo Bonzini
        size = MAX((size + BITS_PER_LONG - 1) >> BITS_PER_LEVEL, 1);
392 e7c033c3 Paolo Bonzini
        hb->levels[i] = g_malloc0(size * sizeof(unsigned long));
393 e7c033c3 Paolo Bonzini
    }
394 e7c033c3 Paolo Bonzini
395 e7c033c3 Paolo Bonzini
    /* We necessarily have free bits in level 0 due to the definition
396 e7c033c3 Paolo Bonzini
     * of HBITMAP_LEVELS, so use one for a sentinel.  This speeds up
397 e7c033c3 Paolo Bonzini
     * hbitmap_iter_skip_words.
398 e7c033c3 Paolo Bonzini
     */
399 e7c033c3 Paolo Bonzini
    assert(size == 1);
400 e7c033c3 Paolo Bonzini
    hb->levels[0][0] |= 1UL << (BITS_PER_LONG - 1);
401 e7c033c3 Paolo Bonzini
    return hb;
402 e7c033c3 Paolo Bonzini
}