// SPDX-License-Identifier: MPL-2.0 // This is the implementation for the slab allocator for sh_pez_REGION_VIRTUAL_OBJECT #ifndef SH_LIB_SLAB_REG_VIRT_H #define SH_LIB_SLAB_REG_VIRT_H #include "std/type.h" #include "std/status.h" #include "memory/page.h" #include "memory/vmem_layout.h" #define SH_SLAB_REG_VIRT_DATA_VA SH_VMEM_LAYOUT_SLAB_REG_VIRT_VA #define SH_SLAB_REG_VIRT_MAX_SLAB (sh_uint64)(512*1024) #define SH_SLAB_REG_VIRT_SLAB_DATA_PAGES (sh_uint64)3 #define SH_SLAB_REG_VIRT_SLAB_DATA_SIZE_BYTES (sh_uint64)(SH_SLAB_REG_VIRT_SLAB_DATA_PAGES*4096) #define SH_SLAB_REG_VIRT_OBJECT_SIZE_BYTES (sh_uint64)12 #define SH_SLAB_REG_VIRT_OBJECTS_PER_SLAB (sh_uint64)1024 #define SH_SLAB_REG_VIRT_ACTUAL_OBJECTS_PER_SLAB (sh_uint64)1023 #define SH_SLAB_REG_VIRT_SLAB_BITMAP_SIZE_BYTES (sh_uint64)(SH_SLAB_REG_VIRT_OBJECTS_PER_SLAB/8) #define SH_SLAB_REG_VIRT_NULL_REF (sh_uint64)0 // Virtual region slab structure typedef struct sh_slab_reg_virt_SLAB_STRUCT { sh_uint16 used_count; sh_uint32 slab_index; struct sh_slab_reg_virt_SLAB_STRUCT* next; struct sh_slab_reg_virt_SLAB_STRUCT* prev; sh_uint64 free_bitmap[16]; } sh_slab_reg_virt_SLAB_STRUCT; #define SH_SLAB_REG_VIRT_HEADER_LIST_SIZE_BYTES SH_SLAB_REG_VIRT_MAX_SLAB*sizeof(sh_slab_reg_virt_SLAB_STRUCT) // Virtual region object slab allocator structure typedef struct { sh_slab_reg_virt_SLAB_STRUCT* slabs_header; sh_uint8* slabs_data; sh_uint32 max_slabs; sh_uint32 slab_count; sh_slab_reg_virt_SLAB_STRUCT* partial_head; } sh_slab_reg_virt_SLAB_ALLOCATOR; typedef sh_uint32 sh_slab_reg_virt_OBJECT_INDEX; // Return slab index #define SH_SLAB_REG_VIRT_REF_SLAB(ref) (sh_uint32)((ref)>>10) // Return object index inside a slab #define SH_SLAB_REG_VIRT_REF_OBJECT(ref) (sh_uint16)((ref) & 0x3FF) // Make a valid object index from a slab index and an object index inside this slab #define SH_SLAB_REG_VIRT_MAKE_REF(slab,obj) (((sh_slab_reg_virt_OBJECT_INDEX)(slab)<<10) | (sh_slab_reg_virt_OBJECT_INDEX)(obj)) // Initialize slab allocator structure. Does not allocate any slabs SH_STATUS sh_slab_reg_virt_alloc_init(sh_slab_reg_virt_SLAB_ALLOCATOR* slab_alloc,sh_page_PAGE_TABLE_POOL *ptp); // 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_reg_virt_add_slab(sh_slab_reg_virt_SLAB_ALLOCATOR* alloc,sh_page_PAGE_TABLE_POOL *ptp,sh_slab_reg_virt_SLAB_STRUCT** 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_reg_virt_get_partial_slab(sh_slab_reg_virt_SLAB_ALLOCATOR* alloc,sh_page_PAGE_TABLE_POOL* ptp,sh_slab_reg_virt_SLAB_STRUCT** found_slab); // Rescan all the slabs to set all metadatas in case of doubt. Does not modify alloc->slab_count, alloc->slabs_data SH_STATUS sh_slab_reg_virt_scan_slabs(sh_slab_reg_virt_SLAB_ALLOCATOR* alloc); // Return a valid 29 bits index to a empty object slot. Slabs allocation is automated by sh_slab_reg_virt_get_partial_slab SH_STATUS sh_slab_reg_virt_find_free_object(sh_slab_reg_virt_SLAB_ALLOCATOR* alloc,sh_page_PAGE_TABLE_POOL *ptp,sh_slab_reg_virt_OBJECT_INDEX* out_ref); // Return a pointer to referenced virtual region object void* sh_slab_reg_virt_ref_to_ptr(sh_slab_reg_virt_SLAB_ALLOCATOR* alloc,sh_slab_reg_virt_OBJECT_INDEX ref); // Allocate one new virtual region object. Return both a pointer to the struct of the new object and an index to access and deallocte the object. Since it call sh_slab_reg_virt_find_free_object, it can allocate new slab SH_STATUS sh_slab_reg_virt_alloc(sh_slab_reg_virt_SLAB_ALLOCATOR* alloc,sh_page_PAGE_TABLE_POOL *ptp,sh_slab_reg_virt_OBJECT_INDEX* out_index); // Dellocate one virtual region object provided as index. SH_STATUS sh_slab_reg_virt_dealloc(sh_slab_reg_virt_SLAB_ALLOCATOR* alloc,sh_slab_reg_virt_OBJECT_INDEX index); #endif