125 lines
2.5 KiB
C
125 lines
2.5 KiB
C
/*
|
|
* Copyright (c) 2013-2014 Stanford University
|
|
* All rights reserved.
|
|
*/
|
|
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
|
|
#include <sys/cdefs.h>
|
|
#include <sys/kassert.h>
|
|
#include <sys/kdebug.h>
|
|
#include <sys/queue.h>
|
|
#include <sys/kmem.h>
|
|
|
|
#include <machine/pmap.h>
|
|
|
|
LIST_HEAD(SlabListHead, Slab) slabList = LIST_HEAD_INITIALIZER(slabList);
|
|
|
|
void
|
|
Slab_Init(Slab *slab, const char *name, uintptr_t objsz, uintptr_t align)
|
|
{
|
|
ASSERT(objsz >= sizeof(SlabElement));
|
|
|
|
slab->objsz = objsz;
|
|
slab->align = align;
|
|
slab->xmem = XMem_New();
|
|
slab->objs = 0;
|
|
slab->freeObjs = 0;
|
|
slab->allocs = 0;
|
|
slab->frees = 0;
|
|
LIST_INIT(&slab->freeList);
|
|
|
|
ASSERT(slab->xmem != NULL);
|
|
|
|
strncpy(&slab->name[0], name, SLAB_NAMELEN);
|
|
|
|
Spinlock_Init(&slab->lock, name, SPINLOCK_TYPE_NORMAL);
|
|
|
|
LIST_INSERT_HEAD(&slabList, slab, slabList);
|
|
}
|
|
|
|
int
|
|
SlabExtend(Slab *slab)
|
|
{
|
|
uintptr_t base = XMem_GetBase(slab->xmem);
|
|
uintptr_t len = XMem_GetLength(slab->xmem);
|
|
uintptr_t inc;
|
|
uintptr_t realObjSz = ROUNDUP(slab->objsz, slab->align);
|
|
|
|
inc = ROUNDUP(realObjSz * 64, PGSIZE);
|
|
if (inc < 4 * PGSIZE) {
|
|
inc = 4 * PGSIZE;
|
|
}
|
|
|
|
if (!XMem_Allocate(slab->xmem, len + inc)) {
|
|
kprintf("Slab: Cannot grow XMem region!\n");
|
|
return -1;
|
|
}
|
|
|
|
// Add empty objects to linked list
|
|
uintptr_t i;
|
|
uintptr_t objs = inc / realObjSz;
|
|
for (i = 0; i < objs; i++) {
|
|
SlabElement *elem = (SlabElement *)(base + len + i * realObjSz);
|
|
|
|
LIST_INSERT_HEAD(&slab->freeList, elem, free);
|
|
}
|
|
|
|
slab->objs += objs;
|
|
slab->freeObjs += objs;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void *
|
|
Slab_Alloc(Slab *slab)
|
|
{
|
|
SlabElement *elem;
|
|
|
|
Spinlock_Lock(&slab->lock);
|
|
|
|
if (slab->freeObjs == 0)
|
|
SlabExtend(slab);
|
|
|
|
elem = LIST_FIRST(&slab->freeList);
|
|
if (elem != NULL) {
|
|
LIST_REMOVE(elem, free);
|
|
slab->allocs++;
|
|
slab->freeObjs--;
|
|
}
|
|
|
|
Spinlock_Unlock(&slab->lock);
|
|
|
|
return (void *)elem;
|
|
}
|
|
|
|
void
|
|
Slab_Free(Slab *slab, void *region)
|
|
{
|
|
Spinlock_Lock(&slab->lock);
|
|
|
|
SlabElement *elem = (SlabElement *)region;
|
|
LIST_INSERT_HEAD(&slab->freeList, elem, free);
|
|
slab->frees++;
|
|
slab->freeObjs++;
|
|
|
|
Spinlock_Unlock(&slab->lock);
|
|
}
|
|
|
|
static void
|
|
Debug_Slabs(int argc, const char *argv[])
|
|
{
|
|
Slab *slab;
|
|
|
|
kprintf("%-36s %-10s %-10s %-10s\n", "Slab Name", "Alloc", "Free", "Total");
|
|
LIST_FOREACH(slab, &slabList, slabList) {
|
|
kprintf("%-36s %-10lld %-10lld %-10lld\n", slab->name,
|
|
slab->objs - slab->freeObjs, slab->freeObjs, slab->objs);
|
|
}
|
|
}
|
|
|
|
REGISTER_DBGCMD(slabs, "Display list of slabs", Debug_Slabs);
|
|
|