mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 12:48:22 +00:00
slab: deallocation
This commit is contained in:
+77
-1
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user