slab: big object allocation

This commit is contained in:
Matheus
2023-04-18 23:13:29 -03:00
parent f9d1c046b7
commit 81a50399af
3 changed files with 35 additions and 13 deletions
-1
View File
@@ -22,6 +22,5 @@ void kernel_entry() {
logging_sethook(term_putchar);
arch_mmu_init();
vmm_init();
slab_init();
__assert(!"kernel entry end");
}
+1
View File
@@ -9,6 +9,7 @@ typedef struct slab_t {
struct slab_t *prev;
size_t used;
void **free;
void *base;
} slab_t;
typedef struct scache_t {
+33 -11
View File
@@ -8,6 +8,7 @@
#define SLAB_PAGE_OFFSET (PAGE_SIZE - sizeof(slab_t))
#define SLAB_DATA_SIZE SLAB_PAGE_OFFSET
#define SLAB_INDIRECT_PTR_COUNT (SLAB_DATA_SIZE / sizeof(void **))
#define GET_SLAB(x) (slab_t *)(ROUND_DOWN((uintptr_t)x, PAGE_SIZE) + SLAB_PAGE_OFFSET)
@@ -19,9 +20,7 @@ static scache_t selfcache = {
.slabobjcount = SLAB_DATA_SIZE / ROUND_UP(sizeof(scache_t) + sizeof(void **), 8)
};
static scache_t *slabcache;
static void initsmall(scache_t *cache, slab_t *slab, void *base) {
static void initdirect(scache_t *cache, slab_t *slab, void *base) {
slab->free = NULL;
slab->used = 0;
@@ -35,14 +34,38 @@ static void initsmall(scache_t *cache, slab_t *slab, void *base) {
}
}
static void initindirect(scache_t *cache, slab_t *slab, void **base, void *objbase) {
slab->free = NULL;
slab->used = 0;
slab->base = objbase;
for (uintmax_t offset = 0; offset < cache->truesize * cache->slabobjcount; offset += cache->truesize) {
if (cache->ctor)
cache->ctor(cache, (void *)((uintptr_t)objbase + offset));
void **freenext = &base[offset / cache->truesize];
*freenext = slab->free;
slab->free = freenext;
}
}
static bool growcache(scache_t *cache) {
__assert(cache->size < SLAB_INDIRECT_CUTOFF); // TODO bigger than this allocation and support
void *_slab = vmm_map(NULL, PAGE_SIZE, VMM_FLAGS_ALLOCATE, ARCH_MMU_FLAG_READ | ARCH_MMU_FLAG_WRITE | ARCH_MMU_FLAG_NOEXEC, NULL);
if (_slab == NULL)
return false;
slab_t *slab = GET_SLAB(_slab);
initsmall(cache, slab, _slab);
if (cache->size < SLAB_INDIRECT_CUTOFF) {
initdirect(cache, slab, _slab);
} else {
void *base = vmm_map(NULL, cache->slabobjcount * cache->truesize, VMM_FLAGS_ALLOCATE, ARCH_MMU_FLAG_READ | ARCH_MMU_FLAG_WRITE | ARCH_MMU_FLAG_NOEXEC, NULL);
if (base == NULL) {
vmm_unmap(_slab, PAGE_SIZE, 0);
return false;
}
initindirect(cache, slab, _slab, base);
}
slab->next = cache->empty;
cache->empty = slab;
@@ -56,7 +79,10 @@ static void *takeobject(scache_t *cache, slab_t *slab) {
void *objend = slab->free;
slab->free = *slab->free;
slab->used += 1;
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);
}
void *slab_allocate(scache_t *cache) {
@@ -105,7 +131,8 @@ scache_t *slab_newcache(size_t size, size_t alignment, void (*ctor)(scache_t *,
cache->size = size;
cache->alignment = alignment;
cache->truesize = ROUND_UP(size + sizeof(void **), alignment);
size_t freeptrsize = size < SLAB_INDIRECT_CUTOFF ? sizeof(void **) : 0;
cache->truesize = ROUND_UP(size + freeptrsize, alignment);
cache->ctor = ctor;
cache->dtor = dtor;
cache->slabobjcount = size < SLAB_INDIRECT_CUTOFF ? SLAB_DATA_SIZE / cache->truesize : SLAB_INDIRECT_COUNT;
@@ -114,8 +141,3 @@ scache_t *slab_newcache(size_t size, size_t alignment, void (*ctor)(scache_t *,
return cache;
}
void slab_init() {
slabcache = slab_newcache(sizeof(slab_t), 0, NULL, NULL);
__assert(slabcache);
}