rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
lua_heap.cpp
Go to the documentation of this file.
1#include "pch.h"
2
3#include "rusefi_lua.h"
4
5#if EFI_LUA
6
7#include "lua.hpp"
8#include "lua_heap.h"
9
10#if EFI_PROD_CODE || EFI_SIMULATOR
11
12#ifndef MCU_HAS_CCM_RAM
13 #define MCU_HAS_CCM_RAM FALSE
14#endif
15
16#ifndef LUA_EXTRA_HEAP
17 #define LUA_EXTRA_HEAP 0
18#endif
19
20#if (LUA_EXTRA_HEAP > 0)
21CH_HEAP_AREA(luaExtraHeapArea, LUA_EXTRA_HEAP)
22 #ifdef EFI_HAS_EXT_SDRAM
23 SDRAM_OPTIONAL
24 #endif
25 ;
26#endif
27
28class Heap {
29public:
30 memory_heap_t m_heap;
31
32 size_t m_size = 0;
33 uint8_t* m_buffer = nullptr;
34
35 void* alloc(size_t n) {
36 if (m_buffer && m_size) {
37 return chHeapAlloc(&m_heap, n);
38 }
39
40 return nullptr;
41 }
42
43 void free(void* obj) {
44 chHeapFree(obj);
45 }
46
47public:
48 template<size_t TSize>
49 Heap(uint8_t (&buffer)[TSize])
50 {
51 init(buffer, TSize);
52 }
53
54 Heap()
55 {
56 init(nullptr, 0);
57 }
58
59 void init(uint8_t *buffer, size_t size) {
60 criticalAssertVoid(used() == 0, "Too late to init Lua heap: already in use");
61
62 m_size = size;
63 m_buffer = buffer;
64
65 reset();
66 }
67
68 size_t size() const {
69 return m_size;
70 }
71
72 size_t used() {
73 if (size() == 0) {
74 return 0;
75 }
76
77 size_t heapFree = 0;
78 size_t lagestFree = 0;
79 chHeapStatus(&m_heap, &heapFree, &lagestFree);
80
81 return m_size - heapFree;
82 }
83
84 // Use only in case of emergency - obliterates all heap objects and starts over
85 void reset() {
86 if (m_buffer && m_size) {
87 chHeapObjectInit(&m_heap, m_buffer, m_size);
88 }
89 }
90};
91
92// see [tag:multi-step-lua-alloc] below
93// this is a bit over-complicated at the moment, one argument would be that this supports multi-region RAM use-case
94#if (LUA_EXTRA_HEAP > 0)
95// Optional SDRAM
96static Heap luaExtraHeap(luaExtraHeapArea);
97#endif
98
99#if defined(STM32F4)
100// Optional RAM3 exist on STM32F42x
101static Heap luaOptionalHeap;
102#endif
103
104#if MCU_HAS_CCM_RAM
105// CCM RAM leftovers on STM32F4xx
106static Heap luaCcmHeap;
107#endif
108
110{
111 // stm32f4xx can have optional ram3 region
112#if defined(STM32F4)
113 // Some boads can be equiped with STM32F42x only, in this case we allow linker to take care of ram3
114#if !defined(EFI_IS_F42x)
115 // cute hack: let's check at runtime if you are a lucky owner of board with extra RAM and use that extra RAM for extra Lua
116 // we need this on microRusEFI for sure
117 // definitely should NOT have this on Proteus
118 // on Hellen a bit of open question what's the best track
119 if (isStm32F42x()) {
120 // This is safe to use section base and end as we define ram3 for all F4 chips
121 extern uint8_t __ram3_base__[];
122 extern uint8_t __ram3_end__[];
123 luaOptionalHeap.init(__ram3_base__, __ram3_end__ - __ram3_base__);
124 }
125#endif // !EFI_IS_F42x
126#endif // STM32F4
127
128 // stm32f4xx have CCM memory that may have some leftovers
129#if MCU_HAS_CCM_RAM
130 extern uint8_t __heap_ccm_base__[];
131 extern uint8_t __heap_ccm_end__[];
132 luaCcmHeap.init(__heap_ccm_base__, __heap_ccm_end__ - __heap_ccm_base__);
133#endif
134}
135
136static size_t luaMemoryUsed = 0;
137
138void* luaHeapAlloc(void* /*ud*/, void* optr, size_t osize, size_t nsize) {
139 // If new size is zero, this is a free. Do not allocate.
140 if (nsize == 0) {
141 if (optr) {
142 size_t oldSize = chHeapGetSize(optr);
143 chHeapFree(optr);
144 luaMemoryUsed -= oldSize;
145 }
146 return nullptr;
147 }
148
149 void *nptr = nullptr;
150
151 // [tag:multi-step-lua-alloc]
152 // First try dedicated Lua heap(s)
153#if (LUA_EXTRA_HEAP > 0)
154 if (nptr == nullptr) {
155 nptr = luaExtraHeap.alloc(nsize);
156 }
157#endif
158#if defined(STM32F4)
159 if (nptr == nullptr) {
160 nptr = luaOptionalHeap.alloc(nsize);
161 }
162#endif
163#if MCU_HAS_CCM_RAM
164 if (nptr == nullptr) {
165 nptr = luaCcmHeap.alloc(nsize);
166 }
167#endif
168
169 // [tag:multi-step-lua-alloc]
170 // then try ChibiOS default heap
171 if (nptr == nullptr) {
172 nptr = chHeapAlloc(NULL, nsize);
173 }
174
175 size_t newSize = 0;
176 if (nptr) {
177 // Account for newly allocated memory by actual block size
178 newSize = chHeapGetSize(nptr);
179 chDbgAssert(newSize >= nsize, "Lua allocator returned smaller block than requested");
180 luaMemoryUsed += newSize;
181 }
182
183 if (optr) {
184 chDbgAssert(osize <= chHeapGetSize(optr), "Lua lost track of allocated mem");
185 // An old pointer was passed in. Only free it if we successfully allocated a new one.
186 size_t oldSize = chHeapGetSize(optr);
187 if (nptr != nullptr) {
188 // Copy the minimum of old and new block sizes
189 size_t copySize = (oldSize < newSize) ? oldSize : newSize;
190 memcpy(nptr, optr, copySize);
191 // chHeapFree will find correct heap to return memory to
192 chHeapFree(optr);
193 luaMemoryUsed -= oldSize;
194 } else {
195 if (nsize <= oldSize) {
196 return optr; // shrink must not fail per Lua's assumption
197 }
198 return nullptr; // grow failed
199 }
200 }
201
202 if (engineConfiguration->debugMode == DBG_LUA) {
204 }
205
206 return nptr;
207}
208
210{
211 return luaMemoryUsed;
212}
213
215{
216#if (LUA_EXTRA_HEAP > 0)
217 luaExtraHeap.reset();
218#endif
219#if defined(STM32F4)
220 luaOptionalHeap.reset();
221#endif
222#if MCU_HAS_CCM_RAM
223 luaCcmHeap.reset();
224#endif
225
226 luaMemoryUsed = 0;
227}
228
229#if CH_CFG_MEMCORE_SIZE == 0
230 extern uint8_t __heap_base__[];
231 extern uint8_t __heap_end__[];
232#endif
233
235 size_t chMemTotal =
236 /* Chibios heap size */
237 #if CH_CFG_MEMCORE_SIZE == 0
239 #else
240 CH_CFG_MEMCORE_SIZE;
241 #endif
242 auto totalHeapSize =
243 chMemTotal +
244 #if (LUA_EXTRA_HEAP > 0)
245 luaExtraHeap.size() +
246 #endif
247 #if defined(STM32F4)
248 luaOptionalHeap.size() +
249 #endif
250 #if MCU_HAS_CCM_RAM
251 luaCcmHeap.size() +
252 #endif
253 0;
254
255 if (totalHeapSize) {
256 auto memoryUsed = luaHeapUsed();
257 float pct = 100.0f * memoryUsed / totalHeapSize;
258 efiPrintf("Lua total heap(s) usage: %d / %d bytes = %.1f%%", memoryUsed, totalHeapSize, pct);
259 } else {
260 efiPrintf("No heap available for Lua");
261 }
262
263 #if (LUA_EXTRA_HEAP > 0)
264 efiPrintf("Lua extra heap usage: %d / %d", luaExtraHeap.used(), luaExtraHeap.size());
265 #endif
266 #if defined(STM32F4)
267 efiPrintf("Lua optional heap usage: %d / %d", luaOptionalHeap.used(), luaOptionalHeap.size());
268 #endif
269 #if MCU_HAS_CCM_RAM
270 efiPrintf("Lua CCM heap usage: %d / %d", luaCcmHeap.used(), luaCcmHeap.size());
271 #endif
272
273 size_t chHeapFree = 0;
274 chHeapStatus(NULL, &chHeapFree, NULL);
275 /* total available for ChibiOS minus left free, plus free in Chibios Heap */
276 size_t chMemCoreUsed = chMemTotal - chCoreGetStatusX() - chHeapFree;
277 efiPrintf("Common ChibiOS heap: %d bytes free", chHeapFree);
278 efiPrintf("ChibiOS memcore usage: %d / %d", chMemCoreUsed, chMemTotal);
279}
280
281#else // not EFI_PROD_CODE
282// Non-MCU code can use plain realloc function instead of custom implementation
283void* luaHeapAlloc(void* /*ud*/, void* ptr, size_t /*osize*/, size_t nsize) {
284 if (!nsize) {
285 free(ptr);
286 return nullptr;
287 }
288
289 if (!ptr) {
290 return malloc(nsize);
291 }
292
293 return realloc(ptr, nsize);
294}
295#endif // EFI_PROD_CODE
296
297#endif // EFI_LUA
bool isStm32F42x(void)
TunerStudioOutputChannels outputChannels
Definition engine.h:109
void * malloc(size_t)
void free(void *)
static EngineAccessor engine
Definition engine.h:413
static constexpr engine_configuration_s * engineConfiguration
static Heap luaExtraHeap(luaExtraHeapArea)
uint8_t __heap_end__[]
CH_HEAP_AREA(luaExtraHeapArea, LUA_EXTRA_HEAP) SDRAM_OPTIONAL
size_t luaHeapUsed()
Definition lua_heap.cpp:209
static size_t luaMemoryUsed
Definition lua_heap.cpp:136
static Heap luaCcmHeap
Definition lua_heap.cpp:106
uint8_t __heap_base__[]
void luaHeapPrintInfo()
Definition lua_heap.cpp:234
void * luaHeapAlloc(void *, void *optr, size_t osize, size_t nsize)
Definition lua_heap.cpp:138
static Heap luaOptionalHeap
Definition lua_heap.cpp:101
void luaHeapInit()
Definition lua_heap.cpp:109
void luaHeapReset()
Definition lua_heap.cpp:214
composite packet size
static BigBufferHandle buffer