Files
libucore/include/ucore/slot_allocator.h
T
Nils O. Selåsdal d85735add9 Simple slot allocator
2026-04-20 23:36:55 +02:00

80 lines
2.2 KiB
C

#ifndef UC_SLOT_ALLOCATOR_H_
#define UC_SLOT_ALLOCATOR_H_
#include <stddef.h>
#include <stdint.h>
#include <assert.h>
// Repurpose free memory to eep a linked list of free slots
typedef struct UCSlot UCSlot;
struct UCSlot {
UCSlot *next;
};
typedef struct UCSlotArena UCSlotArena;
struct UCSlotArena {
UCSlot *free_list;
uint8_t *memory_start;
size_t memory_len;
size_t n_slots;
size_t slot_size;
};
/**
* Initialize a memory arena for dynamically allocating slots of memory.
* Each allocation returns memory slots of the same size
* Note: For max speed, align @memory and @slot_size to the size of a pointer
*
* @param arena arena to initialize
* @param memory start of the backing memory
* @param memory_len length of @memory
* @param slot_size size of each slot allocation
*/
static inline void uc_slot_arena_init(UCSlotArena *arena, void *memory, size_t memory_len, size_t slot_size)
{
// Optionally - align to a pointer
//slot_size = (slot_size + _Alignof(UCSlot) - 1) & (~(_Alignof(UCSlot) - 1));
assert(slot_size >= sizeof(UCSlot));
size_t n_slots = memory_len / slot_size;
arena->free_list = NULL;
uint8_t *start = (uint8_t *)memory;
// build free_list in ascending order, anticipating sequential allocation
// and sequential access as the common case
for (size_t slot = n_slots; slot > 0; slot--) {
size_t index = slot - 1;
UCSlot *free_slot = (UCSlot *)(start + index * slot_size);
free_slot->next = arena->free_list;
arena->free_list = free_slot;
}
arena->n_slots = n_slots;
arena->memory_start = (uint8_t*)memory;
arena->memory_len = memory_len;
arena->slot_size = slot_size;
}
static inline void *uc_slot_alloc(UCSlotArena *arena)
{
UCSlot *slot = arena->free_list;
if (slot != NULL) {
arena->free_list = slot->next;
}
return slot;
}
static inline void uc_slot_free(UCSlotArena *arena, void *mem)
{
if (mem != NULL) {
assert((uint8_t *)mem >= arena->memory_start);
assert((uint8_t *)mem < arena->memory_start + arena->memory_len);
UCSlot *slot = (UCSlot *)mem;
slot->next = arena->free_list;
arena->free_list = slot;
}
}
#endif