Implement malloc with a working free

This commit is contained in:
Mathieu Maret 2024-01-29 21:47:24 +01:00
parent edbbaec930
commit 2b324ac62d
4 changed files with 97 additions and 40 deletions

View File

@ -5,6 +5,7 @@
#include "list.h" #include "list.h"
#include "mem.h" #include "mem.h"
#include "mmuContext.h" #include "mmuContext.h"
#include "paging.h"
#include "process.h" #include "process.h"
#include "stdarg.h" #include "stdarg.h"
#include "thread.h" #include "thread.h"
@ -78,7 +79,7 @@ int uAddrSpaceDelete(struct uAddrSpace *addr)
// TODO Implement me with real ressources // TODO Implement me with real ressources
assertmsg(reg->res == NULL, "Unsupported mapper ressource"); assertmsg(reg->res == NULL, "Unsupported mapper ressource");
// This is memory allocated for the heap just unmap it to free it // This is memory allocated for the heap just unmap it to free it
pr_devel("Freeing heap for process %s\n", processGetName(addr->process)); pr_devel("Freeing heap 0x%lx for process %s\n", reg->addr, processGetName(addr->process));
pageUnmap(reg->addr); pageUnmap(reg->addr);
free(reg); free(reg);
} }
@ -127,7 +128,7 @@ int uAddrSpaceCheckNAlloc(struct uAddrSpace *as, vaddr_t addr)
struct uAddrVirtualReg *newReg; struct uAddrVirtualReg *newReg;
int right = PAGING_MEM_USER | PAGING_MEM_WRITE | PAGING_MEM_READ; int right = PAGING_MEM_USER | PAGING_MEM_WRITE | PAGING_MEM_READ;
pr_devel("Checking %lx inside %lx and %lx\n", addr, as->heapStart, as->heapStart +as->heapSize); pr_devel("Checking 0x%lx inside 0x%lx and 0x%lx\n", addr, as->heapStart, as->heapStart +as->heapSize);
if (addr < as->heapStart || addr >= as->heapStart + as->heapSize) { if (addr < as->heapStart || addr >= as->heapStart + as->heapSize) {
return -1; return -1;
} }

View File

@ -5,8 +5,7 @@
do { \ do { \
if (!(p)) { \ if (!(p)) { \
printf("BUG at %s:%d assert(%s)\n", __FILE__, __LINE__, #p); \ printf("BUG at %s:%d assert(%s)\n", __FILE__, __LINE__, #p); \
while (1) { \ _exit(-1); \
} \
} \ } \
} while (0) } while (0)
@ -15,7 +14,6 @@
if (!(p)) { \ if (!(p)) { \
printf("BUG at %s:%d assert(%s)\n", __FILE__, __LINE__, #p); \ printf("BUG at %s:%d assert(%s)\n", __FILE__, __LINE__, #p); \
printf(__VA_ARGS__); \ printf(__VA_ARGS__); \
while (1) { \ _exit(-1); \
} \
} \ } \
} while (0) } while (0)

View File

@ -1,4 +1,5 @@
#include "libc.h" #include "libc.h"
#include "list.h"
#include "minmax.h" #include "minmax.h"
#include "swintr.h" #include "swintr.h"
#include "syscall.h" #include "syscall.h"
@ -585,45 +586,90 @@ void *sbrk(intptr_t increment)
if (increment == 0) { if (increment == 0) {
return current; return current;
} }
if (syscall1(SYSCALL_ID_BRK, (uintptr_t)current + increment)) { if ((uintptr_t)syscall1(SYSCALL_ID_BRK, (uintptr_t)current + increment) < ((uintptr_t)current + increment)) {
// errno = ENOMEM // errno = ENOMEM
return (void *)-1; return (void *)-1;
} }
return current; return current;
} }
static char *heapTop = 0; // Malloc internal
static char *heapFree = 0; struct heapBlock {
static char *lastAlloc = 0; size_t size;
struct heapBlock *next, *prev;
int free;
};
static struct heapBlock *heapBlkList = NULL;
struct heapBlock *findFreeBlock(size_t size){
struct heapBlock *cur = NULL;
struct heapBlock *found = NULL;
int idx;
list_foreach(heapBlkList, cur, idx){
if(cur->size >= size && cur->free){
found = cur;
break;
}
}
return found;
}
struct heapBlock *allocNewBlock(size_t size) {
struct heapBlock *blk = sbrk(size + sizeof(struct heapBlock));
struct heapBlock *head = sbrk(0);
size_t blkSize = (intptr_t)head - (intptr_t)blk - sizeof(struct heapBlock);
if (blk == (void *)-1) {
return NULL;
}
blk->size = blkSize;
blk->free = 1;
list_add_tail(heapBlkList, blk);
return blk;
}
struct heapBlock *splitBlock(struct heapBlock *blk, size_t neededSize)
{
if (blk->size < neededSize + sizeof(struct heapBlock) + 1) {
return NULL;
}
struct heapBlock *newBlk = (struct heapBlock *)((uintptr_t)(blk + 1) + neededSize);
newBlk->free = 1;
newBlk->size = blk->size - sizeof(struct heapBlock) - neededSize;
blk->size = neededSize;
return newBlk;
}
void *malloc(size_t size) void *malloc(size_t size)
{ {
if (heapTop == 0) { if (size == 0)
heapTop = heapFree = sbrk(0); return NULL;
} else {
heapTop = sbrk(0);
}
if (heapFree + size + sizeof(size) > heapTop) { struct heapBlock *blk = findFreeBlock(size);
if (brk(heapTop + size + sizeof(size))) if (!blk)
return NULL; blk = allocNewBlock(size);
if (!blk)
return NULL;
struct heapBlock *remainBlock = splitBlock(blk, size);
if (remainBlock) {
list_add_head(heapBlkList, remainBlock);
} }
blk->free = 0;
*((size_t *)heapFree) = size; return blk + 1; // return the area after the blk description
heapFree += sizeof(size);
lastAlloc = heapFree;
heapFree += size;
return lastAlloc;
} }
void free(void *ptr) struct heapBlock *getHeapBlock(void *ptr) {
{ return (struct heapBlock *)ptr - 1;
void *size_addr = ((char *)ptr - sizeof(size_t));
size_t size = *(size_t *)size_addr;
if (heapFree - size == ptr) {
heapFree = size_addr;
}
//TODO ELSE
return;
} }
void free(void *ptr){
if(!ptr)
return;
struct heapBlock *blk = getHeapBlock(ptr);
assert(blk->free == 0);
blk->free = 1;
}

View File

@ -24,21 +24,33 @@ int func_suicide()
char *initialHeap = 0; char *initialHeap = 0;
int func_alloc() int func_alloc()
{ {
if (initialHeap == 0) { if (initialHeap == 0) {
initialHeap = sbrk(0); initialHeap = sbrk(0);
} }
printf("Testing allocation\n"); printf("Testing allocation\n");
int allocSize = 4096 * 2; int allocSize = 4096 * 2;
char *currentHeap = sbrk(0); char *currentHeap = sbrk(0);
if (currentHeap - initialHeap < allocSize) { if (currentHeap - initialHeap < allocSize) {
brk(initialHeap + allocSize); brk(initialHeap + allocSize);
} }
int *allocatedData = (int *)initialHeap; int *allocatedData = (int *)initialHeap;
for (unsigned int i = 0; i < allocSize / sizeof(int); i++) { for (unsigned int i = 0; i < allocSize / sizeof(int); i++) {
allocatedData[i] = i; allocatedData[i] = i;
} }
printf("Success\n"); printf("Success\nTesting malloc\n");
uintptr_t heap = (uintptr_t)sbrk(0);
for (int i = 0; i < 12; i++) {
void *ptr = malloc(1 << i);
printf("malloc size %d: 0x%p\n", (1 << i), ptr);
if (ptr == NULL) {
printf("Malloc failed\n");
}
memset(ptr, 0, 1 << i);
free(ptr);
}
uintptr_t newHeap = (uintptr_t)sbrk(0);
printf("Malloc used %dB\n", newHeap - heap);
return 0; return 0;
} }