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
stk_c_memory.cpp
Go to the documentation of this file.
1/*
2 * SuperTinyKernel(TM) RTOS: Lightweight High-Performance Deterministic C++ RTOS for Embedded Systems.
3 *
4 * Source: https://github.com/SuperTinyKernel-RTOS
5 *
6 * Copyright (c) 2022-2026 Neutron Code Limited <stk@neutroncode.com>. All Rights Reserved.
7 * License: MIT License, see LICENSE for a full text.
8 */
9
10#include <cstddef> // for std::size_t
11
12#include <stk_config.h>
13#include <stk.h>
14#include <memory/stk_memory.h>
15
16#include "stk_c.h"
17#include "stk_c_memory.h"
18
19#ifndef _NEW
20inline void *operator new(std::size_t, void *ptr) noexcept { return ptr; }
21inline void operator delete(void *, void *) noexcept { /* nothing for placement delete */ }
22#endif
23
24using namespace stk;
25using namespace stk::memory;
26
27// ---------------------------------------------------------------------------
28// stk_blockpool_t — wraps a BlockMemoryPool instance
29//
30// The struct is opaque to C callers. Instances live in s_BlockPools[].
31// ---------------------------------------------------------------------------
32
34{
35 // Constructor forwarded to the external-storage BlockMemoryPool ctor.
36 stk_blockpool_t(size_t capacity, size_t raw_block_size,
37 uint8_t *storage, size_t storage_size, const char *name)
38 : handle(capacity, raw_block_size, storage, storage_size, name)
39 {}
40
41 // Constructor forwarded to the heap-storage BlockMemoryPool ctor.
42 stk_blockpool_t(size_t capacity, size_t raw_block_size, const char *name)
43 : handle(capacity, raw_block_size, name)
44 {}
45
47};
48
49// ---------------------------------------------------------------------------
50// Static pool of stk_blockpool_t slots
51// ---------------------------------------------------------------------------
52
53static struct BlockPoolSlot
54{
56 {}
57
58 stk_blockpool_t *pool() { return reinterpret_cast<stk_blockpool_t *>(storage); }
59 const stk_blockpool_t *pool() const { return reinterpret_cast<const stk_blockpool_t *>(storage); }
60
61 // Raw storage for placement-new, keeps the slot trivially constructible
62 // while letting BlockMemoryPool's own ctor/dtor run normally.
63 STK_STATIC_ASSERT_DESC(sizeof(stk_blockpool_t) % sizeof(Word) == 0, "stk_blockpool_t memory size must be multiple of Word");
64 Word storage[sizeof(stk_blockpool_t) / sizeof(Word)];
65 bool busy;
66}
68
69// ---------------------------------------------------------------------------
70// Internal helpers
71// ---------------------------------------------------------------------------
72
73// Find the slot that owns 'pool'; returns nullptr if not found.
75{
76 for (uint32_t i = 0; i < STK_C_BLOCKPOOL_MAX; ++i)
77 {
78 if (s_BlockPools[i].busy && (s_BlockPools[i].pool() == pool))
79 return &s_BlockPools[i];
80 }
81 return nullptr;
82}
83
84// Acquire a free slot; returns nullptr when the pool is exhausted.
86{
87 for (uint32_t i = 0; i < STK_C_BLOCKPOOL_MAX; ++i)
88 {
89 if (!s_BlockPools[i].busy)
90 {
91 s_BlockPools[i].busy = true;
92 return &s_BlockPools[i];
93 }
94 }
95 return nullptr;
96}
97
98// ---------------------------------------------------------------------------
99// C-interface
100// ---------------------------------------------------------------------------
101extern "C" {
102
103// ─────────────────────────────────────────────────────────────────────────────
104// Lifecycle — heap storage
105// ─────────────────────────────────────────────────────────────────────────────
106
107stk_blockpool_t *stk_blockpool_create(size_t capacity, size_t raw_block_size, const char *name)
108{
109 STK_ASSERT(capacity > 0U);
110 STK_ASSERT(raw_block_size > 0U);
111
113
114 BlockPoolSlot *slot = AcquireSlot();
115 if (slot == nullptr)
116 {
117 // pool exhausted — increase STK_C_BLOCKPOOL_MAX
118 STK_ASSERT(false);
119 return nullptr;
120 }
121
122 return new (slot->storage) stk_blockpool_t(capacity, raw_block_size, name);
123}
124
126 size_t raw_block_size,
127 uint8_t *storage,
128 size_t storage_size,
129 const char *name)
130{
131 STK_ASSERT(capacity > 0U);
132 STK_ASSERT(raw_block_size > 0U);
133 STK_ASSERT(storage != nullptr);
134 STK_ASSERT(storage_size >= (capacity * BlockMemoryPool::AlignBlockSize(raw_block_size)));
135
137
138 BlockPoolSlot *slot = AcquireSlot();
139 if (slot == nullptr)
140 {
141 // pool exhausted — increase STK_C_BLOCKPOOL_MAX
142 STK_ASSERT(false);
143 return nullptr;
144 }
145
146 return new (slot->storage) stk_blockpool_t(capacity, raw_block_size,
147 storage, storage_size, name);
148}
149
151{
152 STK_ASSERT(pool != nullptr);
153
155
156 BlockPoolSlot *slot = FindSlot(pool);
157
158 // pool not found: double-destroy or corruption
159 STK_ASSERT(slot != nullptr);
160 if (slot == nullptr)
161 return;
162
163 // Explicitly run the destructor (frees heap storage if owned).
164 pool->~stk_blockpool_t();
165 slot->busy = false;
166}
167
168// ─────────────────────────────────────────────────────────────────────────────
169// Allocation
170// ─────────────────────────────────────────────────────────────────────────────
171
173{
174 STK_ASSERT(pool != nullptr);
175
176 return pool->handle.Alloc();
177}
178
179void *stk_blockpool_timed_alloc(stk_blockpool_t *pool, uint32_t timeout)
180{
181 STK_ASSERT(pool != nullptr);
182
183 return pool->handle.TimedAlloc(static_cast<Timeout>(timeout));
184}
185
187{
188 STK_ASSERT(pool != nullptr);
189
190 return pool->handle.TryAlloc();
191}
192
193// ─────────────────────────────────────────────────────────────────────────────
194// Deallocation
195// ─────────────────────────────────────────────────────────────────────────────
196
198{
199 STK_ASSERT(pool != nullptr);
200
201 return pool->handle.Free(ptr);
202}
203
204// ─────────────────────────────────────────────────────────────────────────────
205// Query
206// ─────────────────────────────────────────────────────────────────────────────
207
209{
210 STK_ASSERT(pool != nullptr);
211
212 return pool->handle.IsStorageValid();
213}
214
216{
217 STK_ASSERT(pool != nullptr);
218
219 return pool->handle.GetCapacity();
220}
221
223{
224 STK_ASSERT(pool != nullptr);
225
226 return pool->handle.GetBlockSize();
227}
228
230{
231 STK_ASSERT(pool != nullptr);
232
233 return pool->handle.GetUsedCount();
234}
235
237{
238 STK_ASSERT(pool != nullptr);
239
240 return pool->handle.GetFreeCount();
241}
242
244{
245 STK_ASSERT(pool != nullptr);
246
247 return pool->handle.IsFull();
248}
249
251{
252 STK_ASSERT(pool != nullptr);
253
254 return pool->handle.IsEmpty();
255}
256
257} // extern "C"
Collection of memory-related primitives (stk::memory namespace).
Top-level STK include. Provides the Kernel class template and all built-in task-switching strategies.
#define STK_ASSERT(e)
Runtime assertion. Halts execution if the expression e evaluates to false.
Definition stk_defs.h:330
#define STK_STATIC_ASSERT_DESC(X, DESC)
Compile-time assertion with a custom error description. Produces a compilation error if X is false.
Definition stk_defs.h:350
C language binding/interface for SuperTinyKernel (STK).
C language binding for stk::memory::BlockMemoryPool.
static BlockPoolSlot * FindSlot(const stk_blockpool_t *pool)
static BlockPoolSlot * AcquireSlot()
static struct BlockPoolSlot s_BlockPools[8]
size_t stk_blockpool_get_capacity(const stk_blockpool_t *pool)
Get the total block capacity of the pool.
void stk_blockpool_destroy(stk_blockpool_t *pool)
Destroy a pool and return its slot to the static pool.
bool stk_blockpool_is_storage_valid(const stk_blockpool_t *pool)
Verify that the backing storage is valid and the pool is ready for use.
#define STK_C_BLOCKPOOL_MAX
Maximum number of concurrent stk_blockpool_t instances (default: 8).
void * stk_blockpool_timed_alloc(stk_blockpool_t *pool, uint32_t timeout)
Allocate one block, blocking until one becomes available or the timeout expires.
size_t stk_blockpool_get_used_count(const stk_blockpool_t *pool)
Get the number of currently allocated (outstanding) blocks.
struct stk_blockpool_t stk_blockpool_t
Opaque handle to a stk::memory::BlockMemoryPool instance.
void * stk_blockpool_alloc(stk_blockpool_t *pool)
Allocate one block, blocking indefinitely until one is available.
bool stk_blockpool_free(stk_blockpool_t *pool, void *ptr)
Return a previously allocated block to the pool.
void * stk_blockpool_try_alloc(stk_blockpool_t *pool)
Non-blocking allocation attempt.
stk_blockpool_t * stk_blockpool_create_static(size_t capacity, size_t raw_block_size, uint8_t *storage, size_t storage_size, const char *name)
Create a block pool backed by caller-supplied (external) storage.
stk_blockpool_t * stk_blockpool_create(size_t capacity, size_t raw_block_size, const char *name)
Create a block pool backed by heap-allocated storage.
bool stk_blockpool_is_empty(const stk_blockpool_t *pool)
Check whether all blocks are free (no outstanding allocations).
bool stk_blockpool_is_full(const stk_blockpool_t *pool)
Check whether all blocks are currently allocated (pool exhausted).
size_t stk_blockpool_get_free_count(const stk_blockpool_t *pool)
Get the number of free (available) blocks.
size_t stk_blockpool_get_block_size(const stk_blockpool_t *pool)
Get the aligned block size used internally by the allocator.
Namespace of STK package.
uintptr_t Word
Native processor word type.
Definition stk_common.h:113
int32_t Timeout
Timeout time (ticks).
Definition stk_common.h:123
Memory-related primitives.
BlockMemoryPool(size_t capacity, size_t raw_block_size, uint8_t *storage, size_t storage_size, const char *name=nullptr)
Construct a pool backed by caller-supplied (external) storage.
RAII-style low-level synchronization primitive for atomic code execution. Used as building brick for ...
Definition stk_sync_cs.h:54
stk_blockpool_t(size_t capacity, size_t raw_block_size, uint8_t *storage, size_t storage_size, const char *name)
stk_blockpool_t(size_t capacity, size_t raw_block_size, const char *name)
BlockMemoryPool handle
stk_blockpool_t * pool()
Word storage[sizeof(stk_blockpool_t)/sizeof(Word)]
const stk_blockpool_t * pool() const