matos/core/allocArea.c

188 lines
4.2 KiB
C
Raw Normal View History

2021-02-10 23:22:57 +01:00
#include "allocArea.h"
#include "alloc.h"
#include "assert.h"
#include "kernel.h"
#include "list.h"
#include "mem.h"
#include "stdarg.h"
static struct memArea *freeArea;
static struct memArea *usedArea;
2021-08-09 09:26:10 +02:00
static int areaMergeFreeArea(struct memArea *prev, struct memArea *next);
2021-08-19 16:44:47 +02:00
void areaInit(vaddr_t firstMemUsed, vaddr_t lastUsed)
2021-02-10 23:22:57 +01:00
{
list_init(freeArea);
list_init(usedArea);
2021-08-09 09:26:10 +02:00
vaddr_t areaAddr, descAddr, entryAddr;
allocSetup(sizeof(struct memArea), &areaAddr, &descAddr, &entryAddr);
areaAdd(descAddr, PAGE_SIZE, FALSE);
if (entryAddr != descAddr)
areaAdd(entryAddr, PAGE_SIZE, FALSE);
if (areaAddr != descAddr && areaAddr != entryAddr)
areaAdd(areaAddr, PAGE_SIZE, FALSE);
2021-08-19 16:44:47 +02:00
int nbPages = DIV_ROUND_UP((lastUsed - firstMemUsed), PAGE_SIZE);
areaAdd(ALIGN_DOWN(firstMemUsed, PAGE_SIZE), nbPages, FALSE);
areaAdd(ALIGN_DOWN(areaAddr + PAGE_SIZE, PAGE_SIZE), 300 , TRUE);
2021-08-09 09:26:10 +02:00
allocPopulate();
2021-02-10 23:22:57 +01:00
}
struct memArea *areaFindFit(unsigned int nbPages)
{
struct memArea *area;
int count;
list_foreach(freeArea, area, count)
{
if (area->nbPages >= nbPages)
return area;
}
return NULL;
}
2021-08-19 16:44:47 +02:00
static void insertSorted(struct memArea **list, struct memArea *item)
2021-02-10 23:22:57 +01:00
{
struct memArea *prev, *cur;
int count;
prev = NULL;
2021-08-19 16:44:47 +02:00
list_foreach(*list, cur, count)
2021-02-10 23:22:57 +01:00
{
if (cur->startAddr > item->startAddr)
break;
prev = cur;
}
if (prev)
2021-08-19 16:44:47 +02:00
list_insert_after(*list, prev, item);
2021-02-10 23:22:57 +01:00
else
2021-08-19 16:44:47 +02:00
list_add_tail(*list, item);
2021-02-10 23:22:57 +01:00
}
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);
2021-08-19 16:44:47 +02:00
insertSorted(&usedArea, area);
2021-02-10 23:22:57 +01:00
allocated = area;
}
struct memArea *newArea = (struct memArea *)malloc(sizeof(struct memArea));
2021-08-19 16:44:47 +02:00
if (!newArea){
pr_devel("Failed to allocated area of %d pages\n", nbPages);
2021-02-10 23:22:57 +01:00
return (vaddr_t)NULL;
2021-08-19 16:44:47 +02:00
}
2021-02-10 23:22:57 +01:00
// Avoid insertSorted(freeArea, newArea) call by modifying area
newArea->nbPages = nbPages;
newArea->startAddr = area->startAddr;
area->nbPages -= nbPages;
area->startAddr += nbPages * PAGE_SIZE;
2021-08-19 16:44:47 +02:00
insertSorted(&usedArea, newArea);
2021-02-10 23:22:57 +01:00
allocated = newArea;
for (uint i = 0; i < nbPages; i++) {
paddr_t page = allocPhyPage(1);
if (page) {
2021-08-19 16:44:47 +02:00
pageMap(newArea->startAddr + i * PAGE_SIZE, page, PAGING_MEM_WRITE);
2021-02-10 23:22:57 +01:00
} else {
// TODO
assert(1);
}
}
return allocated->startAddr;
}
2021-08-09 09:26:10 +02:00
int areaAdd(vaddr_t addr, uint nbPages, int isFree)
{
2021-08-19 16:44:47 +02:00
struct memArea **area;
2021-08-09 09:26:10 +02:00
struct memArea *newArea = (struct memArea *)malloc(sizeof(struct memArea));
if (!newArea)
return (vaddr_t)NULL;
newArea->nbPages = nbPages;
newArea->startAddr = addr;
if (isFree) {
2021-08-19 16:44:47 +02:00
area = &freeArea;
2021-08-09 09:26:10 +02:00
} else {
2021-08-19 16:44:47 +02:00
area = &usedArea;
2021-08-09 09:26:10 +02:00
}
insertSorted(area, newArea);
if (isFree) {
if (newArea->prev)
2021-08-19 16:44:47 +02:00
areaMergeFreeArea(newArea->prev, *area);
2021-08-09 09:26:10 +02:00
if (newArea->next)
2021-08-19 16:44:47 +02:00
areaMergeFreeArea(*area, newArea->next);
2021-08-09 09:26:10 +02:00
}
return 0;
}
2021-02-10 23:22:57 +01:00
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);
2021-08-19 16:44:47 +02:00
insertSorted(&freeArea, area);
2021-02-10 23:22:57 +01:00
if (area->prev)
areaMergeFreeArea(area->prev, area);
if (area->next)
areaMergeFreeArea(area, area->next);
return 0;
}