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);
|
logging_sethook(term_putchar);
|
||||||
arch_mmu_init();
|
arch_mmu_init();
|
||||||
vmm_init();
|
vmm_init();
|
||||||
slab_init();
|
|
||||||
__assert(!"kernel entry end");
|
__assert(!"kernel entry end");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ typedef struct slab_t {
|
|||||||
struct slab_t *prev;
|
struct slab_t *prev;
|
||||||
size_t used;
|
size_t used;
|
||||||
void **free;
|
void **free;
|
||||||
|
void *base;
|
||||||
} slab_t;
|
} slab_t;
|
||||||
|
|
||||||
typedef struct scache_t {
|
typedef struct scache_t {
|
||||||
|
|||||||
+34
-12
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#define SLAB_PAGE_OFFSET (PAGE_SIZE - sizeof(slab_t))
|
#define SLAB_PAGE_OFFSET (PAGE_SIZE - sizeof(slab_t))
|
||||||
#define SLAB_DATA_SIZE SLAB_PAGE_OFFSET
|
#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)
|
#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)
|
.slabobjcount = SLAB_DATA_SIZE / ROUND_UP(sizeof(scache_t) + sizeof(void **), 8)
|
||||||
};
|
};
|
||||||
|
|
||||||
static scache_t *slabcache;
|
static void initdirect(scache_t *cache, slab_t *slab, void *base) {
|
||||||
|
|
||||||
static void initsmall(scache_t *cache, slab_t *slab, void *base) {
|
|
||||||
slab->free = NULL;
|
slab->free = NULL;
|
||||||
slab->used = 0;
|
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) {
|
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);
|
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)
|
if (_slab == NULL)
|
||||||
return false;
|
return false;
|
||||||
slab_t *slab = GET_SLAB(_slab);
|
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;
|
slab->next = cache->empty;
|
||||||
cache->empty = slab;
|
cache->empty = slab;
|
||||||
@@ -56,7 +79,10 @@ static void *takeobject(scache_t *cache, slab_t *slab) {
|
|||||||
void *objend = slab->free;
|
void *objend = slab->free;
|
||||||
slab->free = *slab->free;
|
slab->free = *slab->free;
|
||||||
slab->used += 1;
|
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) {
|
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->size = size;
|
||||||
cache->alignment = alignment;
|
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->ctor = ctor;
|
||||||
cache->dtor = dtor;
|
cache->dtor = dtor;
|
||||||
cache->slabobjcount = size < SLAB_INDIRECT_CUTOFF ? SLAB_DATA_SIZE / cache->truesize : SLAB_INDIRECT_COUNT;
|
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;
|
return cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
void slab_init() {
|
|
||||||
slabcache = slab_newcache(sizeof(slab_t), 0, NULL, NULL);
|
|
||||||
__assert(slabcache);
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user