rossdylan / rdslab

Trying my hand at implementing a simple slab allocator

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

rdslab is an implementation of a simple slab allocator. Slabs are currently defined as 2 pages of memory. These pages are then split into objects of a user specified size. These objects look like this:

   object 1          object 2          object 3
 +----------+------+----------+------+----------+------+
 | obj_size | meta | obj_size | meta | obj_size | meta |
 +----------+------+----------+------+----------+------+

The obj_size chunk contains the actual user specified memory the meta chunk contains a pointer to the slab this object is in. This pointer is used to figure out which slab a particular chunk of memory is in. This is needed in order to simplify the user facing api. The user facing api for rdslab works like malloc/free in that you ask it for memory it gives you a void pointer, and when you are done you just pass that pointer back to free.

A slab keeps track of the objects which are free in a minheap. I'm not sure if this was a good idea since initial profiling indicates a lot of time is taken up in the heap implementation. I might change this to be a simple linked list.

slabs are used within a struct called rdcache_t. an rdcache_t has 3 linked lists which represent the various states of slabs. When a slab is first initialized it is inserted into the free_slabs list. After it has started to be filled it is promoted to the partial_slabs list. Once it is totally filled it is promoted once more to the full_slabs list. After some objects within the slab are freed it is moved back to the partial_slabs list. The allocation algorithm takes objects first from the partial_slabs list, and if it is empty it takes a slab from the free_slabs list, allocates an object from it, and promotes it.

The 3 linked lists are built as follows:

   +------------+-----------+-----------+
   |            ^           ^           ^
   V            |           |           |
 rdlist_t -> rdslab_t -> rdslab_t -> rdslab_t
   |                                    ^
   |                                    |
   +------------------------------------+

The rdlist_t struct keeps track of the head and tail of the list, which are just slab structs. Each slab has a pointer to the list it is in so when an object is freed it knows which list to operate on.

The actual api has 3 calls and is defined in rdcache.h. rdcache_t is essentially a memory pool that contains some number of slabs. This is currently defined as 8 slabs, which totals 16 pages worth of memory.

To create a new rdcache_t you call rdcache_t *rdcache_new(uint64_t obj_size);

    #include "rdcache.h"
    #include <stdio.h>

    int main(int argc, char *argv[]) {
        rdcache_t cache = rdcache_new(24);
        printf("Objects in Cache: %llu\n", cache->count);
        printf("Max number of Objects: %llu\n", cache->max);
        printf("Cache Object Size: %llu\n", cache->obj_size);
    }

To allocate some mmeory call void *rdcache_malloc(rdcache_t *cache);

To free memory call void rdcache_free(rdcache_t *cache, void *ptr);

NOTE: rdcache_free doesn't actually free any memory, it just marks it as available for reuse.

    #include "rdcache.h"
    #include <stdio.h>
    typedef struct {
        int foo;
        char * bar;
    } baz;

    int main(int argc, char *argv[]) {
        rdcache_t cache = rdcache_new(sizeof(baz));
        baz *the_baz = rdcache_malloc(cache);
        rdcache_free(cache, the_baz);
    }

About

Trying my hand at implementing a simple slab allocator


Languages

Language:C 89.5%Language:Objective-C 6.9%Language:Makefile 3.7%