Line | Branch | Decision | Exec | Source |
---|---|---|---|---|
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) | |||
21 | CH_HEAP_AREA(luaExtraHeapArea, LUA_EXTRA_HEAP) | |||
22 | #ifdef EFI_HAS_EXT_SDRAM | |||
23 | SDRAM_OPTIONAL | |||
24 | #endif | |||
25 | ; | |||
26 | #endif | |||
27 | ||||
28 | class Heap { | |||
29 | public: | |||
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 | ||||
47 | public: | |||
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 | |||
96 | static Heap luaExtraHeap(luaExtraHeapArea); | |||
97 | #endif | |||
98 | ||||
99 | #if defined(STM32F4) | |||
100 | // Optional RAM3 exist on STM32F42x | |||
101 | static Heap luaOptionalHeap; | |||
102 | #endif | |||
103 | ||||
104 | #if MCU_HAS_CCM_RAM | |||
105 | // CCM RAM leftovers on STM32F4xx | |||
106 | static Heap luaCcmHeap; | |||
107 | #endif | |||
108 | ||||
109 | void luaHeapInit() | |||
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 | ||||
136 | static size_t luaMemoryUsed = 0; | |||
137 | ||||
138 | void* luaHeapAlloc(void* /*ud*/, void* optr, size_t osize, size_t nsize) { | |||
139 | void *nptr = nullptr; | |||
140 | ||||
141 | if (nsize) { | |||
142 | // [tag:multi-step-lua-alloc] | |||
143 | // First try dedicated Lua heap(s) | |||
144 | #if (LUA_EXTRA_HEAP > 0) | |||
145 | if (nptr == nullptr) { | |||
146 | nptr = luaExtraHeap.alloc(nsize); | |||
147 | } | |||
148 | #endif | |||
149 | #if defined(STM32F4) | |||
150 | if (nptr == nullptr) { | |||
151 | nptr = luaOptionalHeap.alloc(nsize); | |||
152 | } | |||
153 | #endif | |||
154 | #if MCU_HAS_CCM_RAM | |||
155 | if (nptr == nullptr) { | |||
156 | nptr = luaCcmHeap.alloc(nsize); | |||
157 | } | |||
158 | #endif | |||
159 | ||||
160 | // [tag:multi-step-lua-alloc] | |||
161 | // then try ChibiOS default heap | |||
162 | if (nptr == nullptr) { | |||
163 | nptr = chHeapAlloc(NULL, nsize); | |||
164 | } | |||
165 | } | |||
166 | ||||
167 | if (nptr) { | |||
168 | luaMemoryUsed += nsize; | |||
169 | } | |||
170 | ||||
171 | if (optr) { | |||
172 | // An old pointer was passed in, copy the old data in, then free | |||
173 | if (nptr != nullptr) { | |||
174 | memcpy(nptr, optr, chHeapGetSize(optr) > nsize ? nsize : chHeapGetSize(optr)); | |||
175 | } | |||
176 | // chHeapFree will find correct heap to return memory to | |||
177 | chHeapFree(optr); | |||
178 | luaMemoryUsed -= osize; | |||
179 | } | |||
180 | ||||
181 | if (engineConfiguration->debugMode == DBG_LUA) { | |||
182 | engine->outputChannels.debugIntField1 = luaHeapUsed(); | |||
183 | } | |||
184 | ||||
185 | return nptr; | |||
186 | } | |||
187 | ||||
188 | size_t luaHeapUsed() | |||
189 | { | |||
190 | return luaMemoryUsed; | |||
191 | } | |||
192 | ||||
193 | void luaHeapReset() | |||
194 | { | |||
195 | #if (LUA_EXTRA_HEAP > 0) | |||
196 | luaExtraHeap.reset(); | |||
197 | #endif | |||
198 | #if defined(STM32F4) | |||
199 | luaOptionalHeap.reset(); | |||
200 | #endif | |||
201 | #if MCU_HAS_CCM_RAM | |||
202 | luaCcmHeap.reset(); | |||
203 | #endif | |||
204 | ||||
205 | luaMemoryUsed = 0; | |||
206 | } | |||
207 | ||||
208 | #if CH_CFG_MEMCORE_SIZE == 0 | |||
209 | extern uint8_t __heap_base__[]; | |||
210 | extern uint8_t __heap_end__[]; | |||
211 | #endif | |||
212 | ||||
213 | void luaHeapPrintInfo() { | |||
214 | size_t chMemTotal = | |||
215 | /* Chibios heap size */ | |||
216 | #if CH_CFG_MEMCORE_SIZE == 0 | |||
217 | (__heap_end__ - __heap_base__); | |||
218 | #else | |||
219 | CH_CFG_MEMCORE_SIZE; | |||
220 | #endif | |||
221 | auto totalHeapSize = | |||
222 | chMemTotal + | |||
223 | #if (LUA_EXTRA_HEAP > 0) | |||
224 | luaExtraHeap.size() + | |||
225 | #endif | |||
226 | #if defined(STM32F4) | |||
227 | luaOptionalHeap.size() + | |||
228 | #endif | |||
229 | #if MCU_HAS_CCM_RAM | |||
230 | luaCcmHeap.size() + | |||
231 | #endif | |||
232 | 0; | |||
233 | ||||
234 | if (totalHeapSize) { | |||
235 | auto memoryUsed = luaHeapUsed(); | |||
236 | float pct = 100.0f * memoryUsed / totalHeapSize; | |||
237 | efiPrintf("Lua total heap(s) usage: %d / %d bytes = %.1f%%", memoryUsed, totalHeapSize, pct); | |||
238 | } else { | |||
239 | efiPrintf("No heap available for Lua"); | |||
240 | } | |||
241 | ||||
242 | #if (LUA_EXTRA_HEAP > 0) | |||
243 | efiPrintf("Lua extra heap usage: %d / %d", luaExtraHeap.used(), luaExtraHeap.size()); | |||
244 | #endif | |||
245 | #if defined(STM32F4) | |||
246 | efiPrintf("Lua optional heap usage: %d / %d", luaOptionalHeap.used(), luaOptionalHeap.size()); | |||
247 | #endif | |||
248 | #if MCU_HAS_CCM_RAM | |||
249 | efiPrintf("Lua CCM heap usage: %d / %d", luaCcmHeap.used(), luaCcmHeap.size()); | |||
250 | #endif | |||
251 | ||||
252 | size_t chHeapFree = 0; | |||
253 | chHeapStatus(NULL, &chHeapFree, NULL); | |||
254 | /* total available for ChibiOS minus left free, plus free in Chibios Heap */ | |||
255 | size_t chMemCoreUsed = chMemTotal - chCoreGetStatusX() - chHeapFree; | |||
256 | efiPrintf("Common ChibiOS heap: %d bytes free", chHeapFree); | |||
257 | efiPrintf("ChibiOS memcore usage: %d / %d", chMemCoreUsed, chMemTotal); | |||
258 | } | |||
259 | ||||
260 | #else // not EFI_PROD_CODE | |||
261 | // Non-MCU code can use plain realloc function instead of custom implementation | |||
262 | 215589 | void* luaHeapAlloc(void* /*ud*/, void* ptr, size_t /*osize*/, size_t nsize) { | ||
263 |
2/2✓ Branch 0 taken 116456 times.
✓ Branch 1 taken 99133 times.
|
2/2✓ Decision 'true' taken 116456 times.
✓ Decision 'false' taken 99133 times.
|
215589 | if (!nsize) { |
264 | 116456 | free(ptr); | ||
265 | 116456 | return nullptr; | ||
266 | } | |||
267 | ||||
268 |
2/2✓ Branch 0 taken 92925 times.
✓ Branch 1 taken 6208 times.
|
2/2✓ Decision 'true' taken 92925 times.
✓ Decision 'false' taken 6208 times.
|
99133 | if (!ptr) { |
269 | 92925 | return malloc(nsize); | ||
270 | } | |||
271 | ||||
272 | 6208 | return realloc(ptr, nsize); | ||
273 | } | |||
274 | #endif // EFI_PROD_CODE | |||
275 | ||||
276 | #endif // EFI_LUA | |||
277 |