this is my slab allocator code
Code: Select all
struct pmm_node
{
struct pmm_node *next;
};
struct Header
{
size_t size;
struct Header *next;
struct pmm_node *freelist;
};
struct cache
{
struct Header *slabs;
size_t size;
};
struct cache kmalloc_cache[8];
void init_cache(struct cache *cache, size_t size)
{
char ****[64] = "";
cache->size = size;
void *page = pmm_alloc_singlep();
struct Header *h = page + hhdm_request.response->offset;
h->size = size;
cache->slabs = (uint64_t)h;
size_t obj_amount = (4096 - sizeof(struct Header)) / (size);
write_color(ctx, "Slab: Creating Cache of Object Count: ", 0);
write(ctx, itoa(****, obj_amount));
write(ctx, " and Size: ");
write(ctx, itoa(****, size));
write(ctx, "\n");
struct pmm_node *start = (uint64_t)h + sizeof(struct Header);
h->freelist = start;
struct pmm_node *prev = start;
for (int i = 1; i < obj_amount; i++)
{
struct pmm_node *new = (uint64_t)start + (i * size);
prev->next = new;
prev = new;
}
write_color(ctx, "Slab: Cache Created!\n", 0);
}
struct Header *make_slab(size_t size)
{
char ****[64] = "";
void *page = pmm_alloc_singlep();
struct Header *h = page + hhdm_request.response->offset;
h->size = size;
size_t obj_amount = (4096 - sizeof(struct Header)) / (size);
struct pmm_node *start = (uint64_t)h + sizeof(struct Header);
h->freelist = start;
struct pmm_node *prev = start;
for (int i = 1; i < obj_amount; i++)
{
struct pmm_node *new = (uint64_t)start + (i * size);
prev->next = new;
prev = new;
}
return h;
}
size_t next_pow2(size_t v)
{
v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v++;
return v;
}
static inline struct cache *search_for_bigenoughcache(size_t size)
{
for (int i = 0; i < 8; i++)
{
if (kmalloc_cache[i].size >= size)
{
return &kmalloc_cache[i];
}
}
return NULL;
}
void *slab_alloc(struct cache *cache)
{
char ****[64] = "";
struct Header *h = cache->slabs;
while (h != NULL)
{
if (h->freelist != NULL)
{
struct pmm_node *him = h->freelist;
serial_print("memory address: ");
serial_print(itoah(****, (uint64_t)him));
serial_print(" size: ");
serial_print(itoa(****, h->size));
serial_print("\n");
h->freelist = him->next;
return him;
}
else
{
if (h->next == NULL)
{
break;
}
h = h->next; // go to next header
}
}
serial_print("um\n");
// no slabs at all on this cache
// allocate new slab
struct Header *new_slab = make_slab(cache->size);
h->next = new_slab;
struct pmm_node *we = new_slab->freelist;
new_slab->freelist = new_slab->freelist->next;
serial_print(itoah(****, (uint64_t)new_slab->freelist));
serial_print("making new slab\n");
return we;
}
void free(void *addr)
{
serial_print("before\n");
char da[64] = "";
if ((uint64_t)addr == 0)
{
return;
}
struct Header *h = (uint64_t)addr & ~0xFFF;
struct cache *rightcache = NULL;
for (int i = 0; i < 8; i++)
{
if (kmalloc_cache[i].size == h->size)
{
rightcache = &kmalloc_cache[i];
}
}
if (rightcache == NULL)
{
return;
}
struct pmm_node *new = (uint64_t)addr;
new->next = h->freelist;
h->freelist = new;
// put header into header freelist if not
struct Header *prev = NULL;
struct Header ***** = rightcache->slabs;
while (**** != NULL)
{
if (**** == h)
{
return; // no need to do anything
}
else
{
prev = ****;
**** = ****->next;
}
}
// slab was fully used and now needs to be put back onto the header list
serial_print("go back\n");
prev->next = h;
return;
}
void *kmalloc(size_t size)
{
char ****[64] = "";
struct cache *ca = search_for_bigenoughcache(next_pow2(size));
if (ca == NULL)
{
serial_print("COUDNLT FIND FOR THIS SIZE BOZO!\n");
return;
}
return slab_alloc(ca);
}
void init_slabs()
{
init_cache(&kmalloc_cache[0], 8);
init_cache(&kmalloc_cache[1], 16);
init_cache(&kmalloc_cache[2], 32);
init_cache(&kmalloc_cache[3], 64);
init_cache(&kmalloc_cache[4], 128);
init_cache(&kmalloc_cache[5], 256);
init_cache(&kmalloc_cache[6], 512);
init_cache(&kmalloc_cache[7], 1024);
}