In this implementation we only allow small caches (i.e. objects must be smaller than EG_SLAB_LIMIT), with buffer controls and slab structures stored within a unique memory page. We could allow in the future for more flexible slabs. This implementation also uses colored slabs (see the paper for further details).
Here we can see a schematic drawing of the slab allocator structure and functions:
Files | |
| file | eg_memslab.ex.c |
| file | eg_memslab.h |
Data Structures | |
| struct | EGmemSlab_t |
| structure that holds the information relevant to each slab More... | |
| struct | EGmemSlabPool_t |
| structure used to store a slab memory pool More... | |
Defines | |
| #define | _EGmemSlabPoolInitProfile(_EGmPl, sz) |
| Initialize the profiling data of a slab pool. | |
| #define | _EGmemSlabPoolProfile(_EGmPl) |
| show profile information after clearing a pool. | |
| #define | _XOPEN_SOURCE 600 |
| #define | EG_SLAB_BFCNTL_SIZE sizeof(char*) |
| size of the buffer manager, this size should be memory aligned, it is used to compute the actual pointer to the object. | |
| #define | EG_SLAB_DEBUG 0 |
| local debug level for the slab allocator, the lower the level, the more testing will be done. | |
| #define | EG_SLAB_LIMIT 1023U |
| maximum size of the objects that can be allocated via slab. | |
| #define | EG_SLAB_MASK (~0x0fffU) |
| mask to detect the position of a piece of memory within a slab | |
| #define | EG_SLAB_PAGE(ptr) (((size_t)ptr)&EG_SLAB_MASK) |
| Given a pointer, return a pointer to the beginning of the containing page. | |
| #define | EG_SLAB_POISON (0xdeadbeef) |
| address used to check consistency if enabled | |
| #define | EG_SLAB_PROFILE 100 |
| if set to one, enable profiling for the slab allocator | |
| #define | EG_SLAB_REDUCE_TO_MALLOC 0 |
| if set to one, reduce the slab pool allocator to a simple malloc call | |
| #define | EG_SLAB_SIZE 0x1000U |
| size of the memory slabs (in bytes ) | |
| #define | EG_SLAB_VERBOSE 100 |
| local verbose level for the slab allocator, the lower the level, the more information will be printed on screen. | |
| #define | EGmemSlabCheck(_EGmSlb) |
| given a pointer to a zone within a slab, check if the slab is OK. If not, then the program will exit execution with a message. Note that this test is performed only when we are debugging. | |
| #define | EGmemSlabClear(slab) |
| given an initialized slab, clear all internally allocated memory, and leave the slab ready to be freed by 'free', this include calling the destructor for all elements in the slab. | |
| #define | EGmemSlabGetSlab(ptr) ((EGmemSlab_t*)(EG_SLAB_PAGE(ptr) + EG_SLAB_SIZE - EG_MEM_ALIGN(sizeof(EGmemSlab_t)))) |
| given a piece of memory that should be within a slab, return the pointer to the related slab structure, remember that the slab structure is at the end of the slab piece of memory. | |
| #define | EGmemSlabInit(slab, Pool, Color) |
| initialize a slab structure. This include calling the constructor for all elements in the slab. Note that this function asumes that all memory has been previously set to NULL. It will also place this slab in the list of empty slabs in the given pool. | |
| #define | EGmemSlabPoolAlloc(Pool) |
| Given a slab pool, return an element from the pool. | |
| #define | EGmemSlabPoolClear(Pool) |
| clear a slab pool and all internal sub-structures and data, no further calls to this structure are posible after this (but for freeing the memory containing this data, or to re-initialize it). | |
| #define | EGmemSlabPoolFree(ptr) EGmemSlabPushElement(ptr) |
| Given a pointer to an element allocated through a slab pool, give it back to the pool. | |
| #define | EGmemSlabPoolInit(pool, sz, constr_fn, dest_fn) |
| initialize a slab pool as an empty pool for elements of the given size, and with te given constructor and destructors. | |
| #define | EGmemSlabPoolShrink(Pool) |
| Given a slab pool, free all unused slabs. | |
| #define | EGmemSlabPopElement(slab) |
| Given a non-full slab, extract a pointer to the next unused element in the slab, and update all internal data. and if it becomes full, then move it to the full list within the pool. Also, if debugging, poison the pointer to the enext element in the returned element. If the slab is not full, and the number of active elements is one, then move the slab to the half-full slab list in the pool. | |
| #define | EGmemSlabPushElement(ptr) |
| Given an used object within a slab, give it back to the slab for future used. | |
| #define | EGSLB_UPDATE(a) |
| add one to the given pointer, if profiling is enabled, otherwise, do nothing | |
Typedefs | |
| typedef EGmemSlab_t | EGmemSlab_t |
| structure that holds the information relevant to each slab | |
| typedef EGmemSlabPool_t | EGmemSlabPool_t |
| structure used to store a slab memory pool | |
Functions | |
| int | main (int argc, char **argv) |
| this program expect only one parameter, the number of elements to be created. | |
| static void | my_constr (void *ptr) |
| static void | my_dest (void *ptr) |
| simple destructor for heap connectors | |
|
|
Initialize the profiling data of a slab pool.
Definition at line 346 of file eg_memslab.h. |
|
|
show profile information after clearing a pool.
Definition at line 402 of file eg_memslab.h. |
|
|
Definition at line 56 of file eg_memslab.h. |
|
|
size of the buffer manager, this size should be memory aligned, it is used to compute the actual pointer to the object.
Definition at line 91 of file eg_memslab.h. |
|
|
local debug level for the slab allocator, the lower the level, the more testing will be done.
Definition at line 101 of file eg_memslab.h. |
|
|
maximum size of the objects that can be allocated via slab.
Definition at line 70 of file eg_memslab.h. |
|
|
mask to detect the position of a piece of memory within a slab
Definition at line 78 of file eg_memslab.h. |
|
|
Given a pointer, return a pointer to the beginning of the containing page.
Definition at line 114 of file eg_memslab.h. |
|
|
address used to check consistency if enabled
Definition at line 82 of file eg_memslab.h. |
|
|
if set to one, enable profiling for the slab allocator
Definition at line 86 of file eg_memslab.h. |
|
|
if set to one, reduce the slab pool allocator to a simple malloc call
Definition at line 107 of file eg_memslab.h. |
|
|
size of the memory slabs (in bytes )
Definition at line 74 of file eg_memslab.h. |
|
|
local verbose level for the slab allocator, the lower the level, the more information will be printed on screen.
Definition at line 96 of file eg_memslab.h. |
|
|
Value: ({\
EXIT(_EGmSlb->flags,"Slab at %p has been cleared, and can't be used", \
(void*)EG_SLAB_PAGE(_EGmSlb));\
EXIT( _EGmSlb->next_elem == (char*)EG_SLAB_POISON , "Slab at %p is "\
"poisoned", (void*)EG_SLAB_PAGE(_EGmSlb));\
EXIT(!(_EGmSlb->pool) || _EGmSlb->pool == (EGmemSlabPool_t*)EG_SLAB_POISON ,\
"Slab at %p has no pool asociated with it", \
(void*)EG_SLAB_PAGE(_EGmSlb));\
0;})
Definition at line 229 of file eg_memslab.h. |
|
|
given an initialized slab, clear all internally allocated memory, and leave the slab ready to be freed by 'free', this include calling the destructor for all elements in the slab.
Definition at line 190 of file eg_memslab.h. |
|
|
given a piece of memory that should be within a slab, return the pointer to the related slab structure, remember that the slab structure is at the end of the slab piece of memory.
Definition at line 137 of file eg_memslab.h. |
|
|
Value: ({\
EGmemSlab_t*const _EGmSlb = EGmemSlabGetSlab(slab);\
const EGconstructor_f _EGconstr = (Pool)->constr;\
const size_t _EGesz = (Pool)->elem_sz;\
unsigned _EGnel = (EG_SLAB_SIZE - EG_MEM_ALIGN(sizeof(EGmemSlab_t)))/_EGesz;\
char* _EGcel = (char*)EG_SLAB_PAGE(_EGmSlb) + (Color);\
char** _EGcptr = 0;\
MESSAGE(EG_SLAB_VERBOSE,"Creating slab at %p with %u elements of effective"\
" size %zd and color %u", (void*)EG_SLAB_PAGE(_EGmSlb), _EGnel, \
_EGesz, (Color));\
_EGmSlb->n_used = 0;\
_EGmSlb->elem_sz = _EGesz;\
_EGmSlb->n_elem = _EGnel;\
_EGmSlb->flags = 0;\
_EGmSlb->color = (Color);\
_EGmSlb->next_elem = _EGcel;\
_EGmSlb->pool = (Pool);\
while(_EGnel--){\
/* call constructor for the element if provided */\
if(_EGconstr) _EGconstr(((void*)_EGcel));\
/* set the next pointer to the next element in the slab */\
_EGcptr = (char**)(_EGcel + _EGesz - EG_SLAB_BFCNTL_SIZE);\
_EGcel += _EGesz;\
*_EGcptr = _EGcel;}\
/* position the slab in the pool */\
EGeListAddAfter(&(_EGmSlb->slab_cn),&((Pool)->empty));\
/* set the next pointer of the last element in the slab to NULL */\
*_EGcptr = 0;})
Definition at line 152 of file eg_memslab.h. |
|
|
Value: ({\
EGmemSlabPool_t*const _EGmPl = (Pool);\
void* _EGSmbRf = 0;\
if(!EGeListIsEmpty(&(_EGmPl->half))) _EGSmbRf = _EGmPl->half.next;\
else{\
if(!EGeListIsEmpty(&(_EGmPl->empty))) _EGSmbRf = _EGmPl->empty.next;\
else{\
if(posix_memalign(&_EGSmbRf,EG_SLAB_SIZE,EG_SLAB_SIZE))\
EXIT(1,"posix_memalign falied");\
else{\
EGmemSlabInit(_EGSmbRf,_EGmPl,_EGmPl->c_color);\
_EGmPl->c_color += EG_MEM_ALIGNMENT;\
EGSLB_UPDATE(_EGmPl->n_slabs);\
if(_EGmPl->c_color > _EGmPl->max_color) _EGmPl->c_color = 0;}}}\
EGSLB_UPDATE(_EGmPl->n_tot);\
EGmemSlabPopElement(_EGSmbRf);})
Definition at line 459 of file eg_memslab.h. |
|
|
Value: ({\
EGmemSlabPool_t*const _EGmPl = (Pool);\
void* _EGptr;\
while(!EGeListIsEmpty(&(_EGmPl->half))){\
_EGptr = _EGmPl->half.next;\
EGmemSlabClear(_EGptr);\
free((void*)EG_SLAB_PAGE(_EGptr));}\
while(!EGeListIsEmpty(&(_EGmPl->empty))){\
_EGptr = _EGmPl->empty.next;\
EGmemSlabClear(_EGptr);\
free((void*)EG_SLAB_PAGE(_EGptr));}\
while(!EGeListIsEmpty(&(_EGmPl->full))){\
_EGptr = _EGmPl->full.next;\
EGmemSlabClear(_EGptr);\
free((void*)EG_SLAB_PAGE(_EGptr));}\
/* profile the pool if we are prpfiling */\
_EGmemSlabPoolProfile(_EGmPl);\
/* if we are debugging, then poison the pool */\
if(EG_SLAB_DEBUG <= DEBUG){\
_EGmPl->constr = 0;\
_EGmPl->dest = 0;\
_EGmPl->elem_sz = _EGmPl->n_elem = _EGmPl->c_color = \
_EGmPl->max_color = 0;}\
;})
Definition at line 411 of file eg_memslab.h. |
|
|
Given a pointer to an element allocated through a slab pool, give it back to the pool.
Definition at line 489 of file eg_memslab.h. |
|
|
Value: ({\
EGmemSlabPool_t*const _EGmPl = (pool);\
unsigned const _EGesz = EG_MEM_ALIGN(sz)+EG_MEM_ALIGN(EG_SLAB_BFCNTL_SIZE);\
unsigned const _EGnel = (EG_SLAB_SIZE - EG_MEM_ALIGN(sizeof(EGmemSlab_t))) \
/ _EGesz;\
/* check that the real element size is within bounds */\
EXIT(_EGesz > EG_SLAB_LIMIT, "element size (user %u, real %u) for slab is"\
" above limits %u", (sz), _EGesz, EG_SLAB_LIMIT);\
/* initialize the structure */\
EGeListInit(&(_EGmPl->half));\
EGeListInit(&(_EGmPl->empty));\
EGeListInit(&(_EGmPl->full));\
_EGmPl->constr = constr_fn;\
_EGmPl->dest = dest_fn;\
_EGmPl->elem_sz = _EGesz;\
_EGmPl->n_elem = _EGnel;\
_EGmPl->c_color = 0;\
_EGmPl->max_color = EG_SLAB_SIZE - EG_MEM_ALIGN(sizeof(EGmemSlab_t)) - \
(_EGnel*_EGesz);\
_EGmemSlabPoolInitProfile(_EGmPl,sz);\
/* verbose output */\
MESSAGE(EG_SLAB_VERBOSE,"Creating Slab Pool at %p:\n\tmax colors %u\n"\
"\telements per slab %u\n\tuser size %u\n\treal size %u\n", \
(void*)_EGmPl, _EGmPl->max_color, _EGnel, (sz), _EGesz);\
0;})
Definition at line 360 of file eg_memslab.h. |
|
|
Value: ({\
EGmemSlabPool_t*const _EGmPl = (Pool);\
void* _EGptr;\
while(!EGeListIsEmpty(&(_EGmPl->empty))){\
_EGptr = (void*)(_EGmPl->empty.next);\
EGmemSlabClear(_EGptr);\
free((void*)EG_SLAB_PAGE(_EGptr));}\
0;})
Definition at line 495 of file eg_memslab.h. |
|
|
Value: ({\
EGmemSlab_t*const _EGmSlb = EGmemSlabGetSlab(slab);\
EGmemSlabPool_t*const _EGPlRf = _EGmSlb->pool;\
void*const _EGelem = (void*)(_EGmSlb->next_elem);\
char** _EGnext_elem = (char**)(((char*)_EGelem) + _EGmSlb->elem_sz - \
EG_SLAB_BFCNTL_SIZE);\
/* some consistency checks */\
EGmemSlabCheck(_EGmSlb);\
EXITL(EG_SLAB_DEBUG, *_EGnext_elem == (char*)EG_SLAB_POISON, "Poisoned "\
"element");\
EXITL(EG_SLAB_DEBUG, _EGmSlb->n_used == _EGmSlb->n_elem, "Trying to get"\
" an element from slab at %p, but slab is full", \
(void*)EG_SLAB_PAGE(_EGmSlb));\
/* now update the slab */\
_EGmSlb->next_elem = *_EGnext_elem;\
_EGmSlb->n_used++;\
if(_EGmSlb->n_used == _EGmSlb->n_elem)\
EGeListMoveAfter(&(_EGmSlb->slab_cn),&(_EGPlRf->full));\
else if(_EGmSlb->n_used == 1U)\
EGeListMoveAfter(&(_EGmSlb->slab_cn),&(_EGPlRf->half));\
/* if debugging, poison the pointer to next in the returned element */\
if(EG_SLAB_DEBUG <= DEBUG) *_EGnext_elem = (char*)EG_SLAB_POISON;\
/* return the element */\
_EGelem;})
Definition at line 253 of file eg_memslab.h. |
|
|
Value: ({\
EGmemSlab_t*const _EGmSlb = EGmemSlabGetSlab(ptr);\
EGmemSlabPool_t*const _EGmPl = _EGmSlb->pool;\
void*const _EGelem = (void*)(ptr);\
char** _EGnext_elem = (char**)(((char*)_EGelem) + _EGmSlb->elem_sz - \
EG_SLAB_BFCNTL_SIZE);\
/* if debugging, check for poison in the pointer to the next element in the \
* given element */\
EXITL(EG_SLAB_DEBUG, !_EGelem, "Trying to free a NULL ptr");\
EGmemSlabCheck(_EGmSlb);\
EXITL(EG_SLAB_DEBUG, *_EGnext_elem != (char*)EG_SLAB_POISON, "This can't"\
" happen, memory %p is corrupted!", (void*)_EGelem);\
EXITL(EG_SLAB_DEBUG, !_EGmSlb->n_used, "Trying to free elements in an "\
"unused slab!");\
/* now, if the slab was full, put it as half-full */\
if(_EGmSlb->n_elem == _EGmSlb->n_used)\
EGeListMoveAfter(&(_EGmSlb->slab_cn),&(_EGmPl->half));\
/* decrease the number of used elements, and if zero, then move to the list\
* of empty slabs. */\
_EGmSlb->n_used -= 1;\
if(!(_EGmSlb->n_used))\
EGeListMoveAfter(&(_EGmSlb->slab_cn),&(_EGmPl->empty));\
/* now actually put the element into the slab */\
*_EGnext_elem = _EGmSlb->next_elem;\
_EGmSlb->next_elem = _EGelem;})
Definition at line 283 of file eg_memslab.h. |
|
|
add one to the given pointer, if profiling is enabled, otherwise, do nothing
Definition at line 442 of file eg_memslab.h. |
|
|
structure that holds the information relevant to each slab
|
|
|
structure used to store a slab memory pool
|
|
||||||||||||
|
this program expect only one parameter, the number of elements to be created.
Definition at line 46 of file eg_memslab.ex.c. Here is the call graph for this function: ![]() |
|
|
brief simple destructor for heap connectors
Definition at line 30 of file eg_memslab.ex.c. |
|
|
simple destructor for heap connectors
Definition at line 37 of file eg_memslab.ex.c. |
1.4.5