From f04d4b5a31db6eb2a4ba269839829ca38e5100ae Mon Sep 17 00:00:00 2001 From: Matheus Date: Fri, 19 Aug 2022 22:11:06 -0300 Subject: [PATCH] page allocator for alloc() --- src/include/kernel/pagealloc.h | 11 +++ src/include/kernel/slab.h | 3 +- src/sys/mm/alloc.c | 34 +++++++-- src/sys/mm/pagealloc.c | 136 +++++++++++++++++++++++++++++++++ src/sys/mm/slab.c | 5 ++ 5 files changed, 181 insertions(+), 8 deletions(-) create mode 100644 src/include/kernel/pagealloc.h create mode 100644 src/sys/mm/pagealloc.c diff --git a/src/include/kernel/pagealloc.h b/src/include/kernel/pagealloc.h new file mode 100644 index 00000000..f2c63563 --- /dev/null +++ b/src/include/kernel/pagealloc.h @@ -0,0 +1,11 @@ +#ifndef _PAGEALLOC_H_INCLUDE +#define _PAGEALLOC_H_INCLUDE + +#include +#include + +void* pageallocator_alloc(size_t size); +bool pageallocator_free(void* addr); +void* pageallocator_realloc(void* addr, size_t size, bool* nonexistant); + +#endif diff --git a/src/include/kernel/slab.h b/src/include/kernel/slab.h index ac30ecce..56b4c2f6 100644 --- a/src/include/kernel/slab.h +++ b/src/include/kernel/slab.h @@ -1,11 +1,12 @@ #ifndef _SLAB_H_INCLUDE #define _SLAB_H_INCLUDE + #include void* slab_alloc(size_t); void slab_free(void*); - +size_t slab_getentrysize(void*); void slab_init(); #endif diff --git a/src/sys/mm/alloc.c b/src/sys/mm/alloc.c index 25b40e3a..3a1c40c6 100644 --- a/src/sys/mm/alloc.c +++ b/src/sys/mm/alloc.c @@ -1,13 +1,18 @@ #include #include #include +#include void* alloc(size_t size){ - return slab_alloc(size); + if(size > 256) // slab implementation max size + return pageallocator_alloc(size); + else + return slab_alloc(size); } void free(void* addr){ - slab_free(addr); + if(pageallocator_free(addr)) + slab_free(addr); } void alloc_init(){ @@ -15,14 +20,29 @@ void alloc_init(){ } void* realloc(void* addr, size_t size){ - void* tmp = alloc(size); - if(!tmp) + + bool nonexistant; + + void* newaddr = pageallocator_realloc(addr, size, &nonexistant); + + if(newaddr) + return newaddr; + + if(nonexistant == 0) + return NULL; + + + size_t slabsize = slab_getentrysize(addr); + + newaddr = alloc(size); + + if(!newaddr) return NULL; - memcpy(tmp, addr, size); + memcpy(newaddr, addr, slabsize); - free(addr); + slab_free(addr); - return tmp; + return newaddr; } diff --git a/src/sys/mm/pagealloc.c b/src/sys/mm/pagealloc.c new file mode 100644 index 00000000..dcd43f71 --- /dev/null +++ b/src/sys/mm/pagealloc.c @@ -0,0 +1,136 @@ +#include +#include +#include +#include +#include +#include + +typedef struct _page_allocation{ + struct _page_allocation* next; + void* start; + size_t size; +} page_allocation; + +static int lock; +static page_allocation* list; + +void* pageallocator_alloc(size_t size){ + + page_allocation* alloc = slab_alloc(sizeof(page_allocation)); + + if(!alloc) + return NULL; + + size_t pagec = size / PAGE_SIZE + (size % PAGE_SIZE ? 1 : 0); + + // use vmm? + + alloc->start = pmm_hhdmalloc(pagec); + + if(!alloc->start){ + slab_free(alloc); + return NULL; + } + + alloc->size = size; + + spinlock_acquire(&lock); + + if(list) + alloc->next = list; + + list = alloc; + + spinlock_release(&lock); + + return alloc->start; + +} + +bool pageallocator_free(void* addr){ + spinlock_acquire(&lock); + + page_allocation* it = list; + page_allocation* prev = NULL; + + while(it){ + void* end = it->start + it->size; + if(it->start <= addr && end > addr) + break; + prev = it; + it = it->next; + } + + if(!it){ + spinlock_release(&lock); + return false; + } + + if(!prev) + list = it->next; + else + prev->next = it->next; + + spinlock_release(&lock); + + + size_t pagec = it->size / PAGE_SIZE + (it->size % PAGE_SIZE ? 1 : 0); + + // use vmm? + pmm_hhdmfree(it->start, pagec); + slab_free(it); + + return true; +} + +void* pageallocator_realloc(void* addr, size_t size, bool* nonexistant){ + + spinlock_acquire(&lock); + + page_allocation* it = list; + page_allocation* prev = NULL; + + while(it){ + void* end = it->start + it->size; + if(it->start <= addr && end > addr) + break; + prev = it; + it = it->next; + } + + if(!it){ + *nonexistant = 1; + spinlock_release(&lock); + return NULL; + } + size_t oldpagec = it->size / PAGE_SIZE + (it->size % PAGE_SIZE ? 1 : 0); + size_t newpagec = size / PAGE_SIZE + (size % PAGE_SIZE ? 1 : 0); + + if(oldpagec == newpagec){ + spinlock_release(&lock); + return it->start; + } + + if(!prev) + list = it->next; + else + prev->next = it->next; + + spinlock_release(&lock); + + void* new = pageallocator_alloc(size); + + if(!new){ + *nonexistant = 0; + return NULL; + } + + memcpy(new, it->start, it->size); + + // use vmm? + pmm_hhdmfree(it->start, oldpagec); + slab_free(it); + + return new; + +} diff --git a/src/sys/mm/slab.c b/src/sys/mm/slab.c index 7ada74a2..d6920c85 100644 --- a/src/sys/mm/slab.c +++ b/src/sys/mm/slab.c @@ -50,6 +50,11 @@ static inline slabdesc* getslabdesc(size_t size){ } +size_t slab_getentrysize(void* addr){ + slab_t *slab = (size_t)addr & ~(0xFFF); + return slab->entrysize; +} + static void free(void* addr){ // align down to page size