GDT finally works
This commit is contained in:
117
kernel/bitmap/bitmap.c
Normal file
117
kernel/bitmap/bitmap.c
Normal file
@ -0,0 +1,117 @@
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include "bitmap.h"
|
||||
|
||||
#define DIV_ROUNDUP(num, div) ((num + div - 1) / div)
|
||||
|
||||
void *bitmap_toptr(BitMap *bm, size_t block) {
|
||||
uint8_t *ptr = (uint8_t *)(bm->mem_start + (block * BITMAP_BLOCK_SIZE));
|
||||
return (void *)ptr;
|
||||
}
|
||||
|
||||
size_t bitmap_toblock(BitMap *bm, void *ptr) {
|
||||
uint8_t *p = ptr;
|
||||
return (size_t)(p - bm->mem_start) / BITMAP_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
size_t bitmap_toblock_roundup(BitMap *bm, void *ptr) {
|
||||
uint8_t *p = ptr;
|
||||
return (size_t)DIV_ROUNDUP((size_t)(p - bm->mem_start), BITMAP_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
size_t bitmap_calcsize(size_t total) {
|
||||
size_t nblocks = DIV_ROUNDUP(total, BITMAP_BLOCK_SIZE);
|
||||
size_t nbytes = DIV_ROUNDUP(nblocks, 8);
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
bool bitmap_get(BitMap *bm, size_t block) {
|
||||
size_t elem = block / BITMAP_BLOCKS_PER_BYTE;
|
||||
size_t off = block % BITMAP_BLOCKS_PER_BYTE;
|
||||
return (bm->map[elem] & (1 << off)) != 0;
|
||||
}
|
||||
|
||||
void bitmap_set(BitMap *bm, size_t block, bool value) {
|
||||
size_t elem = block / BITMAP_BLOCKS_PER_BYTE;
|
||||
size_t off = block % BITMAP_BLOCKS_PER_BYTE;
|
||||
if (value) {
|
||||
bm->map[elem] |= (1 << off);
|
||||
} else {
|
||||
bm->map[elem] &= ~(1 << off);
|
||||
}
|
||||
}
|
||||
|
||||
void bitmap_markblocks(BitMap *bm, size_t start, size_t size, bool value) {
|
||||
if (!value && start < bm->last_deep_frag) {
|
||||
bm->last_deep_frag = start;
|
||||
}
|
||||
|
||||
for (size_t i = start; i < start + size; i++) {
|
||||
bitmap_set(bm, i, value);
|
||||
}
|
||||
|
||||
bm->alloc_blocks += value ? size : -size;
|
||||
}
|
||||
|
||||
void bitmap_markregion(BitMap *bm, void *baseptr, size_t size, bool is_used) {
|
||||
size_t base, size1;
|
||||
|
||||
if (is_used) {
|
||||
base = bitmap_toblock(bm, baseptr);
|
||||
size1 = DIV_ROUNDUP(size, BITMAP_BLOCK_SIZE);
|
||||
} else {
|
||||
base = bitmap_toblock(bm, baseptr);
|
||||
size1 = size / BITMAP_BLOCK_SIZE;
|
||||
}
|
||||
bitmap_markblocks(bm, base, size1, is_used);
|
||||
}
|
||||
|
||||
size_t bitmap_freeregion(BitMap *bm, size_t blocks) {
|
||||
size_t curregstart = bm->last_deep_frag;
|
||||
size_t curregsize = 0;
|
||||
for (size_t i = curregstart; i < bm->nblocks; i++) {
|
||||
if (bitmap_get(bm, i)) {
|
||||
curregsize = 0;
|
||||
curregstart = i + 1;
|
||||
} else {
|
||||
if (blocks == 1) {
|
||||
bm->last_deep_frag = curregstart + 1;
|
||||
}
|
||||
|
||||
curregsize++;
|
||||
if (curregsize >= blocks) {
|
||||
return curregstart;
|
||||
}
|
||||
}
|
||||
}
|
||||
return BITMAP_INVALID_BLOCK;
|
||||
}
|
||||
|
||||
void *bitmap_alloc(BitMap *bm, size_t blocks) {
|
||||
if (!blocks) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t pickedreg = bitmap_freeregion(bm, blocks);
|
||||
if (pickedreg == BITMAP_INVALID_BLOCK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bitmap_markblocks(bm, pickedreg, blocks, 1);
|
||||
return bitmap_toptr(bm, pickedreg);
|
||||
}
|
||||
|
||||
void bitmap_free(BitMap *bm, void *base, size_t blocks) {
|
||||
bitmap_markregion(bm, base, BITMAP_BLOCK_SIZE * blocks, 0);
|
||||
}
|
||||
|
||||
size_t bitmap_allocpageframe(BitMap *bm) {
|
||||
size_t pickedreg = bitmap_freeregion(bm, 1);
|
||||
bitmap_markblocks(bm, pickedreg, 1, 1);
|
||||
return (bm->mem_start + (pickedreg * BITMAP_BLOCK_SIZE));
|
||||
}
|
||||
|
||||
void bitmap_freepageframe(BitMap *bm, void *addr) {
|
||||
bitmap_markregion(bm, addr, BITMAP_BLOCK_SIZE * 1, 0);
|
||||
}
|
Reference in New Issue
Block a user