void bm_clear(struct bitmap* const bm, const Addr a1, const Addr a2) { Addr b, b_next; tl_assert(bm); tl_assert(a1); tl_assert(a1 <= a2); for (b = a1; b < a2; b = b_next) { struct bitmap2* const p2 = bm2_lookup_exclusive(bm, b >> ADDR0_BITS); b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT; if (b_next > a2) { b_next = a2; } if (p2) { Addr c = b; /* If the first address in the bitmap that must be cleared does not */ /* start on an UWord boundary, start clearing the first addresses. */ if (UWORD_LSB(c)) { Addr c_next = UWORD_MSB(c) + BITS_PER_UWORD; if (c_next > b_next) c_next = b_next; bm0_clear_range(p2->bm1.bm0_r, c & ADDR0_MASK, c_next - c); bm0_clear_range(p2->bm1.bm0_w, c & ADDR0_MASK, c_next - c); c = c_next; } /* If some UWords have to be cleared entirely, do this now. */ if (UWORD_LSB(c) == 0) { const Addr c_next = UWORD_MSB(b_next); tl_assert(UWORD_LSB(c) == 0); tl_assert(UWORD_LSB(c_next) == 0); tl_assert(c_next <= b_next); tl_assert(c <= c_next); if (c_next > c) { UWord idx = (c & ADDR0_MASK) >> BITS_PER_BITS_PER_UWORD; VG_(memset)(&p2->bm1.bm0_r[idx], 0, (c_next - c) / 8); VG_(memset)(&p2->bm1.bm0_w[idx], 0, (c_next - c) / 8); c = c_next; } } /* If the last address in the bitmap that must be cleared does not */ /* fall on an UWord boundary, clear the last addresses. */ /* tl_assert(c <= b_next); */ bm0_clear_range(p2->bm1.bm0_r, c & ADDR0_MASK, b_next - c); bm0_clear_range(p2->bm1.bm0_w, c & ADDR0_MASK, b_next - c); } }
// New and fast implementation. void bm_clear(const struct bitmap* const bm, const Addr a1, const Addr a2) { Addr b, b_next; tl_assert(bm); tl_assert(a1); tl_assert(a1 <= a2); for (b = a1; b < a2; b = b_next) { struct bitmap2* const p2 = bm_lookup(bm, b); b_next = (b & ~ADDR0_MASK) + ADDR0_COUNT; if (b_next > a2) { b_next = a2; } if (p2) { Addr c = b; if (UWORD_LSB(c)) { Addr c_next = UWORD_MSB(c) + BITS_PER_UWORD; if (c_next > b_next) c_next = b_next; bm1_clear(&p2->bm1, c, c_next); c = c_next; } if (UWORD_LSB(c) == 0) { const Addr c_next = UWORD_MSB(b_next); tl_assert(UWORD_LSB(c) == 0); tl_assert(UWORD_LSB(c_next) == 0); tl_assert(c_next <= b_next); tl_assert(c <= c_next); if (c_next > c) { UWord idx = (c & ADDR0_MASK) >> BITS_PER_BITS_PER_UWORD; VG_(memset)(&p2->bm1.bm0_r[idx], 0, (c_next - c) / 8); VG_(memset)(&p2->bm1.bm0_w[idx], 0, (c_next - c) / 8); c = c_next; } } if (c != b_next) { bm1_clear(&p2->bm1, c, b_next); } } }
static __inline__ void bm1_clear(struct bitmap1* const bm1, const Addr a1, const Addr a2) { UWord idx; UWord mask; #if 0 // Commented out the assert statements below because of performance reasons. tl_assert(a1); tl_assert(a1 <= a2); tl_assert(UWORD_MSB(a1) == UWORD_MSB(a2) || UWORD_MSB(a1) == UWORD_MSB(a2 - 1)); #endif idx = (a1 & ADDR0_MASK) >> BITS_PER_BITS_PER_UWORD; /* mask: a contiguous series of one bits. The first bit set is bit */ /* UWORD_LSB(a2-1), and the last bit set is UWORD_LSB(a1). */ mask = UWORD_LSB(a2) ? bm0_mask(a2) - bm0_mask(a1) : - bm0_mask(a1); bm1->bm0_r[idx] &= ~mask; bm1->bm0_w[idx] &= ~mask; }