Add slot allocator

This commit is contained in:
Nils O. Selåsdal
2025-07-21 19:57:26 +02:00
parent 7408c48dff
commit 251246924d
6 changed files with 188 additions and 12 deletions
+1 -1
View File
@@ -27,7 +27,7 @@ struct UCBitVec {
* Use as
* @code
* uc_bv_integer v[10];
* struct UCBitVec v = BITVEC_STATIC_INIT(v);
* struct UCBitVec v = UC_BV_STATIC_INIT(v);
* @endcode
*/
#define UC_BV_STATIC_INIT(vec_data)\
+112
View File
@@ -0,0 +1,112 @@
#ifndef UC_SLOT_ALLOCATOR_H_
#define UC_SLOT_ALLOCATOR_H_
#include <stddef.h>
#include <stdint.h>
#include "ucore/bitvec.h"
#ifdef __cplusplus
extern "C" {
#endif
/** @file
* Fixed size slot memory allocator
*
* UCSlotAlloc is used to allocate fixed slots of memory from a pre-allocated
* piece of memory.
*
* The main use case is to keep allocated memory in a contiguous block for use
* maximum number of objects(slots) is known and relatively small. More than 131072 slots
* is not recommended.
*
* Note that this allocator is not thread safe.
*
* A bitmap is used to track which slots are allocated.
*/
typedef struct UCSlotAlloc UCSlotAlloc;
struct UCSlotAlloc {
const uint32_t slot_size;
const uint32_t num_slots;
struct UCBitVec bitmap;
uint8_t *slots;
};
/** Initialize a UCSlotAlloc with an array as the backing memory to allocate slots from.
* The macro can be used at local scope to allocate memory automatic (stack) storage,
* or at global scope where the backin array will have static storage duration
*
* Use as:
* @code
* UC_SLOT_ALLOC_DEF(my_allocator, sizeof foo, 1024)
* struct foo *foo = uc_slot_alloc(&my_allocator);
* if (foo == NULL) {
* // out of memory
* } else {
* .. use foo
* uc_slot_free(&my_allocator, foo);
* }
* @endcode
*
* @param var_name Variable name for the allocator
* @param v slot_size Memory size allocated for each slot
* @param v num_slots Number of slots to reserve memory for
*/
#define UC_SLOT_ALLOC_DEF(var_name, slot_size_, num_slots_) \
struct {\
uc_bv_integer bitmap[UC_BV_LEN(num_slots_)]; \
uint8_t memory[num_slots_ * slot_size_] __attribute__((aligned)); \
} var_name ## _memory = { \
}; \
UCSlotAlloc var_name = { \
.slot_size = slot_size_, \
.num_slots = num_slots_, \
.bitmap = UC_BV_STATIC_INIT(var_name ## _memory.bitmap), \
.slots = var_name ## _memory.memory \
};
/** Similar to UC_SLOT_ALLOC_DEF but allows you to specify the backing memory that must
* be atleast as large as num_slots * slot_size. Note that an array of num_slots * slot_size
* bits is also allocated for the bitmap with this definition
*/
#define UC_SLOT_ALLOC_DEF_EX(var_name, slot_size_, num_slots_, memory) \
uc_bv_integer var_name ## _bitmap[UC_BV_LEN(num_slots_)] = {}; \
UCSlotAlloc var_name = { \
.slot_size = slot_size_, \
.num_slots = num_slots_, \
.bitmap = UC_BV_STATIC_INIT(var_name ## _bitmap), \
.slots = memory \
};
/** Allocate a memory slot
*
* @param sa The allocator to allocate from
* @return A pointer to the memory slot that's sa.slot_size big, or NULL if
* all slots are allocated
*/
void *uc_slot_alloc(UCSlotAlloc *sa);
/** Free a memory slot previously returned from uc_slot_alloc()
*
* @param sa The allocator to free from.
* @param slot The memory slot to free. Passing a NULL pointer is undefined behavior
*/
void uc_slot_free(UCSlotAlloc *restrict sa, void *restrict slot);
/** uc_slot_free() where the slot can be a NULL pointer */
#define uc_slot_free_safe(sa, slot) \
do { \
if (slot != NULL) { \
uc_slot_free(sa, slot); \
} \
} while (0)
#ifdef __cplusplus
}
#endif
#endif
+4 -4
View File
@@ -30,7 +30,7 @@
// int i;
// struct bar zap;
//};
// ...
// ...
//struct bar *p = ..; //the local p is a pointer to
//a 'zap' member inside a struct foo.
//give us the struct foo*:
@@ -55,7 +55,7 @@ const typeof( ((const type *)0)->member ) *__mptr = (ptr); \
/**
* Test if x is a power of 2
*
*
* @param x value, must be an unsigned type
* @return 1 if x is a power of 20, 0 if it is not
*/
@@ -90,7 +90,7 @@ const typeof( ((const type *)0)->member ) *__mptr = (ptr); \
*
* @param x numerator, must be positive
* @param y denominator
* @return x/y rounded up
* @return x/y rounded up
*/
#define UC_DIV_ROUND_UP(x, y) (((x) + ((y) - 1))/(y))
@@ -103,7 +103,7 @@ const typeof( ((const type *)0)->member ) *__mptr = (ptr); \
* @param y denominator
* @return x rounded up to nearest multiple of y
*/
#define UC_ROUND_UP(x, y) (UC_DIV_ROUND_UP((x), (y)) * (y))
#define UC_ROUND_UP(x, y) (UC_DIV_ROUND_UP((x), (y)) * (y))
/**
* Round x down to nearest multiple of y