SuperTinyKernel™ RTOS 1.06.0
Lightweight, high-performance, deterministic, bare-metal C++ RTOS for resource-constrained embedded systems. MIT Open Source License.
Loading...
Searching...
No Matches
BlockMemoryPool Class Reference

Fixed-size block allocator with O(1) alloc/free and proper task-blocking semantics. More...

#include <stk_memory_blockpool.h>

Detailed Description

Fixed-size block allocator with O(1) alloc/free and proper task-blocking semantics.

BlockMemoryPool provides a deterministic, fragmentation-free allocator for scenarios where the same block size is repeatedly allocated and released - such as packet buffers, sensor sample records, or task-local state objects.

The pool uses an intrusive singly-linked free-list inside the storage array. When a block is free, its first sizeof(void*) bytes hold a pointer to the next free block; no separate metadata array is needed. Alloc and Free are therefore O(1) with a minimal critical section.

Memory layout (pool storage, contiguous):

[ block_0 | block_1 | ... | block_{n-1} ]
^                                       ^
m_storage                         (m_storage + n * m_block_size)

At construction all blocks are chained: block_i->next = block_{i+1},
last->next = nullptr. m_free_list points to block_0.

Two storage modes** mirror the CMSIS osMemoryPoolAttr_t mp_mem / mp_size fields and allow fully static (zero-heap) deployments:

Mode Constructor Frees storage?
External storage BlockMemoryPool(cap, blksz, buf, bufsz [, name]) No - caller
Heap storage BlockMemoryPool(cap, blksz [, name]) Yes - dtor

Blocking semantics**: TimedAlloc() suspends the calling task via a ConditionVariable until Free() returns a block, or the timeout expires. This replaces the spin-yield polling loop that was used in the old CMSIS wrapper, giving up the CPU completely while blocked instead of burning cycles.

ISR safety**: TryAlloc() and Free() are ISR-safe (guarded by a critical section). Alloc() and TimedAlloc() with a non-zero timeout must only be called from task context.

// --------------------------------------------------------------------&mdash;
// Example 1 - native STK usage with zero-heap external storage
// --------------------------------------------------------------------&mdash;
static const uint32_t PKT_COUNT = 8U;
static const uint32_t PKT_SIZE = sizeof(Packet);
alignas(sizeof(void *)) static uint8_t
g_PktStorage[PKT_COUNT * stk::memory::BlockMemoryPool::AlignBlockSize(PKT_SIZE)];
stk::memory::BlockMemoryPool g_PktPool(PKT_COUNT, PKT_SIZE,
g_PktStorage, sizeof(g_PktStorage));
void ISR_Receiver() {
void *blk = g_PktPool.TryAlloc(); // ISR-safe, non-blocking
if (blk) {
FillPacket(static_cast<Packet *>(blk));
g_ParseQueue.Write(blk, NO_WAIT);
}
}
void Task_Parser() {
void *blk = nullptr;
if (g_ParseQueue.Read(blk)) {
Parse(static_cast<Packet *>(blk));
g_PktPool.Free(blk); // O(1), wakes one blocked allocator
}
}
\see sync::ConditionVariable, sync::Semaphore, sync::Pipe
\note Blocking alloc paths require the kernel to be compiled with \a KERNEL_SYNC.
\c TryAlloc() and \c Free() are always available regardless of kernel mode.
*/
class BlockMemoryPool : public ITraceable
{
public:

The documentation for this class was generated from the following file: