/* * * Copyright (c) 2021 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "MemMonitoring.h" #include "AppConfig.h" #include #include #include namespace chip { namespace DeviceLayer { namespace Silabs { static osThreadId_t sMonitorThreadHandle; constexpr uint32_t kMonitorTaskSize = 1024; static uint8_t monitorStack[kMonitorTaskSize]; static osThread_t sMonitorTaskControlBlock; constexpr osThreadAttr_t kMonitorTaskAttr = { .name = "MemMonitor", .attr_bits = osThreadDetached, .cb_mem = &sMonitorTaskControlBlock, .cb_size = osThreadCbSize, .stack_mem = monitorStack, .stack_size = kMonitorTaskSize, .priority = osPriorityLow }; size_t nbAllocSuccess = 0; size_t nbFreeSuccess = 0; size_t largestBlockAllocated = 0; void MemMonitoring::StartMonitor() { sMonitorThreadHandle = osThreadNew(MonitorTask, nullptr, &kMonitorTaskAttr); } void MemMonitoring::MonitorTask(void * pvParameter) { uint32_t threadCount = osThreadGetCount(); osThreadId_t * threadIdTable = new osThreadId_t[threadCount]; // Forms a table of the active thread ids osThreadEnumerate(threadIdTable, threadCount); while (true) { SILABS_LOG("============================="); SILABS_LOG(" "); SILABS_LOG("Largest Block allocated %lu B", largestBlockAllocated); SILABS_LOG("Number Of Successful Alloc %lu", nbAllocSuccess); SILABS_LOG("Number Of Successful Frees %lu", nbFreeSuccess); SILABS_LOG(" "); SILABS_LOG("Thread stack highwatermark "); for (uint8_t tIdIndex = 0; tIdIndex < threadCount; tIdIndex++) { osThreadId_t tId = threadIdTable[tIdIndex]; if (tId != sMonitorThreadHandle) // don't print stats for this current debug thread. { // The smallest amount of free stack space there has been since the thread creation SILABS_LOG("\t%-10s : %6lu B", osThreadGetName(tId), osThreadGetStackSpace(tId)); } } SILABS_LOG(" "); SILABS_LOG("============================="); // run loop every 5 seconds osDelay(osKernelGetTickFreq() * 5); } // will never get here. Still, free allocated memory before exiting delete threadIdTable; } } // namespace Silabs } // namespace DeviceLayer } // namespace chip extern "C" void memMonitoringTrackAlloc(void * ptr, size_t size) { if (ptr != NULL) { chip::DeviceLayer::Silabs::nbAllocSuccess++; if (chip::DeviceLayer::Silabs::largestBlockAllocated < size) { chip::DeviceLayer::Silabs::largestBlockAllocated = size; } } } extern "C" void memMonitoringTrackFree(void * ptr, size_t size) { chip::DeviceLayer::Silabs::nbFreeSuccess++; }