// SPDX-License-Identifier: MPL-2.0 // This is the implementation for the slab allocator for generic sizes #ifndef SH_LIB_SLAB_GENERIC_H #define SH_LIB_SLAB_GENERIC_H #include "memory/page.h" #include "std/status.h" #include "std/type.h" #include "memory/pba.h" #define SH_SLAB_GENERIC_SLAB_DATA_PAGES {1,2,4,8,16,32,64,128} #define SH_SLAB_GENERIC_OBJECT_SIZE_BYTES {8,16,32,64,128,256,512,1024} #define SH_SLAB_GENERIC_OBJECTS_PER_SLAB 512 #define SH_SLAB_GENERIC_ACTUAL_OBJECTS_PER_SLAB {496,504,508,510,511,511,511,511} #define SH_SLAB_GENERIC_SLAB_BITMAP_INIT {0xFFFF,0xFF,0xF,0x3,1,1,1,1} #define SH_SLAB_GENERIC_SLAB_BITMAP_SIZE_BYTES 64 #define SH_SLAB_GENERIC_NULL_REF (sh_uint64)0 #define SH_SLAB_GENERIC_SLAB_SIG {'S','h','S','l','G','e','n','e'} #define SH_SLAB_GENERIC_MAGIC 0x656E65476C536853ULL // little endian // Generic slab structure #pragma pack(1) typedef struct sh_slab_generic_SLAB { sh_uint8 sig[8]; sh_uint16 used_count; sh_uint64 slab_index; struct sh_slab_generic_SLAB* next_slab; struct sh_slab_generic_SLAB* prev_slab; struct sh_slab_generic_SLAB* next_partial; struct sh_slab_generic_SLAB* prev_partial; sh_uint8 padding[14]; sh_uint64 free_bitmap[SH_SLAB_GENERIC_SLAB_BITMAP_SIZE_BYTES/8]; // First objects will be mark as unavailable due to being replaced by the header and bitmap, their amount depend on the object size } sh_slab_generic_SLAB; #pragma pack() // Radix node slab allocator structure struct sh_slab_generic_SLAB_ALLOCATOR { sh_slab_generic_SLAB* first_slab; sh_slab_generic_SLAB* partial_head; sh_uint64 level; sh_uint64 slab_count; sh_uint64 object_size_bytes; sh_uint64 object_per_slab; sh_uint64 actual_object_per_slab; sh_uint64 bitmap_init; sh_uint64 slab_pages_count; sh_pba_PAGE_BLOCK_ALLOCATOR* pba; }; typedef sh_uint16 sh_slab_generic_OBJECT_INDEX_IN_SLAB; // Initialize slab allocator structure. Does not allocate any slab SH_STATUS sh_slab_generic_alloc_init(sh_uint8 level,struct sh_slab_generic_SLAB_ALLOCATOR* slab_alloc,sh_pba_PAGE_BLOCK_ALLOCATOR *pba); // Allocate a new slab, initialize it and put it into the allocator. If new slab isn't the first to be allocated, push it on the partial slab list SH_STATUS sh_slab_generic_add_slab(struct sh_slab_generic_SLAB_ALLOCATOR* alloc,sh_page_PAGE_TABLE_POOL *ptp,sh_slab_generic_SLAB** out_slab); // Obtain a pointer to the first partial slab. Does not scan the slabs. Allocate a new slab if necessary SH_STATUS sh_slab_generic_get_partial_slab(struct sh_slab_generic_SLAB_ALLOCATOR* alloc,sh_page_PAGE_TABLE_POOL* ptp,sh_slab_generic_SLAB** found_slab); // Rescan all the slabs to rebuild partial list in case of doubt. Does not modify alloc->slab_count, any slab->free_bitmap or any slab>->nodes SH_STATUS sh_slab_generic_scan_slabs(struct sh_slab_generic_SLAB_ALLOCATOR* alloc); // Return a valid pointer to an empty object slot as well as the object index in the corresponding index. Slabs allocation is automated by sh_slab_generic_get_partial_slab SH_STATUS sh_slab_generic_find_free_object(struct sh_slab_generic_SLAB_ALLOCATOR* alloc,sh_page_PAGE_TABLE_POOL *ptp,void** out,sh_slab_generic_OBJECT_INDEX_IN_SLAB* index_in_slab); // Allocate one new object. Return a pointer to the struct of the new object. Since it call sh_slab_generic_find_free_object, it can allocate new slab SH_STATUS sh_slab_generic_alloc(struct sh_slab_generic_SLAB_ALLOCATOR* alloc,sh_page_PAGE_TABLE_POOL *ptp,void** out_obj); // Dellocate one radix node object provided as pointer. SH_STATUS sh_slab_generic_dealloc(struct sh_slab_generic_SLAB_ALLOCATOR* alloc,void *object_ptr); #endif