From 812cd7dee295bf2880a816e892decda7b0ee3a44 Mon Sep 17 00:00:00 2001 From: Maxim Prokhorov Date: Wed, 9 Feb 2022 14:47:35 +0300 Subject: [PATCH] system: sync HeapStats with upstream both heap size values should be u32 --- code/espurna/debug.cpp | 2 +- code/espurna/system.cpp | 66 ++++++++++++++++++++++---------- code/espurna/system.h | 9 ++--- code/espurna/terminal.cpp | 2 +- code/espurna/terminal_commands.h | 3 +- code/espurna/utils.h | 4 -- 6 files changed, 52 insertions(+), 34 deletions(-) diff --git a/code/espurna/debug.cpp b/code/espurna/debug.cpp index 7cb95e4f..534ef6c4 100644 --- a/code/espurna/debug.cpp +++ b/code/espurna/debug.cpp @@ -559,7 +559,7 @@ bool status(espurna::heartbeat::Mask mask) { if (mask & espurna::heartbeat::Report::Freeheap) { const auto stats = systemHeapStats(); - debugSend(PSTR("[MAIN] Heap: initial %5lu available %5lu contiguous %5hu\n"), + debugSend(PSTR("[MAIN] Heap: initial %5lu available %5lu contiguous %5lu\n"), systemInitialFreeHeap(), stats.available, stats.usable); } diff --git a/code/espurna/system.cpp b/code/espurna/system.cpp index 207e216c..91f6869f 100644 --- a/code/espurna/system.cpp +++ b/code/espurna/system.cpp @@ -159,33 +159,62 @@ namespace { // returns 'total stack size' minus 'un-painted area' // needs re-painting step, as this never decreases -unsigned long freeStack() { +size_t freeStack() { return ESP.getFreeContStack(); } -HeapStats heapStats() { - HeapStats stats; - ESP.getHeapStats(&stats.available, &stats.usable, &stats.frag_pct); - return stats; -} +// esp8266 normally only has a one single heap area, located in DRAM just 'before' the SYS stack +// since Core 3.x.x, internal C-level allocator was extended to support multiple contexts +// - external SPI RAM chip (but, this may not work with sizes above 65KiB on older Cores, check the actual version) +// - part of the IRAM, which will be specifically excluded from the CACHE by using a preprocessed linker file +// +// API expects us to use the same C API as usual - malloc, realloc, calloc, etc. +// Only now we are able to switch 'contexts' and receive different address range, currenty via `umm_{push,pop}_heap(ID)` +// (e.g. UMM_HEAP_DRAM, UMM_HEAP_IRAM, ... which techically is an implementation detail, and ESP::... methods should be used) +// +// Meaning, what happens below is heavily dependant on the when and why these functions are called -void heapStats(HeapStats& stats) { - stats = heapStats(); -} - -unsigned long freeHeap() { - return ESP.getFreeHeap(); +size_t freeHeap() { + return system_get_free_heap_size(); } decltype(freeHeap()) initialFreeHeap() { static const auto value = ([]() { - return freeHeap(); + return system_get_free_heap_size(); })(); return value; } +// see https://github.com/esp8266/Arduino/pull/8440 +template +using HasHeapStatsFixBase = decltype(std::declval().getHeapStats( + std::declval(), std::declval(), std::declval())); + +template +using HasHeapStatsFix = is_detected; + +template +HeapStats heapStats(T& instance, std::true_type) { + HeapStats out; + instance.getHeapStats(&out.available, &out.usable, &out.fragmentation); + return out; } + +template +HeapStats heapStats(T& instance, std::false_type) { + HeapStats out; + uint16_t usable{0}; + instance.getHeapStats(&out.available, &usable, &out.fragmentation); + out.usable = usable; + return out; +} + +HeapStats heapStats() { + return heapStats(ESP, HasHeapStatsFix{}); +} + +} // namespace } // namespace memory namespace boot { @@ -392,8 +421,7 @@ namespace load_average { namespace build { namespace { -constexpr size_t ValueMin { 0 }; -constexpr size_t ValueMax { 100 }; +static constexpr size_t ValueMax { 100 }; static constexpr espurna::duration::Seconds Interval { LOADAVG_INTERVAL }; static_assert(Interval <= espurna::duration::Seconds(90), ""); @@ -836,15 +864,11 @@ HeapStats systemHeapStats() { return espurna::memory::heapStats(); } -void systemHeapStats(HeapStats& stats) { - espurna::memory::heapStats(stats); -} - -unsigned long systemFreeHeap() { +size_t systemFreeHeap() { return espurna::memory::freeHeap(); } -unsigned long systemInitialFreeHeap() { +size_t systemInitialFreeHeap() { return espurna::memory::initialFreeHeap(); } diff --git a/code/espurna/system.h b/code/espurna/system.h index e33bd60d..e7b89566 100644 --- a/code/espurna/system.h +++ b/code/espurna/system.h @@ -16,8 +16,8 @@ Copyright (C) 2019 by Xose Pérez struct HeapStats { uint32_t available; - uint16_t usable; - uint8_t frag_pct; + uint32_t usable; + uint8_t fragmentation; }; enum class CustomResetReason : uint8_t { @@ -279,10 +279,9 @@ String serialize(espurna::duration::ClockCycles); unsigned long systemFreeStack(); HeapStats systemHeapStats(); -void systemHeapStats(HeapStats&); -unsigned long systemFreeHeap(); -unsigned long systemInitialFreeHeap(); +size_t systemFreeHeap(); +size_t systemInitialFreeHeap(); bool eraseSDKConfig(); void forceEraseSDKConfig(); diff --git a/code/espurna/terminal.cpp b/code/espurna/terminal.cpp index 91449d7f..cdc76f28 100644 --- a/code/espurna/terminal.cpp +++ b/code/espurna/terminal.cpp @@ -406,7 +406,7 @@ void _terminalInitCommands() { terminalRegisterCommand(F("HEAP"), [](::terminal::CommandContext&& ctx) { const auto stats = systemHeapStats(); - ctx.output.printf_P(PSTR("initial: %lu available: %lu contiguous: %hu\n"), + ctx.output.printf_P(PSTR("initial: %lu available: %lu contiguous: %lu\n"), systemInitialFreeHeap(), stats.available, stats.usable); terminalOK(ctx); diff --git a/code/espurna/terminal_commands.h b/code/espurna/terminal_commands.h index 21f952bc..284b6d06 100644 --- a/code/espurna/terminal_commands.h +++ b/code/espurna/terminal_commands.h @@ -67,8 +67,7 @@ public: // and we can either stop (false) or continue (true) the function. void process(ProcessFunc = defaultProcessFunc); - private: - +private: static bool defaultProcessFunc(Result); // general input / output stream: diff --git a/code/espurna/utils.h b/code/espurna/utils.h index c1bed3a9..af5c0ae6 100644 --- a/code/espurna/utils.h +++ b/code/espurna/utils.h @@ -36,10 +36,6 @@ bool haveRelaysOrSensors(); String prettyDuration(espurna::duration::Seconds); String getUptime(); -void infoHeapStats(const char* name, const HeapStats& stats); -void infoHeapStats(bool show_frag_stats = false); -void infoMemory(const char* name, unsigned int total_memory, unsigned int free_memory); - bool sslCheckFingerPrint(const char * fingerprint); bool sslFingerPrintArray(const char * fingerprint, unsigned char * bytearray); bool sslFingerPrintChar(const char * fingerprint, char * destination);