From f5c76c5ff8ee166fadea1c0a5de5a7711eb59be9 Mon Sep 17 00:00:00 2001 From: Matheus Date: Tue, 18 Apr 2023 23:48:41 -0300 Subject: [PATCH] slab: deallocation --- kernel-src/mm/slab.c | 78 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 1 deletion(-) diff --git a/kernel-src/mm/slab.c b/kernel-src/mm/slab.c index 34606f59..a63cbc23 100644 --- a/kernel-src/mm/slab.c +++ b/kernel-src/mm/slab.c @@ -76,15 +76,54 @@ static void *takeobject(scache_t *cache, slab_t *slab) { if (slab->free == NULL) return NULL; - void *objend = slab->free; + void **objend = slab->free; slab->free = *slab->free; slab->used += 1; + *objend = NULL; if (cache->size < SLAB_INDIRECT_CUTOFF) return (void *)((uintptr_t)objend - cache->size); else return (void *)((uintptr_t)slab->base + ((uintptr_t)objend - ROUND_DOWN((uintptr_t)slab, PAGE_SIZE)) / sizeof(void **) * cache->truesize); } +// frees an object and returns the slab the object belongs to +static slab_t *returnobject(scache_t *cache, void *obj) { + slab_t *slab = NULL; + void **freeptr = NULL; + if (cache->size < SLAB_INDIRECT_CUTOFF) { + slab = (slab_t *)(ROUND_DOWN((uintptr_t)obj, PAGE_SIZE) + SLAB_PAGE_OFFSET); + freeptr = (void **)((uintptr_t)obj + cache->size); + __assert(*freeptr == NULL); + } else { + slab = cache->full; + bool partial = false; + while (slab) { + void *top = (void *)((uintptr_t)slab->base + cache->slabobjcount * cache->truesize); + if (obj >= slab->base && obj < top) + break; + if (slab->next == NULL && partial == false) { + slab = cache->partial; + partial = true; + } else { + slab = slab->next; + } + } + __assert(slab); + uintmax_t objn = ((uintptr_t)obj - (uintptr_t)slab->base) / cache->truesize; + void **base = (void **)ROUND_DOWN((uintptr_t)obj, PAGE_SIZE); + freeptr = &base[objn]; + } + + if (cache->dtor) + cache->dtor(cache, obj); + + *freeptr = slab->free; + slab->free = freeptr; + --slab->used; + + return slab; +} + void *slab_allocate(scache_t *cache) { // TODO lock slab_t *slab = NULL; @@ -106,12 +145,20 @@ void *slab_allocate(scache_t *cache) { if (slab == cache->empty) { cache->empty = slab->next; + if (slab->prev) + slab->prev->next = slab->next; + if (slab->next) + slab->next->prev = slab->prev; slab->next = cache->partial; cache->partial = slab; } if (slab->used == cache->slabobjcount) { cache->partial = slab->next; + if (slab->prev) + slab->prev->next = slab->next; + if (slab->next) + slab->next->prev = slab->prev; slab->next = cache->full; cache->full = slab; } @@ -121,6 +168,35 @@ void *slab_allocate(scache_t *cache) { return ret; } +void slab_free(scache_t *cache, void *addr) { + // TODO lock + + slab_t *slab = returnobject(cache, addr); + __assert(slab); + + if (slab->used == 0) { + cache->partial = slab->next; + if (slab->prev) + slab->prev->next = slab->next; + if (slab->next) + slab->next->prev = slab->prev; + slab->next = cache->empty; + cache->empty = slab; + } + + if (slab->used == cache->slabobjcount - 1) { + cache->full = slab->next; + if (slab->prev) + slab->prev->next = slab->next; + if (slab->next) + slab->next->prev = slab->prev; + slab->next = cache->empty; + cache->empty = slab; + } + + // TODO unlock +} + scache_t *slab_newcache(size_t size, size_t alignment, void (*ctor)(scache_t *, void *), void (*dtor)(scache_t *, void *)) { if (alignment == 0) alignment = 8;