From d702c7b60e85339a37f0c7ee6246caca6c1af8cb Mon Sep 17 00:00:00 2001 From: Mathieu Maret Date: Thu, 28 Oct 2021 23:18:05 +0200 Subject: [PATCH] malloc: fix recursivity with areaAlloc --- core/alloc.c | 95 +++++++++++++++++++++++++++++++----------------- core/alloc.h | 7 ++-- core/allocArea.c | 59 +++++++++++++++++++++++++++++- core/allocArea.h | 4 ++ core/mem.c | 1 + 5 files changed, 127 insertions(+), 39 deletions(-) diff --git a/core/alloc.c b/core/alloc.c index e9058c5..05a086d 100644 --- a/core/alloc.c +++ b/core/alloc.c @@ -17,7 +17,7 @@ static struct slabDesc *slub; static int allocInitialized = FALSE; 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, 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 slabSize; unsigned char isSelf; -} initSlab[] = {{4, PAGE_SIZE, 0}, - {8, PAGE_SIZE, 0}, - {16, PAGE_SIZE, 0}, - {32, PAGE_SIZE, 0}, - {64, PAGE_SIZE, 0}, - {128, PAGE_SIZE, 0}, - {256, 2 * PAGE_SIZE, 0}, - {1024, 2 * PAGE_SIZE, 0}, - {2048, 3 * PAGE_SIZE, 0}, - {4096, 4 * PAGE_SIZE, 0}, - {0, 0, 0}}; + unsigned char neverEmpty; +} initSlab[] = {{4, PAGE_SIZE, 0, 0}, + {8, PAGE_SIZE, 0, 0}, + {16, PAGE_SIZE, 0, 0}, + {32, PAGE_SIZE, 0, 0}, + {64, PAGE_SIZE, 0, 0}, + {128, PAGE_SIZE, 0, 0}, + {256, 2 * PAGE_SIZE, 0, 0}, + {1024, 2 * PAGE_SIZE, 0, 0}, + {2048, 3 * PAGE_SIZE, 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) { 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)); - 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)); - 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); allocInitialized = TRUE; @@ -61,7 +63,7 @@ int allocPopulate() int ret; if ((ret = allocBookSlab(initSlab[i].elementSize, initSlab[i].slabSize, - initSlab[i].isSelf))) { + initSlab[i].isSelf, initSlab[i].neverEmpty))) { if (ret == -EEXIST) continue; pr_err("Fail to allocBookSlab %d for %d \n", ret, (1U << i)); @@ -73,7 +75,7 @@ int allocPopulate() 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 *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"); restore_IRQs(flags); return ret; @@ -112,7 +114,8 @@ int allocBookSlab(size_t sizeEl, size_t sizeSlab, int selfContained) 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; vaddr_t alloc; @@ -153,10 +156,11 @@ static int allocSlab(struct slabDesc **desc, size_t size, size_t sizeSlab, int s struct slabEntry *slab = &(*desc)->slab; list_singleton(slab, slab); - slab->page = (vaddr_t)alloc; - slab->full = 0; - slab->size = sizeSlab; - (*desc)->size = size; + slab->page = (vaddr_t)alloc; + slab->full = 0; + slab->size = sizeSlab; + (*desc)->neverEmpty = neverEmpty; + (*desc)->size = size; 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; return formatPage((*desc), size, sizeSlab, selfContained); - - return -ENOMEM; } static int formatPage(struct slabEntry *desc, size_t size, size_t sizeSlab, int selfContained) @@ -261,7 +263,7 @@ void *malloc(size_t size) disable_IRQs(flags); - if (size >= PAGE_SIZE){ + if (size >= PAGE_SIZE) { vaddr_t area = areaAlloc(DIV_ROUND_UP(size, PAGE_SIZE), AREA_PHY_MAP); return (void *)area; @@ -271,12 +273,36 @@ void *malloc(size_t size) return NULL; } + struct slabEntry *slabList = &slab->slab; list_foreach(&slab->slab, slabEntry, slabIdx) { if (!slabEntry->full) { - // pr_devel("found place in slub %d at idx %d for size %d\n", slubIdx, - // slabIdx, size); + // pr_devel("found place in slab idx %d for size %d\n", slabIdx, slab->size); 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); return ret; } @@ -284,8 +310,7 @@ void *malloc(size_t size) // No room found struct slabEntry *newSlabEntry; - struct slabEntry *slabList = &slab->slab; - size_t slabSize = MAX(PAGE_SIZE, size); + size_t slabSize = MAX(PAGE_SIZE, size); int retSlab; if ((retSlab = allocSlabEntry(&newSlabEntry, slab->size, slabSize, @@ -304,7 +329,8 @@ void *malloc(size_t size) return ret; } -void *zalloc(size_t size){ +void *zalloc(size_t size) +{ void *alloc = malloc(size); if (alloc != NULL) @@ -333,7 +359,8 @@ static int freeFromSlab(void *ptr, struct slabEntry *slab) return 0; } -int freeSlabAllocated(void *ptr){ +int freeSlabAllocated(void *ptr) +{ struct slabDesc *slab; int slabIdx; int flags; @@ -361,8 +388,8 @@ void free(void *ptr) { if (!ptr) return; - if(!freeSlabAllocated(ptr)) + if (!freeSlabAllocated(ptr)) return; - if(areaFree((vaddr_t)ptr)) + if (areaFree((vaddr_t)ptr)) pr_err("free: cannot found origin\n"); } diff --git a/core/alloc.h b/core/alloc.h index 944bf7c..df6171f 100644 --- a/core/alloc.h +++ b/core/alloc.h @@ -12,7 +12,7 @@ int allocPopulate(); * Allow malloc to allocate elements of this precise size. * 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 *zalloc(size_t size); @@ -22,9 +22,9 @@ void free(void *ptr); */ struct slabEntry { vaddr_t page; - size_t size; void *freeEl; - char full; + size_t size; + bool_t full;//TODO replace by freeEl == NULL struct slabEntry *next; struct slabEntry *prev; }; @@ -32,6 +32,7 @@ struct slabEntry { struct slabDesc { struct slabEntry slab; size_t size; + bool_t neverEmpty; struct slabDesc *next; struct slabDesc *prev; }; diff --git a/core/allocArea.c b/core/allocArea.c index e18a0e5..a733811 100644 --- a/core/allocArea.c +++ b/core/allocArea.c @@ -2,6 +2,7 @@ #include "alloc.h" #include "assert.h" #include "kernel.h" +#include "irq.h" #include "list.h" #include "mem.h" #include "stdarg.h" @@ -71,13 +72,64 @@ static void insertSorted(struct memArea **list, struct memArea *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) { struct memArea *area, *allocated; + uint32_t irqFlags; + + disable_IRQs(irqFlags); area = areaFindFit(nbPages); - if (!area) + if (!area){ + restore_IRQs(irqFlags); + return (vaddr_t)NULL; + } if (area->nbPages == nbPages) { 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)); if (!newArea) { pr_devel("Failed to allocated area of %d pages\n", nbPages); + restore_IRQs(irqFlags); return (vaddr_t)NULL; } @@ -109,12 +162,14 @@ vaddr_t areaAlloc(unsigned int nbPages, uint32_t flags) if (page) { pageMap(allocated->startAddr + i * PAGE_SIZE, page, PAGING_MEM_WRITE); } else { + printf("Ooops\n"); // TODO - assert(1); + assert(0); } } } + restore_IRQs(irqFlags); return allocated->startAddr; } diff --git a/core/allocArea.h b/core/allocArea.h index 948e527..1b21709 100644 --- a/core/allocArea.h +++ b/core/allocArea.h @@ -18,5 +18,9 @@ struct memArea { 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); +// 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 areaAdd(vaddr_t begin, vaddr_t end, int isFree); diff --git a/core/mem.c b/core/mem.c index de471b0..4fa25ce 100644 --- a/core/mem.c +++ b/core/mem.c @@ -133,6 +133,7 @@ paddr_t allocPhyPage(uint nbPage) next = mem->next; } allocatedPage += nbPage; + return head->phy_addr; }