From d2bf42d411b21efd7d79614bb544959904d01082 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Thu, 16 Mar 2023 11:00:17 +0100 Subject: [PATCH] [BH-1655] Fix memory leaks in clock faces and shortcuts Disable libphonenumber initialization since it is not used in Harmony but takes around 1.4MB of memory Add heap allocation statistics --- .vscode/launch.json | 2 + .vscode/settings.json | 5 +- .vscode/tasks.json | 1 + .../widgets/spinners/ItemSpinner.hpp | 13 ++++- .../apps-common/widgets/spinners/Model.hpp | 12 ++++- module-bsp/board/rt1051/bsp/rtc/rtc.cpp | 2 +- module-os/memory/UserMemStatsLogger.hpp | 34 +++++++++++++ module-os/memory/usermem.c | 50 +++++++++++++++++++ module-os/memory/usermem.h | 7 +++ .../service-evtmgr/WorkerEventCommon.cpp | 5 ++ module-utils/log/api/log/debug.hpp | 3 +- products/BellHybrid/BellHybridMain.cpp | 6 +-- .../windows/BellHomeScreenWindow.cpp | 4 +- .../HomeScreenLayoutVerticalSimple.cpp | 4 +- 14 files changed, 135 insertions(+), 13 deletions(-) create mode 100644 module-os/memory/UserMemStatsLogger.hpp diff --git a/.vscode/launch.json b/.vscode/launch.json index 4ba56f32ad8ebb54414902e0e670338ce375c979..d749d1fcbe77d42f7ebff581e0e5e146ab1d199d 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -115,6 +115,8 @@ "jlinkscript": "${workspaceFolder}/evkbimxrt1050_sdram_init_T6.jlinkscript", "rtos": "FreeRTOS", "overrideLaunchCommands": [ + "source tools/gdb_crash_extend.py", + "source tools/misc/puregdb/puregdb.py", "monitor reset 0", "monitor halt", "monitor memU32 0x401BC000 = 128;", diff --git a/.vscode/settings.json b/.vscode/settings.json index 23e8dff91b9492f0e0e28511a1e276ae48be688b..55b665c2849ded704aa9e04b3646d1bea3792e43 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -88,7 +88,10 @@ "assert": "cpp", "narrow": "cpp", "util": "cpp", - "filesystem": "cpp" + "filesystem": "cpp", + "numbers": "cpp", + "semaphore": "cpp", + "byte": "cpp" }, "favorites.sortDirection": "ASC", } diff --git a/.vscode/tasks.json b/.vscode/tasks.json index d4507d071dfa284e7105781048889d843767142d..7b19f1224bb4c13906244bc04cbd9831563088c7 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -55,6 +55,7 @@ "bell", "linux", "Debug", + //"-DLINUX_ENABLE_SANITIZER=OFF", "-G", "Ninja" ], diff --git a/module-apps/apps-common/widgets/spinners/ItemSpinner.hpp b/module-apps/apps-common/widgets/spinners/ItemSpinner.hpp index 29545993ef8a58c45aa691637e76854699c618ae..bb354e084ecd0e699f08ab19ee67045c6efb5d2d 100644 --- a/module-apps/apps-common/widgets/spinners/ItemSpinner.hpp +++ b/module-apps/apps-common/widgets/spinners/ItemSpinner.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once @@ -21,6 +21,7 @@ namespace gui range range, Boundaries boundaries = Boundaries::Continuous, Orientation orientation = Orientation::Vertical); + ~ItemSpinner(); [[nodiscard]] value_type getCurrentValue() const noexcept; void setCurrentValue(value_type val); @@ -70,6 +71,16 @@ namespace gui } } + template + ItemSpinner::~ItemSpinner() + { + for (Item *layout : container) { + if (layout != currentLayout) { + delete layout; + } + } + } + template void ItemSpinner::setFocusEdges(RectangleEdge edges) { diff --git a/module-apps/apps-common/widgets/spinners/Model.hpp b/module-apps/apps-common/widgets/spinners/Model.hpp index be1889e8af8317457631fe476ed66771fee7ed90..cfb26df505cf82ebb41d8876d70c400deb9ccde5 100644 --- a/module-apps/apps-common/widgets/spinners/Model.hpp +++ b/module-apps/apps-common/widgets/spinners/Model.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once @@ -102,6 +102,16 @@ class Model return std::next(it) == elements.end(); } + auto begin() const + { + return elements.begin(); + } + + auto end() const + { + return elements.end(); + } + private: range elements; typename range::iterator it = elements.end(); diff --git a/module-bsp/board/rt1051/bsp/rtc/rtc.cpp b/module-bsp/board/rt1051/bsp/rtc/rtc.cpp index 2a9f58845ef01a0b3b5d905b213ee1beea4790f3..099d5b4d77020f20a7df05f4068d1f877c0e3bb6 100644 --- a/module-bsp/board/rt1051/bsp/rtc/rtc.cpp +++ b/module-bsp/board/rt1051/bsp/rtc/rtc.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "rtc_configuration.hpp" diff --git a/module-os/memory/UserMemStatsLogger.hpp b/module-os/memory/UserMemStatsLogger.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a110c43e806750740533c68dcab40f31c10c38ab --- /dev/null +++ b/module-os/memory/UserMemStatsLogger.hpp @@ -0,0 +1,34 @@ +// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +#include + +#include "usermem.h" + +struct UserMemStatsLogger +{ +#if DEBUG_HEAP_ALLOCATIONS == 1 + UserMemStatsLogger() + { + usermemResetStatistics(); + freeHeapSize1 = usermemGetFreeHeapSize(); + } + + ~UserMemStatsLogger() + { + size_t freeHeapSize2 = usermemGetFreeHeapSize(); + size_t allocationsCount = usermemGetAllocationsCount(); + size_t deallocationsCount = usermemGetDeallocationsCount(); + size_t allocatedMin = usermemGetAllocatedMin(); + size_t allocatedMax = usermemGetAllocatedMax(); + size_t allocatedSum = usermemGetAllocatedSum(); + LOG_INFO("\nFree before: %zu\nFree after: %zu\n# allocations: %zu\n# deallocations: %zu\nSmallest block: %zu\nBiggest block: %zu\nAllocated: %zu", + freeHeapSize1, freeHeapSize2, allocationsCount, deallocationsCount, allocatedMin, allocatedMax, allocatedSum); + } + +private: + size_t freeHeapSize1; +#endif +}; diff --git a/module-os/memory/usermem.c b/module-os/memory/usermem.c index ddc5fe1db6d585fa8dd2791f08b51025b30a1d2f..6db9eaddd7bca59fbe75d352c701907297f63e10 100644 --- a/module-os/memory/usermem.c +++ b/module-os/memory/usermem.c @@ -107,6 +107,12 @@ fragmentation. */ static size_t userxFreeBytesRemaining = 0U; static size_t userxMinimumEverFreeBytesRemaining = 0U; +/* Allocation statistics */ +static size_t xAllocationsCount = 0; +static size_t xDeallocationsCount = 0; +static size_t xAllocatedMin = SIZE_MAX; +static size_t xAllocatedMax = 0; +static size_t xAllocatedSum = 0; /* Gets set to the top bit of an size_t type. When this bit in the xBlockSize member of an BlockLink_t structure is set then the block belongs to the @@ -222,6 +228,14 @@ void *usermalloc(size_t xWantedSize) mtCOVERAGE_TEST_MARKER(); } + /* Allocation statistics */ +#if DEBUG_HEAP_ALLOCATIONS == 1 + ++xAllocationsCount; + if (pxBlock->xBlockSize < xAllocatedMin) xAllocatedMin = pxBlock->xBlockSize; + if (pxBlock->xBlockSize > xAllocatedMax) xAllocatedMax = pxBlock->xBlockSize; + xAllocatedSum += pxBlock->xBlockSize; +#endif + userxFreeBytesRemaining -= pxBlock->xBlockSize; if( userxFreeBytesRemaining < userxMinimumEverFreeBytesRemaining ) @@ -329,6 +343,12 @@ void userfree(void *pv) vTaskSuspendAll(); { + /* Allocation statistics */ +#if DEBUG_HEAP_ALLOCATIONS == 1 + ++xDeallocationsCount; + xAllocatedSum -= pxLink->xBlockSize; +#endif + /* Add this block to the list of free blocks. */ userxFreeBytesRemaining += pxLink->xBlockSize; traceFREE( pv, pxLink->xBlockSize ); @@ -407,6 +427,36 @@ size_t usermemGetMinimumEverFreeHeapSize( void ) } /*-----------------------------------------------------------*/ +void usermemResetStatistics(void) +{ + xAllocationsCount = 0; + xDeallocationsCount = 0; + xAllocatedMin = SIZE_MAX; + xAllocatedMax = 0; + xAllocatedSum = 0; +} +size_t usermemGetAllocationsCount(void) +{ + return xAllocationsCount; +} +size_t usermemGetDeallocationsCount(void) +{ + return xDeallocationsCount; +} +size_t usermemGetAllocatedMin(void) +{ + return xAllocatedMin; +} +size_t usermemGetAllocatedMax(void) +{ + return xAllocatedMax; +} +size_t usermemGetAllocatedSum(void) +{ + return xAllocatedSum; +} + +/*-----------------------------------------------------------*/ static void prvHeapInit( void ) { diff --git a/module-os/memory/usermem.h b/module-os/memory/usermem.h index b651196f6a6ec93e0d6d48f3742fa0655ad4ca0a..1b73b054bf6fa50741e526018987aaa9ad09fe4c 100644 --- a/module-os/memory/usermem.h +++ b/module-os/memory/usermem.h @@ -24,6 +24,13 @@ size_t usermemGetFreeHeapSize(void); size_t usermemGetMinimumEverFreeHeapSize(void); +void usermemResetStatistics(void); +size_t usermemGetAllocationsCount(void); +size_t usermemGetDeallocationsCount(void); +size_t usermemGetAllocatedMin(void); +size_t usermemGetAllocatedMax(void); +size_t usermemGetAllocatedSum(void); + void *userrealloc(void *pv, size_t xWantedSize); #ifdef __cplusplus diff --git a/module-services/service-evtmgr/WorkerEventCommon.cpp b/module-services/service-evtmgr/WorkerEventCommon.cpp index 931e7cf71efcc47a252f81d321df4b2576e54bb2..d2c429a804e6a6939c9aaa0b6e1142af0bcb5712 100644 --- a/module-services/service-evtmgr/WorkerEventCommon.cpp +++ b/module-services/service-evtmgr/WorkerEventCommon.cpp @@ -25,6 +25,7 @@ #include #include +#include WorkerEventCommon::WorkerEventCommon(sys::Service *service) : sys::Worker(service, stackDepthBytes), @@ -33,6 +34,10 @@ WorkerEventCommon::WorkerEventCommon(sys::Service *service) bool WorkerEventCommon::handleMessage(uint32_t queueID) { +#if DEBUG_HEAP_ALLOCATIONS == 1 + LOG_INFO("Free space: %zu", usermemGetFreeHeapSize()); +#endif + auto &queue = queues[queueID]; // service queue diff --git a/module-utils/log/api/log/debug.hpp b/module-utils/log/api/log/debug.hpp index 5e82214e3f51eaf1f48c9075df8079baa45df82b..52483b1d57e413a4fd523202386b0bea1e1700b9 100644 --- a/module-utils/log/api/log/debug.hpp +++ b/module-utils/log/api/log/debug.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once @@ -13,6 +13,7 @@ #define DEBUG_GUI_TEXT 0 /// show basic debug messages for gui::Text - warning this can be hard on cpu #define DEBUG_GUI_TEXT_LINES 0 /// show extended debug messages for gui::Text - lines building #define DEBUG_GUI_TEXT_CURSOR 0 /// show extended debug messages for gui::Text - cursor handling +#define DEBUG_HEAP_ALLOCATIONS 0 /// gather heap allocations statictics #define DEBUG_INPUT_EVENTS 0 /// show input events prints in system #define DEBUG_MISSING_ASSETS 0 /// show debug concerning missing assets #define DEBUG_SCOPED_TIMINGS 0 /// show timings in measured functions diff --git a/products/BellHybrid/BellHybridMain.cpp b/products/BellHybrid/BellHybridMain.cpp index 0582025a7c0303e46d5e893b988c14dee7345f64..9c476534da2dd9710452f0cc580a157694f9a715 100644 --- a/products/BellHybrid/BellHybridMain.cpp +++ b/products/BellHybrid/BellHybridMain.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "PlatformFactory.hpp" @@ -104,10 +104,6 @@ int main() } Log::Logger::get().init(Log::Application{ApplicationName, GIT_REV, VERSION, GIT_BRANCH}); - /// force initialization of PhonenumberUtil because of its stack usage - /// otherwise we would end up with an init race and PhonenumberUtil could - /// be initiated in a task with stack not big enough to handle it - i18n::phonenumbers::PhoneNumberUtil::GetInstance(); return true; }, [sysmgr]() { diff --git a/products/BellHybrid/apps/application-bell-main/windows/BellHomeScreenWindow.cpp b/products/BellHybrid/apps/application-bell-main/windows/BellHomeScreenWindow.cpp index f3656a712c7e175c0fd69555b99d9968117c66bc..6464e52148b063a62d7373e16ed7aadea7b61dba 100644 --- a/products/BellHybrid/apps/application-bell-main/windows/BellHomeScreenWindow.cpp +++ b/products/BellHybrid/apps/application-bell-main/windows/BellHomeScreenWindow.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "BellHomeScreenWindow.hpp" @@ -52,6 +52,8 @@ namespace gui { if (currentLayout) { removeWidget(currentLayout->getLayout()); + delete currentLayout; + currentLayout = nullptr; } currentLayout = layoutGenerator(); addWidget(static_cast(currentLayout->getLayout())); diff --git a/products/BellHybrid/apps/common/src/layouts/HomeScreenLayoutVerticalSimple.cpp b/products/BellHybrid/apps/common/src/layouts/HomeScreenLayoutVerticalSimple.cpp index 479dee3fe139d05034e620d3ac5d4b46fd8d9ba4..1c8ab9f2f4635e25cde3fd27a7324752841b8ce8 100644 --- a/products/BellHybrid/apps/common/src/layouts/HomeScreenLayoutVerticalSimple.cpp +++ b/products/BellHybrid/apps/common/src/layouts/HomeScreenLayoutVerticalSimple.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "layouts/HomeScreenLayoutVerticalSimple.hpp" @@ -35,4 +35,4 @@ namespace gui leftBox->resizeItems(); rightBox->resizeItems(); } -}; // namespace gui +} // namespace gui