mrjbom wrote:I have a ready buddy allocator and I would like to implement SLAB allocator on top of it for kernel needs.
However, I can't find a simple enough yet practical explanation of how I can implement this in my situation.
All the articles about implementing the SLAB allocator boil down to articles about how it works in Linux. Linux articles tend to be overly complicated, since Linux is more complicated than my hobby OS.
I want to find something (an article) that could help me, in my hobby OS, to implement the SLAB allocator. Does anyone know a source of such information? (I have already read the original SunOS article).
I want an article that deals with hobby OSdev, not Linux.
https://en.wikipedia.org/wiki/Slab_allocation
My hobby OS slab allocator is barely documented in the following page. But most of this page relates to how the garbage collection I implement on top of the slab allocator works:
-
http://thewrongchristian.org.uk:8082/wiki?name=Slab
Code:
-
http://thewrongchristian.org.uk:8082/ar ... b623fa8555
But my slab allocator is limited to single page slabs, and so is not very general purpose and useful only for small structures, and not for anything approaching page sized or larger.
But slab allocators are actually really simple.
The slab is the aggregate object out of which you allocate individual objects. In my OS, that aggregate object is page sized, in the bonwick paper and in Linux, the slab can be multiple pages.
Your slab has some meta-data. In my slab, I put this at the front of the slab. Then the remainder of the slab is split into equal sized allocation units (I call these slots in my allocator). The idea being that each slab allocates objects of the same type, hence the allocation sizes are all the same.
Your slab meta-data describes what the contained objects are (in my slab allocator, there is a pointer to a slab type, which gives information like the object size, and garbage collection marking/finalization functions, and also a list of slabs for this slab type.)
The slab meta-data also needs to track the free objects in the slab. In my slab allocator, the free objects use a linked list, and the slab meta-data points to the head of that linked list. Allocation from a slab is just then a case of removing the first free object from the list, and pointing to the next free object in the slab meta-data.
So, to allocate an object of type, say, a vnode (function names from my OS code).
- Using the vnode slab type, call slab_alloc().
- slab_alloc will use the type information to look for a slab of this type with some free space (slab_type_t::first in my code.)
- Having found a slab, remove the first free object from the list (slab_t::free in my code), and point the slab free pointer to the next free object (if any).
- Return the pointer for the now allocated object. My objects are preceded by a header (slab_slot_t in my code), so we advance the pointer beyond the header and return that.
My code is perhaps not the best example for you though, complicated as it is by the garbage collection code it incorporates. But if you can unpick the garbage collection code from slab_alloc, the actual lines of code to do the allocation are of the order of a 10-20 lines of code, all O(1), which is why slab allocators are so attractive.
Freeing a slab allocated object is also easy. Given the object pointer, you can find the slab from which it came easily if your slabs are paged sized. Simply round the pointer down to the slab alignment (1 page in my example), then that gives you the location of your header. You can use the unrounded portion of the freed pointer to find the actual object within the slab (it's just an array of uniformly sized objects), do a quick check that the offset is a valid object pointer, then put the newly freed object onto the slab meta-data free list.