#include #include #include #include #include #include #define WORD_TYPE uint32_t #define WORD_BITS (sizeof(WORD_TYPE) * CHAR_BIT) struct bitmap { uint32_t nbits; uint32_t nwords; WORD_TYPE *map; }; // bitmap_create - allocate a new bitmap object. struct bitmap * bitmap_create(uint32_t nbits) { static_assert(WORD_BITS != 0); assert(nbits != 0 && nbits + WORD_BITS > nbits); struct bitmap *bitmap; if ((bitmap = kmalloc(sizeof(struct bitmap))) == NULL) { return NULL; } uint32_t nwords = ROUNDUP_DIV(nbits, WORD_BITS); WORD_TYPE *map; if ((map = kmalloc(sizeof(WORD_TYPE) * nwords)) == NULL) { kfree(bitmap); return NULL; } bitmap->nbits = nbits, bitmap->nwords = nwords; bitmap->map = memset(map, 0xFF, sizeof(WORD_TYPE) * nwords); /* mark any leftover bits at the end in use(0) */ if (nbits != nwords * WORD_BITS) { uint32_t ix = nwords - 1, overbits = nbits - ix * WORD_BITS; assert(nbits / WORD_BITS == ix); assert(overbits > 0 && overbits < WORD_BITS); for (; overbits < WORD_BITS; overbits ++) { bitmap->map[ix] ^= (1 << overbits); } } return bitmap; } // bitmap_alloc - locate a cleared bit, set it, and return its index. int bitmap_alloc(struct bitmap *bitmap, uint32_t *index_store) { WORD_TYPE *map = bitmap->map; uint32_t ix, offset, nwords = bitmap->nwords; for (ix = 0; ix < nwords; ix ++) { if (map[ix] != 0) { for (offset = 0; offset < WORD_BITS; offset ++) { WORD_TYPE mask = (1 << offset); if (map[ix] & mask) { map[ix] ^= mask; *index_store = ix * WORD_BITS + offset; return 0; } } assert(0); } } return -E_NO_MEM; } // bitmap_translate - according index, get the related word and mask static void bitmap_translate(struct bitmap *bitmap, uint32_t index, WORD_TYPE **word, WORD_TYPE *mask) { assert(index < bitmap->nbits); uint32_t ix = index / WORD_BITS, offset = index % WORD_BITS; *word = bitmap->map + ix; *mask = (1 << offset); } // bitmap_test - according index, get the related value (0 OR 1) in the bitmap bool bitmap_test(struct bitmap *bitmap, uint32_t index) { WORD_TYPE *word, mask; bitmap_translate(bitmap, index, &word, &mask); return (*word & mask); } // bitmap_free - according index, set related bit to 1 void bitmap_free(struct bitmap *bitmap, uint32_t index) { WORD_TYPE *word, mask; bitmap_translate(bitmap, index, &word, &mask); assert(!(*word & mask)); *word |= mask; } // bitmap_destroy - free memory contains bitmap void bitmap_destroy(struct bitmap *bitmap) { kfree(bitmap->map); kfree(bitmap); } // bitmap_getdata - return bitmap->map, return the length of bits to len_store void * bitmap_getdata(struct bitmap *bitmap, size_t *len_store) { if (len_store != NULL) { *len_store = sizeof(WORD_TYPE) * bitmap->nwords; } return bitmap->map; }