| 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 | 207621 | void* luaHeapAlloc(void* /*ud*/, void* ptr, size_t /*osize*/, size_t nsize) { | ||
| 263 |
2/2✓ Branch 0 taken 112112 times.
✓ Branch 1 taken 95509 times.
|
2/2✓ Decision 'true' taken 112112 times.
✓ Decision 'false' taken 95509 times.
|
207621 | if (!nsize) { |
| 264 | 112112 | free(ptr); | ||
| 265 | 112112 | return nullptr; | ||
| 266 | } | |||
| 267 | ||||
| 268 |
2/2✓ Branch 0 taken 89445 times.
✓ Branch 1 taken 6064 times.
|
2/2✓ Decision 'true' taken 89445 times.
✓ Decision 'false' taken 6064 times.
|
95509 | if (!ptr) { |
| 269 | 89445 | return malloc(nsize); | ||
| 270 | } | |||
| 271 | ||||
| 272 | 6064 | return realloc(ptr, nsize); | ||
| 273 | } | |||
| 274 | #endif // EFI_PROD_CODE | |||
| 275 | ||||
| 276 | #endif // EFI_LUA | |||
| 277 |