malloc: fix recursivity with areaAlloc

This commit is contained in:
Mathieu Maret 2021-10-28 23:18:05 +02:00
parent 186192023d
commit d702c7b60e
5 changed files with 127 additions and 39 deletions

View File

@ -17,7 +17,7 @@ static struct slabDesc *slub;
static int allocInitialized = FALSE; static int allocInitialized = FALSE;
static int allocSlab(struct slabDesc **desc, size_t sizeEl, size_t sizeSlab, static int allocSlab(struct slabDesc **desc, size_t sizeEl, size_t sizeSlab,
int self_containing); int self_containing, int neverEmpty);
static int allocSlabEntry(struct slabEntry **desc, size_t sizeEl, size_t sizeSlab, static int allocSlabEntry(struct slabEntry **desc, size_t sizeEl, size_t sizeSlab,
int selfContained); int selfContained);
static int formatPage(struct slabEntry *desc, size_t size, size_t sizeSlab, int selfContained); static int formatPage(struct slabEntry *desc, size_t size, size_t sizeSlab, int selfContained);
@ -28,27 +28,29 @@ static struct {
size_t elementSize; size_t elementSize;
size_t slabSize; size_t slabSize;
unsigned char isSelf; unsigned char isSelf;
} initSlab[] = {{4, PAGE_SIZE, 0}, unsigned char neverEmpty;
{8, PAGE_SIZE, 0}, } initSlab[] = {{4, PAGE_SIZE, 0, 0},
{16, PAGE_SIZE, 0}, {8, PAGE_SIZE, 0, 0},
{32, PAGE_SIZE, 0}, {16, PAGE_SIZE, 0, 0},
{64, PAGE_SIZE, 0}, {32, PAGE_SIZE, 0, 0},
{128, PAGE_SIZE, 0}, {64, PAGE_SIZE, 0, 0},
{256, 2 * PAGE_SIZE, 0}, {128, PAGE_SIZE, 0, 0},
{1024, 2 * PAGE_SIZE, 0}, {256, 2 * PAGE_SIZE, 0, 0},
{2048, 3 * PAGE_SIZE, 0}, {1024, 2 * PAGE_SIZE, 0, 0},
{4096, 4 * PAGE_SIZE, 0}, {2048, 3 * PAGE_SIZE, 0, 0},
{0, 0, 0}}; {4096, 4 * PAGE_SIZE, 0, 0},
{0, 0, 0, 0}};
int allocSetup(size_t sizeOfArea, vaddr_t *areaAddr, vaddr_t *descAddr, vaddr_t *entryAddr) int allocSetup(size_t sizeOfArea, vaddr_t *areaAddr, vaddr_t *descAddr, vaddr_t *entryAddr)
{ {
list_init(slub); list_init(slub);
assert(allocBookSlab(sizeof(struct slabDesc), PAGE_SIZE, TRUE) == 0); assert(allocBookSlab(sizeof(struct slabDesc), PAGE_SIZE, TRUE, FALSE) == 0);
*descAddr = (vaddr_t)allocGetSlab(sizeof(struct slabDesc)); *descAddr = (vaddr_t)allocGetSlab(sizeof(struct slabDesc));
assert(allocBookSlab(sizeof(struct slabEntry), PAGE_SIZE, TRUE) == 0); assert(allocBookSlab(sizeof(struct slabEntry), PAGE_SIZE, TRUE, FALSE) == 0);
*entryAddr = (vaddr_t)allocGetSlab(sizeof(struct slabEntry)); *entryAddr = (vaddr_t)allocGetSlab(sizeof(struct slabEntry));
assert(allocBookSlab(sizeOfArea, PAGE_SIZE, TRUE) == 0); printf("allocSetup for sizeOfArea %d\n", sizeOfArea);
assert(allocBookSlab(sizeOfArea, PAGE_SIZE, TRUE, TRUE) == 0);
*areaAddr = (vaddr_t)allocGetSlab(sizeOfArea); *areaAddr = (vaddr_t)allocGetSlab(sizeOfArea);
allocInitialized = TRUE; allocInitialized = TRUE;
@ -61,7 +63,7 @@ int allocPopulate()
int ret; int ret;
if ((ret = allocBookSlab(initSlab[i].elementSize, initSlab[i].slabSize, if ((ret = allocBookSlab(initSlab[i].elementSize, initSlab[i].slabSize,
initSlab[i].isSelf))) { initSlab[i].isSelf, initSlab[i].neverEmpty))) {
if (ret == -EEXIST) if (ret == -EEXIST)
continue; continue;
pr_err("Fail to allocBookSlab %d for %d \n", ret, (1U << i)); pr_err("Fail to allocBookSlab %d for %d \n", ret, (1U << i));
@ -73,7 +75,7 @@ int allocPopulate()
return 0; return 0;
} }
int allocBookSlab(size_t sizeEl, size_t sizeSlab, int selfContained) int allocBookSlab(size_t sizeEl, size_t sizeSlab, int selfContained, int neverEmpty)
{ {
struct slabDesc *slab = NULL; struct slabDesc *slab = NULL;
struct slabDesc *newSlab = NULL; struct slabDesc *newSlab = NULL;
@ -95,7 +97,7 @@ int allocBookSlab(size_t sizeEl, size_t sizeSlab, int selfContained)
} }
} }
if ((ret = allocSlab(&newSlab, sizeEl, sizeSlab, selfContained))) { if ((ret = allocSlab(&newSlab, sizeEl, sizeSlab, selfContained, neverEmpty))) {
pr_devel("Failed to alloc Slab\n"); pr_devel("Failed to alloc Slab\n");
restore_IRQs(flags); restore_IRQs(flags);
return ret; return ret;
@ -112,7 +114,8 @@ int allocBookSlab(size_t sizeEl, size_t sizeSlab, int selfContained)
return 0; return 0;
} }
static int allocSlab(struct slabDesc **desc, size_t size, size_t sizeSlab, int selfContained) static int allocSlab(struct slabDesc **desc, size_t size, size_t sizeSlab, int selfContained,
int neverEmpty)
{ {
uint nbPage, i; uint nbPage, i;
vaddr_t alloc; vaddr_t alloc;
@ -156,6 +159,7 @@ static int allocSlab(struct slabDesc **desc, size_t size, size_t sizeSlab, int s
slab->page = (vaddr_t)alloc; slab->page = (vaddr_t)alloc;
slab->full = 0; slab->full = 0;
slab->size = sizeSlab; slab->size = sizeSlab;
(*desc)->neverEmpty = neverEmpty;
(*desc)->size = size; (*desc)->size = size;
return formatPage(&(*desc)->slab, size, sizeSlab, selfContained); return formatPage(&(*desc)->slab, size, sizeSlab, selfContained);
@ -202,8 +206,6 @@ static int allocSlabEntry(struct slabEntry **desc, size_t size, size_t sizeSlab,
(*desc)->size = sizeSlab; (*desc)->size = sizeSlab;
return formatPage((*desc), size, sizeSlab, selfContained); return formatPage((*desc), size, sizeSlab, selfContained);
return -ENOMEM;
} }
static int formatPage(struct slabEntry *desc, size_t size, size_t sizeSlab, int selfContained) static int formatPage(struct slabEntry *desc, size_t size, size_t sizeSlab, int selfContained)
@ -271,12 +273,36 @@ void *malloc(size_t size)
return NULL; return NULL;
} }
struct slabEntry *slabList = &slab->slab;
list_foreach(&slab->slab, slabEntry, slabIdx) list_foreach(&slab->slab, slabEntry, slabIdx)
{ {
if (!slabEntry->full) { if (!slabEntry->full) {
// pr_devel("found place in slub %d at idx %d for size %d\n", slubIdx, // pr_devel("found place in slab idx %d for size %d\n", slabIdx, slab->size);
// slabIdx, size);
ret = allocFromSlab(slabEntry); ret = allocFromSlab(slabEntry);
if (slabEntry->full && slab->neverEmpty) {
pr_devel("Prealloc place for slab for object size %d\n", slab->size);
assert(IS_SELF_CONTAINED(slabEntry));
size_t slabSize = slabEntry->size;
int nbPages = DIV_ROUND_UP(slabSize, PAGE_SIZE);
struct slabEntry *entry = (struct slabEntry *)areaBook(nbPages, AREA_PHY_MAP);
if (entry == NULL) {
restore_IRQs(flags);
return NULL;
}
(entry)->freeEl = (char *)(entry) + sizeof(struct slabEntry);
list_singleton(entry, entry);
entry->page = (vaddr_t)entry;
entry->full = 0;
entry->size = slabSize;
formatPage(entry, slab->size, slabSize, 1);
list_add_tail(slabList, entry);
areaAdd((vaddr_t)entry, (vaddr_t)entry + nbPages * PAGE_SIZE, FALSE);
}
restore_IRQs(flags); restore_IRQs(flags);
return ret; return ret;
} }
@ -284,7 +310,6 @@ void *malloc(size_t size)
// No room found // No room found
struct slabEntry *newSlabEntry; struct slabEntry *newSlabEntry;
struct slabEntry *slabList = &slab->slab;
size_t slabSize = MAX(PAGE_SIZE, size); size_t slabSize = MAX(PAGE_SIZE, size);
int retSlab; int retSlab;
@ -304,7 +329,8 @@ void *malloc(size_t size)
return ret; return ret;
} }
void *zalloc(size_t size){ void *zalloc(size_t size)
{
void *alloc = malloc(size); void *alloc = malloc(size);
if (alloc != NULL) if (alloc != NULL)
@ -333,7 +359,8 @@ static int freeFromSlab(void *ptr, struct slabEntry *slab)
return 0; return 0;
} }
int freeSlabAllocated(void *ptr){ int freeSlabAllocated(void *ptr)
{
struct slabDesc *slab; struct slabDesc *slab;
int slabIdx; int slabIdx;
int flags; int flags;

View File

@ -12,7 +12,7 @@ int allocPopulate();
* Allow malloc to allocate elements of this precise size. * Allow malloc to allocate elements of this precise size.
* Otherwise the allocation will be in the closest biggest pool. * Otherwise the allocation will be in the closest biggest pool.
* */ * */
int allocBookSlab(size_t size, size_t sizeSlab, int selfContained); int allocBookSlab(size_t size, size_t sizeSlab, int selfContained, int neverEmpty);
void *malloc(size_t size); void *malloc(size_t size);
void *zalloc(size_t size); void *zalloc(size_t size);
@ -22,9 +22,9 @@ void free(void *ptr);
*/ */
struct slabEntry { struct slabEntry {
vaddr_t page; vaddr_t page;
size_t size;
void *freeEl; void *freeEl;
char full; size_t size;
bool_t full;//TODO replace by freeEl == NULL
struct slabEntry *next; struct slabEntry *next;
struct slabEntry *prev; struct slabEntry *prev;
}; };
@ -32,6 +32,7 @@ struct slabEntry {
struct slabDesc { struct slabDesc {
struct slabEntry slab; struct slabEntry slab;
size_t size; size_t size;
bool_t neverEmpty;
struct slabDesc *next; struct slabDesc *next;
struct slabDesc *prev; struct slabDesc *prev;
}; };

View File

@ -2,6 +2,7 @@
#include "alloc.h" #include "alloc.h"
#include "assert.h" #include "assert.h"
#include "kernel.h" #include "kernel.h"
#include "irq.h"
#include "list.h" #include "list.h"
#include "mem.h" #include "mem.h"
#include "stdarg.h" #include "stdarg.h"
@ -71,13 +72,64 @@ static void insertSorted(struct memArea **list, struct memArea *item)
list_add_tail(*list, item); list_add_tail(*list, item);
} }
vaddr_t areaBook(unsigned int nbPages, uint32_t flags){
struct memArea *area;
vaddr_t allocated;
uint32_t irqFlags;
disable_IRQs(irqFlags);
area = areaFindFit(nbPages);
if (!area){
printf("NULL<\n");
restore_IRQs(irqFlags);
return (vaddr_t)NULL;
}
if (area->nbPages == nbPages) {
list_delete(freeArea, area);
allocated = area->startAddr;
} else {
allocated = area->startAddr;
area->nbPages -= nbPages;
area->startAddr += nbPages * PAGE_SIZE;
}
if (flags & AREA_PHY_MAP) {
for (uint i = 0; i < nbPages; i++) {
paddr_t page = allocPhyPage(1);
if (page) {
pageMap(allocated + i * PAGE_SIZE, page, PAGING_MEM_WRITE);
} else {
printf("Ooops\n");
// TODO
assert(0);
}
}
}
restore_IRQs(irqFlags);
return allocated;
}
vaddr_t areaAlloc(unsigned int nbPages, uint32_t flags) vaddr_t areaAlloc(unsigned int nbPages, uint32_t flags)
{ {
struct memArea *area, *allocated; struct memArea *area, *allocated;
uint32_t irqFlags;
disable_IRQs(irqFlags);
area = areaFindFit(nbPages); area = areaFindFit(nbPages);
if (!area) if (!area){
restore_IRQs(irqFlags);
return (vaddr_t)NULL; return (vaddr_t)NULL;
}
if (area->nbPages == nbPages) { if (area->nbPages == nbPages) {
list_delete(freeArea, area); list_delete(freeArea, area);
@ -87,6 +139,7 @@ vaddr_t areaAlloc(unsigned int nbPages, uint32_t flags)
struct memArea *newArea = (struct memArea *)malloc(sizeof(struct memArea)); struct memArea *newArea = (struct memArea *)malloc(sizeof(struct memArea));
if (!newArea) { if (!newArea) {
pr_devel("Failed to allocated area of %d pages\n", nbPages); pr_devel("Failed to allocated area of %d pages\n", nbPages);
restore_IRQs(irqFlags);
return (vaddr_t)NULL; return (vaddr_t)NULL;
} }
@ -109,12 +162,14 @@ vaddr_t areaAlloc(unsigned int nbPages, uint32_t flags)
if (page) { if (page) {
pageMap(allocated->startAddr + i * PAGE_SIZE, page, PAGING_MEM_WRITE); pageMap(allocated->startAddr + i * PAGE_SIZE, page, PAGING_MEM_WRITE);
} else { } else {
printf("Ooops\n");
// TODO // TODO
assert(1); assert(0);
} }
} }
} }
restore_IRQs(irqFlags);
return allocated->startAddr; return allocated->startAddr;
} }

View File

@ -18,5 +18,9 @@ struct memArea {
void areaInit(vaddr_t firstMemUsed, vaddr_t lastUsed, vaddr_t stack_bottom, vaddr_t stack_top); void areaInit(vaddr_t firstMemUsed, vaddr_t lastUsed, vaddr_t stack_bottom, vaddr_t stack_top);
vaddr_t areaAlloc(unsigned int nbPages, uint32_t flags); vaddr_t areaAlloc(unsigned int nbPages, uint32_t flags);
// Remove an area from the free ones but do not add it into used ones.
// This area should be latter added woth areaAdd.
// Used by malloc to avoid recursivity issue
vaddr_t areaBook(unsigned int nbPages, uint32_t flags);
int areaFree(vaddr_t addr); int areaFree(vaddr_t addr);
int areaAdd(vaddr_t begin, vaddr_t end, int isFree); int areaAdd(vaddr_t begin, vaddr_t end, int isFree);

View File

@ -133,6 +133,7 @@ paddr_t allocPhyPage(uint nbPage)
next = mem->next; next = mem->next;
} }
allocatedPage += nbPage; allocatedPage += nbPage;
return head->phy_addr; return head->phy_addr;
} }