Memory Management
VAIOS provides a lightweight dynamic memory management system to support task creation and system services. The allocator is designed with simplicity, safety, and low overhead in mind, making it suitable for embedded environments where memory resources are limited and predictable behavior is important.
The heap is initialized as a contiguous memory region and managed as a sequence of variable-sized blocks. Each allocated region is preceded by a metadata header that stores information such as block size, allocation status, and a sanity check value. This structure allows the allocator to track memory usage and detect errors such as invalid frees or heap corruption.
Memory allocation follows a linear first-fit strategy. The allocator scans the heap to find a suitable free block or an uninitialized region that can satisfy the requested size. Allocated blocks are aligned to ensure proper access on the target architecture. When a free block is larger than required, it is split into two blocks, allowing efficient utilization of memory.
Deallocation marks a block as free and attempts to merge it with adjacent free blocks to reduce fragmentation. Both forward and backward coalescing are performed when possible, helping to maintain larger contiguous memory regions over time. This approach balances simplicity with basic fragmentation control without introducing complex data structures.
To ensure correctness in a concurrent environment, all allocation and deallocation operations are protected using critical sections. This guarantees thread safety while keeping the implementation straightforward. Additional safety mechanisms include sanity checks using magic values, detection of double frees, and validation of pointer boundaries within the heap.
VAIOS also incorporates runtime monitoring features such as allocation counters and total allocated size tracking. A configurable heap watermark mechanism is used to detect low-memory conditions and trigger a system panic if predefined thresholds are exceeded. This provides an additional layer of protection in safety-critical applications.
Memory allocation is primarily used for task stacks and control structures, while the overall system behavior remains largely predictable due to controlled usage patterns. The design avoids overly complex allocation schemes, prioritizing reliability and transparency over constant-time allocation guarantees.