os_kernel_lab/labcodes/lab8/kern/fs/sfs/bitmap.c

115 lines
3.1 KiB
C
Raw Normal View History

2012-08-22 12:32:13 +08:00
#include <defs.h>
#include <string.h>
#include <bitmap.h>
#include <kmalloc.h>
#include <error.h>
#include <assert.h>
#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;
}