From ace65b453151845bc361f21f3e5b651c35f9f126 Mon Sep 17 00:00:00 2001 From: Jon Santmyer Date: Wed, 22 May 2024 13:00:41 -0400 Subject: massive refactor for mp and organization --- memory/slab.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 memory/slab.c (limited to 'memory/slab.c') diff --git a/memory/slab.c b/memory/slab.c new file mode 100644 index 0000000..dc8aeda --- /dev/null +++ b/memory/slab.c @@ -0,0 +1,148 @@ +#include "slab.h" +#include "bump.h" +#include "memory.h" +#include "string.h" +#include "jove.h" +#include "print.h" +#include "klib/format.h" + +static int +s_get_free_listw(size_t slabw, size_t objw) +{ + int freelistc = 1; + while(freelistc < 256) { + int maxobjc = (slabw - (freelistc * sizeof(uintptr_t))) / objw; + if(maxobjc <= freelistc) return maxobjc; + freelistc++; + } + return freelistc; +} + +static slab_t +*s_slab_new(slab_cache_t *cache, slab_t *last) +{ + size_t slab_width = (cache->slab_pages << PAGE_SHIFT); + uintptr_t descr_base = (uintptr_t)bump_alloc(slab_width); + slab_t *descr = (slab_t*)descr_base; + + size_t free_listc = s_get_free_listw( + slab_width - sizeof(slab_t), + cache->obj_size); + size_t descriptor_width = sizeof(slab_t) + + (free_listc * sizeof(uintptr_t)); + uintptr_t obj_base = descr_base + descriptor_width; + + if(free_listc < 8) { + free_listc = ((slab_width - sizeof(slab_t)) / cache->obj_size); + descr = kmalloc(sizeof(slab_t) + (free_listc * sizeof(uintptr_t))); + obj_base = descr_base; + } + cache->obj_capacity += free_listc; + + *descr = (slab_t) { + .prev = last, + .next = (last == NULL ? NULL : last->next), + .slab_base = (void*)descr_base, + .obj_base = (void*)obj_base, + .free_count = free_listc, + .free_index = free_listc - 1 + }; + for(size_t i = 0; i < free_listc; i++) { + descr->free[i] = obj_base + (i * cache->obj_size); + } + + return descr; +} + +void +slabcache_new(slab_cache_t *cache, char *name, size_t objsize) +{ + if(objsize % 8 > 0) objsize += (8 - (objsize % 8)); + size_t pages = objsize > 512 ? (objsize >> 9) : 1; + *cache = (slab_cache_t){ + .obj_size = objsize, + .slab_pages = pages, + .list_free = NULL, + .list_partial = NULL, + .list_full = NULL + }; + size_t namelen = strlen(name); + namelen = namelen > 32 ? 32 : namelen; + memcpy(cache->name, name, namelen); + + //Allocate the first slab + cache->list_free = s_slab_new(cache, NULL); +} + +void* +slab_alloc(slab_cache_t *cache) +{ + // Get a free slab + slab_t *slab = NULL; + if(cache->list_partial != NULL) slab = cache->list_partial; + if(slab == NULL && cache->list_free != NULL) { + slab = cache->list_free; + cache->list_free = slab->next; + } + if(slab == NULL) slab = s_slab_new(cache, cache->list_free); + cache->list_partial = slab; + + // Take an object from the slab. + uintptr_t objaddr = slab->free[slab->free_index]; + slab->free_index -= 1; + + if(slab->free_index < 0) { + slab->next = cache->list_full; + cache->list_full = slab; + } + return (void*)objaddr; +} + +void +slab_free(slab_cache_t *cache, void *ptr) +{ + uintptr_t addr = (uintptr_t)ptr; + //Look for the pointer in the bounds of every slab + for(slab_t *slab = cache->list_full; + slab != NULL; slab = slab->next) + { + uintptr_t base = (uintptr_t)slab->obj_base; + uintptr_t limit = ((uintptr_t)slab->slab_base) + + (cache->slab_pages << PAGE_SHIFT); + if(addr > limit || addr < base) continue; + if((addr - base) % cache->obj_size != 0) { + klogf("Tried to free offset pointer %#016X in slab %s\n", + addr, cache->name); + return; + } + slab->free_index++; + slab->free[slab->free_index] = addr; + + cache->list_full = slab->next; + slab->next = cache->list_partial; + cache->list_partial = slab; + return; + } + for(slab_t *slab = cache->list_partial; + slab != NULL; slab = slab->next) + { + uintptr_t base = (uintptr_t)slab->obj_base; + uintptr_t limit = ((uintptr_t)slab->slab_base) + + (cache->slab_pages << PAGE_SHIFT); + if(addr > limit || addr < base) continue; + if((addr - base) % cache->obj_size != 0) { + klogf("Tried to free offset pointer %#016X in slab %s\n", + addr, cache->name); + return; + } + slab->free_index++; + slab->free[slab->free_index] = addr; + + if(slab->free_index == ((int)slab->free_count - 1)) { + cache->list_partial = slab->next; + slab->next = cache->list_free; + cache->list_free = slab; + } + return; + } +} -- cgit v1.2.1