diff --git a/core/allocArea.c b/core/allocArea.c new file mode 100644 index 0000000..7713091 --- /dev/null +++ b/core/allocArea.c @@ -0,0 +1,146 @@ +#include "allocArea.h" +#include "alloc.h" +#include "assert.h" +#include "kernel.h" +#include "list.h" +#include "mem.h" +#include "stdarg.h" + +struct memArea { + vaddr_t startAddr; + uint nbPages; + struct memArea *next; + struct memArea *prev; +}; + +static struct memArea *freeArea; +static struct memArea *usedArea; + +void areaInit(void) +{ + list_init(freeArea); + list_init(usedArea); +} + +struct memArea *areaFindFit(unsigned int nbPages) +{ + struct memArea *area; + int count; + + list_foreach(freeArea, area, count) + { + if (area->nbPages >= nbPages) + return area; + } + return NULL; +} + +static void insertSorted(struct memArea *list, struct memArea *item) +{ + struct memArea *prev, *cur; + int count; + prev = NULL; + + list_foreach(list, cur, count) + { + if (cur->startAddr > item->startAddr) + break; + prev = cur; + } + if (prev) + list_insert_after(list, prev, item); + else + list_add_tail(list, item); +} + +vaddr_t areaAlloc(unsigned int nbPages) +{ + struct memArea *area, *allocated; + + area = areaFindFit(nbPages); + if (!area) + return (vaddr_t)NULL; + + if (area->nbPages == nbPages) { + list_delete(freeArea, area); + insertSorted(usedArea, area); + allocated = area; + } + + struct memArea *newArea = (struct memArea *)malloc(sizeof(struct memArea)); + if (!newArea) + return (vaddr_t)NULL; + + // Avoid insertSorted(freeArea, newArea) call by modifying area + + newArea->nbPages = nbPages; + newArea->startAddr = area->startAddr; + + area->nbPages -= nbPages; + area->startAddr += nbPages * PAGE_SIZE; + + insertSorted(usedArea, newArea); + + allocated = newArea; + + for (uint i = 0; i < nbPages; i++) { + paddr_t page = allocPhyPage(1); + if (page) { + pageMap(area->startAddr + i * PAGE_SIZE, page, PAGING_MEM_WRITE); + } else { + // TODO + assert(1); + } + } + + return allocated->startAddr; +} + +static int areaMergeFreeArea(struct memArea *prev, struct memArea *next) +{ + if (prev->startAddr + prev->nbPages * PAGE_SIZE != next->startAddr) { + return -1; + } + + prev->nbPages += next->nbPages; + list_delete(freeArea, next); + free(next); + + next = prev; + + return 0; +} + +static struct memArea *areaFindMemArea(struct memArea *list, vaddr_t addr) +{ + struct memArea *area; + int count; + list_foreach(list, area, count) + { + if (area->startAddr <= addr && addr <= area->startAddr + area->nbPages * PAGE_SIZE) + return area; + } + + return NULL; +} + +int areaFree(vaddr_t addr) +{ + struct memArea *area; + + area = areaFindMemArea(usedArea, addr); + if (!area) { + pr_info("Cannot find memArea associated to %p\n", addr); + return -1; + } + list_delete(usedArea, area); + insertSorted(freeArea, area); + + if (area->prev) + areaMergeFreeArea(area->prev, area); + + if (area->next) + areaMergeFreeArea(area, area->next); + + return 0; +} diff --git a/core/allocArea.h b/core/allocArea.h new file mode 100644 index 0000000..c292442 --- /dev/null +++ b/core/allocArea.h @@ -0,0 +1,4 @@ +#pragma once +#include "paging.h" + +void areaInit(void);