diff --git a/kernel-src/arch/x86-64/main.c b/kernel-src/arch/x86-64/main.c index 41150e44..b38509db 100644 --- a/kernel-src/arch/x86-64/main.c +++ b/kernel-src/arch/x86-64/main.c @@ -22,6 +22,5 @@ void kernel_entry() { logging_sethook(term_putchar); arch_mmu_init(); vmm_init(); - slab_init(); __assert(!"kernel entry end"); } diff --git a/kernel-src/include/kernel/slab.h b/kernel-src/include/kernel/slab.h index d3534fe4..6f3a4fa3 100644 --- a/kernel-src/include/kernel/slab.h +++ b/kernel-src/include/kernel/slab.h @@ -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 { diff --git a/kernel-src/mm/slab.c b/kernel-src/mm/slab.c index 7532f524..34606f59 100644 --- a/kernel-src/mm/slab.c +++ b/kernel-src/mm/slab.c @@ -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; - return (void *)((uintptr_t)objend - cache->size); + 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); -}