-
Notifications
You must be signed in to change notification settings - Fork 3
Object Allocation
Currently, the kernel supports only one allocator for per-object allocation. It is the slab allocator.
The slab allocator works by allocating large slabs directly from the page-allocator. Size of slabs are fixed in the algorithm and presently it is 4KB per slab. Each slab contains a descriptor struct Slab
at the very end of the page.
struct Slab
{
LinkedListNode liLinker;
STACK bufferStack;
unsigned long colouringOffset;
unsigned long freeCount;
};
struct ObjectInfo
{
LinkedListNode liLinker;// Used for listing this, for pressurizing vmm
const char *name;// Name of the object, used for debugging
unsigned long rawSize;// Raw size of the object
unsigned long colorScheme;// Current coloring scheme for the incoming slabs
unsigned long align;// Alignment constraints for the object
unsigned long bufferSize;// Size of the aligned-object buffer
unsigned long bufferPerSlab;// No. of buffers that can fit into one slab
unsigned long bufferMargin;// Leftover-space in a slab, after buffers
void (*ctor) (Void *);// Object-constructor (not for C++, yet)
void (*dtor) (Void *);// Object-destructor (not for C++, yet)
unsigned long allocatedObjects;// No. of object that are in usage
unsigned long freeCount;// No. of objects that are free in current pool
unsigned long callCount;// No. of operation done on this type (not used)
Slab *emptySlab;// Cache for a empty slab
CircularList partialList;// List of partial slabs
CircularList fullList;// List of complete slabs
Spinlock lock;// Serialization lock
};
Objects must be atleast 2 words large on the machine. This is because the allocator stores linked-list nodes at the starting of each buffer in the slab. To do so atleast 2 words are required. The first object is linked to the slab descriptor by the Slab::bufferStack
field.
A object can be aligned in the allocator. For example, struct ObjectInfo
is always allocated at a 64 byte margin for better cache performance. The arena of memory whose size is aligned & can contain the object is the buffer. As 'sizeof(ObjectInfo)' is about 70-80 bytes the buffer-size will be 128-bytes.
Each object can be initialized by a special constructor functor. This must take only one argument - void *pointerToObject
. It is like the default constructor in C++. Whenever a slab is allocated, all objects are initialized, which removes the need to construct objects at allocation time again and again. This assumes that the objects are returned to KDelete
function in the original initialized state.
Whenever a slab is destroyed & unmapped, the destructor for all objects are called as to release resources. The constructor or destructor may also be NULL to specify no special requirement of initialization or finalization.
Note, that C++ constructors & destructors ARE NOT included in this. So that way C structs would be much better for critical code & memory-intensive operations.
The allocator maintains two lists of slabs - partial & full. In the partial list, only those slabs which have free objects in their bufferStack
are kept. In the full list, only those slabs which are fully occupied are kept. The allocator also maintains a cache for a empty slab, which is totally free. Only one free slab is kept in cache and all others are destroyed.
Coloring - The allocator also shifts objects (like in Linux kernel) and maintains a `colorScheme' field.