mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 12:48:22 +00:00
slab: big object allocation
This commit is contained in:
@@ -22,6 +22,5 @@ void kernel_entry() {
|
||||
logging_sethook(term_putchar);
|
||||
arch_mmu_init();
|
||||
vmm_init();
|
||||
slab_init();
|
||||
__assert(!"kernel entry end");
|
||||
}
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user