#include #include #include void bm_init(struct bm *bm, uint8_t *base, size_t nbits) { bm->base = base; bm->nbits = nbits; memset(bm->base, 0, (nbits + 7) / 8); } /* * Set a bit in a bitmap. */ void bm_set(struct bm *bm, size_t k) { if (k >= bm->nbits) return; uint8_t *b = (uint8_t *)((uintptr_t)bm->base + (k / 8)); *b = ((*b) | (1 << (k % 8))); } /* * Clear a bit in a bitmap. */ void bm_clear(struct bm *bm, size_t k) { if (k >= bm->nbits) return; uint8_t *b = (uint8_t *)((uintptr_t)bm->base + (k / 8)); *b = ((*b) & ~(1 << (k % 8))); } /* * Test (true/false) a bit in a bitmap. */ bool bm_test(struct bm *bm, size_t k) { if (k >= bm->nbits) return false; uint8_t *b = (uint8_t *)((uintptr_t)bm->base + (k / 8)); return (*b) & (1 << (k % 8)); } /* * Set a range of bits in a bitmap. if starting bit is out of range, we fail. */ bool bm_set_region(struct bm *bm, size_t k, size_t m) { if ((k >= m) || (k >= bm->nbits) || (k + m >= bm->nbits)) return false; for (size_t i = k; i < m; i++) { bool taken = bm_test(bm, i); if (taken) return false; } for (size_t i = k; i < m; i++) bm_set(bm, i); return true; } /* * Clear a range of bits in a bitmap. starting bit must be in range. */ void bm_clear_region(struct bm *bm, size_t k, size_t m) { if ((k >= m) || (k >= bm->nbits) || (k + m >= bm->nbits)) return; for (size_t i = k; i < m; i++) bm_clear(bm, i); } /* * Test a range if bits in a bitmap. Return true if at least one bit * is set, else return false (all bits clear). For convenience, if k or m * are out of range, act as if the bits are set / bitmap is full - this is * useful for implementing the physical memory manager algorithm. */ bool bm_test_region(struct bm *bm, size_t k, size_t m) { if ((k >= m) || (k >= bm->nbits) || (k + m >= bm->nbits)) return true; for (size_t i = k; i < m; i++) { bool test = bm_test(bm, i); if (test) return true; } return false; }