ChibiOS 21.11.5
chmemcore.c
Go to the documentation of this file.
1/*
2 ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio.
3
4 This file is part of ChibiOS.
5
6 ChibiOS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation version 3 of the License.
9
10 ChibiOS is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19/**
20 * @file oslib/src/chmemcore.c
21 * @brief Core memory manager code.
22 *
23 * @addtogroup oslib_memcore
24 * @details Core Memory Manager related APIs and services.
25 * <h2>Operation mode</h2>
26 * The core memory manager is a simplified allocator that only
27 * allows to allocate memory blocks without the possibility to
28 * free them.<br>
29 * This allocator is meant as a memory blocks provider for the
30 * other allocators such as:
31 * - C-Runtime allocator (through a compiler specific adapter module).
32 * - Heap allocator (see @ref oslib_memheaps).
33 * - Memory pools allocator (see @ref oslib_mempools).
34 * .
35 * By having a centralized memory provider the various allocators
36 * can coexist and share the main memory.<br>
37 * This allocator, alone, is also useful for very simple
38 * applications that just require a simple way to get memory
39 * blocks.
40 * @pre In order to use the core memory manager APIs the @p CH_CFG_USE_MEMCORE
41 * option must be enabled in @p chconf.h.
42 * @note Compatible with RT and NIL.
43 * @{
44 */
45
46#include "ch.h"
47
48#if (CH_CFG_USE_MEMCORE == TRUE) || defined(__DOXYGEN__)
49
50/*===========================================================================*/
51/* Module exported variables. */
52/*===========================================================================*/
53
54/**
55 * @brief Memory core descriptor.
56 */
58
59/*===========================================================================*/
60/* Module local types. */
61/*===========================================================================*/
62
63/*===========================================================================*/
64/* Module local variables. */
65/*===========================================================================*/
66
67/*===========================================================================*/
68/* Module local functions. */
69/*===========================================================================*/
70
71/*===========================================================================*/
72/* Module exported functions. */
73/*===========================================================================*/
74
75/**
76 * @brief Low level memory manager initialization.
77 *
78 * @notapi
79 */
80void __core_init(void) {
81#if CH_CFG_MEMCORE_SIZE == 0
82 extern uint8_t __heap_base__[];
83 extern uint8_t __heap_end__[];
84
85 /*lint -save -e9033 [10.8] Required cast operations.*/
86 ch_memcore.basemem = __heap_base__;
87 ch_memcore.topmem = __heap_end__;
88 /*lint restore*/
89#else
90 static uint8_t static_heap[CH_CFG_MEMCORE_SIZE];
91
92 ch_memcore.basemem = &static_heap[0];
93 ch_memcore.topmem = &static_heap[CH_CFG_MEMCORE_SIZE];
94#endif
95}
96
97/**
98 * @brief Allocates a memory block starting from the lowest address upward.
99 * @details This function allocates a block of @p offset + @p size bytes. The
100 * returned pointer has @p offset bytes before its address and
101 * @p size bytes after.
102 *
103 * @param[in] size the size of the block to be allocated.
104 * @param[in] align desired memory alignment
105 * @param[in] offset aligned pointer offset
106 * @return A pointer to the allocated memory block.
107 * @retval NULL allocation failed, core memory exhausted.
108 *
109 * @iclass
110 */
111void *chCoreAllocFromBaseI(size_t size, unsigned align, size_t offset) {
112 uintptr_t base, top, p, next;
113
116
117 /*lint -save -e9033 [10.8] Required cast operations.*/
118 base = (uintptr_t)ch_memcore.basemem;
119 top = (uintptr_t)ch_memcore.topmem;
120 /*lint -restore*/
121
122 /* Integer-space pre-check: offset alone must fit in available space to
123 avoid forming an out-of-range value before the alignment step.*/
124 if (offset > (top - base)) {
125 return NULL;
126 }
127
128 /* All remaining arithmetic stays in integer space; no pointer is formed
129 until the bounds are verified.*/
130 p = MEM_ALIGN_NEXT(base + offset, align);
131 next = p + size;
132
133 /* Considering also the case where there is numeric overflow.*/
134 if ((next > top) || (next < base)) {
135 return NULL;
136 }
137
138 /*lint -save -e9033 [10.8] Required cast operations.*/
139 ch_memcore.basemem = (uint8_t *)next;
140 /*lint -restore*/
141
142 return (void *)p;
143}
144
145/**
146 * @brief Allocates a memory block starting from the top address downward.
147 * @details This function allocates a block of @p offset + @p size bytes. The
148 * returned pointer has @p offset bytes before its address and
149 * @p size bytes after.
150 *
151 * @param[in] size the size of the block to be allocated.
152 * @param[in] align desired memory alignment
153 * @param[in] offset aligned pointer offset
154 * @return A pointer to the allocated memory block.
155 * @retval NULL allocation failed, core memory exhausted.
156 *
157 * @iclass
158 */
159void *chCoreAllocFromTopI(size_t size, unsigned align, size_t offset) {
160 uintptr_t base, top, p, prev;
161
164
165 /*lint -save -e9033 [10.8] Required cast operations.*/
166 base = (uintptr_t)ch_memcore.basemem;
167 top = (uintptr_t)ch_memcore.topmem;
168 /*lint -restore*/
169
170 /* Integer-space pre-check: size alone must fit in available space to
171 avoid forming an out-of-range value before the alignment step.*/
172 if (size > (top - base)) {
173 return NULL;
174 }
175
176 /* All remaining arithmetic stays in integer space; no pointer is formed
177 until the bounds are verified.*/
178 p = MEM_ALIGN_PREV(top - size, align);
179 prev = p - offset;
180
181 /* Considering also the case where there is numeric overflow.*/
182 if ((prev < base) || (prev > top)) {
183 return NULL;
184 }
185
186 /*lint -save -e9033 [10.8] Required cast operations.*/
187 ch_memcore.topmem = (uint8_t *)prev;
188 /*lint -restore*/
189
190 return (void *)p;
191}
192
193/**
194 * @brief Allocates a memory block starting from the lowest address upward.
195 * @details This function allocates a block of @p offset + @p size bytes. The
196 * returned pointer has @p offset bytes before its address and
197 * @p size bytes after.
198 *
199 * @param[in] size the size of the block to be allocated.
200 * @param[in] align desired memory alignment
201 * @param[in] offset aligned pointer offset
202 * @return A pointer to the allocated memory block.
203 * @retval NULL allocation failed, core memory exhausted.
204 *
205 * @api
206 */
207void *chCoreAllocFromBase(size_t size, unsigned align, size_t offset) {
208 void *p;
209
210 chSysLock();
211 p = chCoreAllocFromBaseI(size, align, offset);
212 chSysUnlock();
213
214 return p;
215}
216
217/**
218 * @brief Allocates a memory block starting from the top address downward.
219 * @details This function allocates a block of @p offset + @p size bytes. The
220 * returned pointer has @p offset bytes before its address and
221 * @p size bytes after.
222 *
223 * @param[in] size the size of the block to be allocated.
224 * @param[in] align desired memory alignment
225 * @param[in] offset aligned pointer offset
226 * @return A pointer to the allocated memory block.
227 * @retval NULL allocation failed, core memory exhausted.
228 *
229 * @api
230 */
231void *chCoreAllocFromTop(size_t size, unsigned align, size_t offset) {
232 void *p;
233
234 chSysLock();
235 p = chCoreAllocFromTopI(size, align, offset);
236 chSysUnlock();
237
238 return p;
239}
240
241/**
242 * @brief Core memory status.
243 *
244 * @return The size, in bytes, of the free core memory.
245 *
246 * @xclass
247 */
248size_t chCoreGetStatusX(void) {
249
250 /*lint -save -e9033 [10.8] The cast is safe.*/
251 return (size_t)(ch_memcore.topmem - ch_memcore.basemem);
252 /*lint -restore*/
253}
254#endif /* CH_CFG_USE_MEMCORE == TRUE */
255
256/** @} */
#define chSysUnlock()
Leaves the kernel lock state.
#define chSysLock()
Enters the kernel lock state.
#define chDbgCheck(c)
Function parameters check.
Definition chdebug.h:117
#define chDbgCheckClassI()
Definition chdebug.h:98
#define CH_CFG_MEMCORE_SIZE
Managed RAM size.
#define MEM_ALIGN_PREV(p, a)
Aligns to the previous aligned memory address.
Definition chalign.h:68
#define MEM_IS_VALID_ALIGNMENT(a)
Returns whatever a constant is a valid alignment.
Definition chalign.h:98
#define MEM_ALIGN_NEXT(p, a)
Aligns to the next aligned memory address.
Definition chalign.h:79
void * chCoreAllocFromTop(size_t size, unsigned align, size_t offset)
Allocates a memory block starting from the top address downward.
Definition chmemcore.c:231
void * chCoreAllocFromBase(size_t size, unsigned align, size_t offset)
Allocates a memory block starting from the lowest address upward.
Definition chmemcore.c:207
size_t chCoreGetStatusX(void)
Core memory status.
Definition chmemcore.c:248
memcore_t ch_memcore
Memory core descriptor.
Definition chmemcore.c:57
void * chCoreAllocFromTopI(size_t size, unsigned align, size_t offset)
Allocates a memory block starting from the top address downward.
Definition chmemcore.c:159
void * chCoreAllocFromBaseI(size_t size, unsigned align, size_t offset)
Allocates a memory block starting from the lowest address upward.
Definition chmemcore.c:111
void __core_init(void)
Low level memory manager initialization.
Definition chmemcore.c:80
Type of memory core object.
Definition chmemcore.h:80