|
LibJuno 1.0.1
LibJuno is a lightweight C11 library designed specifically for embedded systems.
|
Deterministic, static, block-based memory management for embedded systems. This module avoids dynamic allocation and favors predictable behavior and explicit error paths.
This document reflects the current APIs in juno/memory/memory_api.h, juno/memory/pointer_api.h, and juno/memory/memory_block.h and matches the unit tests in tests/test_memory.c.
The memory module provides a fixed-size block allocator. You supply:
The allocator exposes an API vtable with Get/Update/Put. Get returns a result containing both a status and a pointer payload.
The module integrates with LibJuno's module system:
JUNO_POINTER_T uses JUNO_TRAIT_ROOT to carry its API pointerJUNO_MEMORY_ALLOC_ROOT_T uses JUNO_MODULE_ROOT with both the allocator API and pointer APIJUNO_MEMORY_ALLOC_BLOCK_T uses JUNO_MODULE_DERIVE to extend the root with implementation fieldsNo reference counting is implemented in the current design.
Per-block metadata used by the allocator's free list. This is a simple public struct (currently contains a uint8_t *ptFreeMem field) used internally by the allocator. Treat it as allocator-managed storage: declare arrays with JUNO_MEMORY_BLOCK_METADATA(...) but avoid reading/modifying fields directly. The layout may evolve; consumers should not rely on specific members.
Describes a block of memory the allocator returned (defined in pointer_api.h):
void *pvAddr; — block addresssize_t zSize; — block size in bytessize_t zAlignment; — required alignment for the blockconst JUNO_POINTER_API_T *ptApi; — pointer to the API (via JUNO_TRAIT_ROOT macro)Functions that the allocator calls per element type (defined in pointer_api.h):
JUNO_STATUS_T (*Copy)(JUNO_POINTER_T tDest, const JUNO_POINTER_T tSrc); — copy from source to destinationJUNO_STATUS_T (*Reset)(JUNO_POINTER_T tPointer); — reset/zero-initialize the memoryAllocator vtable:
JUNO_RESULT_POINTER_T (*Get)(JUNO_MEMORY_ALLOC_ROOT_T *ptMem, size_t zSize); — allocate a blockJUNO_STATUS_T (*Update)(JUNO_MEMORY_ALLOC_ROOT_T *ptMem, JUNO_POINTER_T *ptMemory, size_t zNewSize); — update block sizeJUNO_STATUS_T (*Put)(JUNO_MEMORY_ALLOC_ROOT_T *ptMem, JUNO_POINTER_T *ptMemory); — free a blockThe concrete block allocator type is JUNO_MEMORY_ALLOC_BLOCK_T (derived via JUNO_MODULE_DERIVE). It contains:
tRoot member of type JUNO_MEMORY_ALLOC_ROOT_T carrying the API pointer and pointer APIpvMemory — pointer to the allocated memory area (uint8_t*)ptMetadata — array of metadata for each blockzTypeSize — size of each block elementzAlignment — required alignmentzLength — total number of blocks availablezUsed — current count of allocated blocks (monotonically increases)zFreed — current count of freed blocks in the free stackExtended pointer types with value semantics (defined in pointer_api.h):
JUNO_VALUE_POINTER_T derives from JUNO_POINTER_TJUNO_VALUE_POINTER_API_T adds Equals comparison operationUse the provided macros to declare storage:
These create:
static MY_TYPE_T myBlock[10];static JUNO_MEMORY_BLOCK_METADATA_T myMeta[10];You must provide a JUNO_POINTER_API_T for your element type. For trivially copyable POD structs, Copy can assign and Reset can zero or reinitialize.
JunoMemory_PointerVerifyType(pointer, TYPE, tApi) — validates size, alignment, and API matchingJunoMemory_PointerInit(api, TYPE, addr) — constructs a typed pointer descriptor (rarely needed by users)JUNO_ASSERT_POINTER_COPY(tDest, tSrc, tApi) — validates preconditions for copy operationsJunoMemory_PointerApiVerify(ptPointerApi) — verifies a pointer API vtable is completeJunoMemory_PointerVerify(tPointer) — verifies a pointer structure is validJunoMemory_AllocApiVerify(ptAllocApi) — verifies an allocator API vtable is completeJunoMemory_AllocVerify(ptAlloc) — verifies an allocator root structure is validSignature (from memory_block.h):
Usage:
Notes:
ptPointerApi and zAlignment are required and validated.pvMemory must be aligned to zAlignment.Obtain the allocator API via the root member (tRoot), then call through it. Get returns a result struct; check tStatus before using tOk.
memory_block.h provides small wrappers:
The block allocator maintains:
zUsed: Total number of blocks ever allocated (monotonically increases until pool is full)zFreed: Count of freed blocks available for reuse (decreases on Get, increases on Put)ptMetadata array as a stack (LIFO order)Allocation strategy:
zFreed > 0), reuse the most recently freed blockzUsed < zLength), allocate a new block from the poolJUNO_STATUS_MEMALLOC_ERRORThe allocator automatically calls Reset on newly allocated blocks. If Reset fails, the block is returned to the free list and the error is propagated.
tStatus on results from Get; don't use tOk unless success.zTypeSize).JUNO_STATUS_MEMFREE_ERROR.Put is rejected.pvMemory is correctly aligned; pass alignof(TYPE) at init.Put, the pointer's pvAddr is set to NULL, zSize and zAlignment are zeroed.JunoMemory_PointerVerifyType macro now requires three arguments: (pointer, TYPE, tApi).Copy function signature takes const JUNO_POINTER_T tSrc (const second parameter).Reset operation fails during Get, the block is returned to the free list automatically.The module is suitable for freestanding builds. Avoid hosted headers in your Copy/Reset implementations; prefer simple assignment/zeroing for POD types. In freestanding mode, enable the CMake option -DJUNO_FREESTANDING=ON and ensure your pvMemory buffer is properly aligned for the element type.
The memory module reports errors through status codes of type JUNO_STATUS_T:
JUNO_STATUS_SUCCESS: Operation completed successfullyJUNO_STATUS_MEMALLOC_ERROR: Failed to allocate memory (block is full or size exceeds element size)JUNO_STATUS_MEMFREE_ERROR: Failed to free memory (invalid address, double free, or unaligned address)JUNO_STATUS_NULLPTR_ERROR: Null pointer provided to function (handled by JUNO_ASSERT_EXISTS)JUNO_STATUS_INVALID_TYPE_ERROR: Invalid memory allocator type (API mismatch)JUNO_STATUS_INVALID_SIZE_ERROR: Invalid size parameter (e.g., zero size)JUNO_STATUS_ERR: General error (e.g., corrupt allocator counters, alignment issues, overflow)JunoMemory_BlockGetT and JunoMemory_BlockPutT to reduce size mismatches.JunoMemory_PointerVerifyType in Copy/Reset, forward declare the API constant.Reference counting is planned but not implemented in the current allocator. The macros JUNO_REF and JUNO_NEW_REF are reserved for a future reference-counting extension and should not be used yet. Status codes such as JUNO_STATUS_INVALID_REF_ERROR and JUNO_STATUS_REF_IN_USE_ERROR are defined globally but are not produced by the block allocator at this time.