M harmony_changelog.md => harmony_changelog.md +1 -0
@@ 11,6 11,7 @@
* Fixed frequency lock during user activity
* Fixed possibility of OS crash during update package size check
* Fixed incorrect calculation of requested CPU frequency
+* Fixed CPU frequency setting when dumping logs to a file
### Added
* Files not fully transferred via Center will be now removed when USB cable is unplugged
M module-sys/SystemManager/CMakeLists.txt => module-sys/SystemManager/CMakeLists.txt +1 -0
@@ 14,6 14,7 @@ target_sources(sys-manager
PRIVATE
CpuGovernor.cpp
CpuSentinel.cpp
+ LogSentinel.cpp
GovernorSentinelOperations.cpp
CpuStatistics.cpp
TaskStatistics.cpp
A module-sys/SystemManager/LogSentinel.cpp => module-sys/SystemManager/LogSentinel.cpp +69 -0
@@ 0,0 1,69 @@
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include <SystemManager/LogSentinel.hpp>
+#include <log/log.hpp>
+
+namespace sys
+{
+ namespace
+ {
+ constexpr std::uint32_t holdMutexTimeoutMs{100000};
+ constexpr auto sentinelName{"LoggerSentinel"};
+ constexpr auto holdFrequencyReason{"LogDump"};
+ } // namespace
+
+ LogSentinel::LogSentinel(bsp::CpuFrequencyMHz frequencyToLock) : requestedFrequency(frequencyToLock)
+ {
+ mutex = xSemaphoreCreateMutex();
+ if (mutex == NULL) {
+ LOG_ERROR("Failed to create mutex for logger!");
+ }
+ }
+
+ void LogSentinel::HoldMinimumFrequency()
+ {
+ frequencyRequest = true;
+ if (mutex != NULL) {
+ if (xSemaphoreTake(mutex, pdMS_TO_TICKS(holdMutexTimeoutMs)) != pdTRUE) {
+ LOG_ERROR("Failed to get mutex for the logger!");
+ }
+ }
+ frequencyRequest = false;
+ }
+
+ void LogSentinel::ReleaseMinimumFrequency()
+ {
+ if (mutex != NULL) {
+ xSemaphoreGive(mutex);
+ }
+ }
+
+ void LogSentinel::UpdateCurrentFrequency(bsp::CpuFrequencyMHz newFrequency)
+ {
+ const bool newPermission = newFrequency >= requestedFrequency;
+ if (mutex != NULL && dumpPermission != newPermission) {
+ if (newPermission) {
+ xSemaphoreGive(mutex);
+ }
+ else if (xSemaphoreTake(mutex, 0) != pdTRUE) {
+ LOG_ERROR("Failed to get mutex when reducing the CPU frequency!");
+ return;
+ }
+ }
+ dumpPermission = newPermission;
+ }
+
+ [[nodiscard]] auto LogSentinel::GetRequestedFrequency() const noexcept -> sentinel::View
+ {
+ sentinel::View view{.ownerTCBNumber = 0,
+ .name = sentinelName,
+ .minFrequency = (frequencyRequest ||
+ ((mutex != NULL) && dumpPermission && (uxSemaphoreGetCount(mutex) == 0)))
+ ? requestedFrequency
+ : bsp::CpuFrequencyMHz::Level_0,
+ .reason = holdFrequencyReason};
+ return view;
+ }
+
+} // namespace sys
M module-sys/SystemManager/PowerManager.cpp => module-sys/SystemManager/PowerManager.cpp +16 -1
@@ 10,6 10,7 @@
#include <SystemManager/PowerManager.hpp>
#include <gsl/util>
#include <log/log.hpp>
+#include <Logger.hpp>
#include <Utils.hpp>
namespace sys
@@ 19,6 20,8 @@ namespace sys
constexpr auto lowestLevelName{"lowestCpuFrequency"};
constexpr auto middleLevelName{"middleCpuFrequency"};
constexpr auto highestLevelName{"highestCpuFrequency"};
+
+ constexpr bsp::CpuFrequencyMHz logDumpFrequencyToHold{bsp::CpuFrequencyMHz::Level_4};
} // namespace
CpuFrequencyMonitor::CpuFrequencyMonitor(const std::string &name) : levelName(name)
@@ 60,6 63,9 @@ namespace sys
driverSEMC = drivers::DriverSEMC::Create(drivers::name::ExternalRAM);
lowPowerControl = bsp::LowPowerMode::Create().value_or(nullptr);
cpuGovernor = std::make_unique<CpuGovernor>();
+ logSentinel = std::make_unique<LogSentinel>(logDumpFrequencyToHold);
+ Log::Logger::get().preDumpToFile = [this]() { logSentinel->HoldMinimumFrequency(); };
+ Log::Logger::get().postDumpToFile = [this]() { logSentinel->ReleaseMinimumFrequency(); };
cpuAlgorithms = std::make_unique<cpu::AlgorithmFactory>();
cpuAlgorithms->emplace(sys::cpu::AlgoID::ImmediateUpscale, std::make_unique<sys::cpu::ImmediateUpscale>());
@@ 107,7 113,7 @@ namespace sys
uint32_t cpuLoad = cpuStatistics.GetPercentageCpuLoad();
cpu::UpdateResult retval;
const cpu::AlgorithmData data{
- cpuLoad, lowPowerControl->GetCurrentFrequencyLevel(), cpuGovernor->GetMinimumFrequencyRequested()};
+ cpuLoad, lowPowerControl->GetCurrentFrequencyLevel(), GetMinimumCpuFrequencyRequested()};
auto _ = gsl::finally([&retval, this, data] {
retval.frequencySet = lowPowerControl->GetCurrentFrequencyLevel();
@@ 174,10 180,19 @@ namespace sys
UpdateCpuFrequencyMonitor(lowPowerControl->GetCurrentFrequencyLevel());
while (lowPowerControl->GetCurrentFrequencyLevel() != freq) {
lowPowerControl->SetCpuFrequency(freq);
+ logSentinel->UpdateCurrentFrequency(freq);
cpuGovernor->InformSentinelsAboutCpuFrequencyChange(freq);
}
}
+ [[nodiscard]] auto PowerManager::GetMinimumCpuFrequencyRequested() const noexcept -> sentinel::View
+ {
+ const auto governorSentinelsView = cpuGovernor->GetMinimumFrequencyRequested();
+ const auto logSentinelView = logSentinel->GetRequestedFrequency();
+ return (logSentinelView.minFrequency > governorSentinelsView.minFrequency) ? logSentinelView
+ : governorSentinelsView;
+ }
+
[[nodiscard]] auto PowerManager::getExternalRamDevice() const noexcept -> std::shared_ptr<devices::Device>
{
return driverSEMC;
A module-sys/SystemManager/include/SystemManager/LogSentinel.hpp => module-sys/SystemManager/include/SystemManager/LogSentinel.hpp +29 -0
@@ 0,0 1,29 @@
+// 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 <mutex.hpp>
+#include <bsp/common.hpp>
+#include "SentinelView.hpp"
+
+namespace sys
+{
+ class LogSentinel
+ {
+ public:
+ explicit LogSentinel(bsp::CpuFrequencyMHz frequencyToLock);
+
+ void HoldMinimumFrequency();
+ void ReleaseMinimumFrequency();
+ void UpdateCurrentFrequency(bsp::CpuFrequencyMHz newFrequency);
+ [[nodiscard]] auto GetRequestedFrequency() const noexcept -> sentinel::View;
+
+ private:
+ xSemaphoreHandle mutex;
+ bsp::CpuFrequencyMHz requestedFrequency{bsp::CpuFrequencyMHz::Level_0};
+ bool dumpPermission{true};
+ bool frequencyRequest{false};
+ };
+
+} // namespace sys
M module-sys/SystemManager/include/SystemManager/PowerManager.hpp => module-sys/SystemManager/include/SystemManager/PowerManager.hpp +3 -0
@@ 9,6 9,7 @@
#include "drivers/semc/DriverSEMC.hpp"
#include "SysCpuUpdateResult.hpp"
#include "CpuGovernor.hpp"
+#include "LogSentinel.hpp"
#include "TaskStatistics.hpp"
#include <bsp/lpm/PowerProfile.hpp>
#include <vector>
@@ 75,6 76,7 @@ namespace sys
void SetCpuFrequency(bsp::CpuFrequencyMHz freq);
void UpdateCpuFrequencyMonitor(bsp::CpuFrequencyMHz currentFreq);
+ [[nodiscard]] auto GetMinimumCpuFrequencyRequested() const noexcept -> sentinel::View;
TickType_t lastCpuFrequencyChangeTimestamp{0};
TickType_t lastLogStatisticsTimestamp{0};
@@ 84,6 86,7 @@ namespace sys
std::shared_ptr<drivers::DriverSEMC> driverSEMC;
std::unique_ptr<bsp::LowPowerMode> lowPowerControl;
std::unique_ptr<CpuGovernor> cpuGovernor;
+ std::unique_ptr<LogSentinel> logSentinel;
const bsp::PowerProfile powerProfile;
std::unique_ptr<sys::cpu::AlgorithmFactory> cpuAlgorithms;
M module-utils/log/CMakeLists.txt => module-utils/log/CMakeLists.txt +1 -0
@@ 20,6 20,7 @@ target_link_libraries(log
utility
purefs-paths
crashdump-metadata-store
+ Microsoft.GSL::GSL
PUBLIC
module-os
log-api
M module-utils/log/Logger.cpp => module-utils/log/Logger.cpp +10 -0
@@ 7,6 7,7 @@
#include <purefs/filesystem_paths.hpp>
#include <fstream>
#include <CrashdumpMetadataStore.hpp>
+#include <gsl/util>
namespace
{
@@ 187,6 188,15 @@ namespace Log
/// @return: 1 - log flush successflul
int Logger::dumpToFile(const std::filesystem::path &logDirectoryPath, LoggerState loggerState)
{
+ if (preDumpToFile != nullptr) {
+ preDumpToFile();
+ }
+ auto _ = gsl::finally([this] {
+ if (postDumpToFile != nullptr) {
+ postDumpToFile();
+ }
+ });
+
if (logFileName.empty()) {
const auto &osMetadata = Store::CrashdumpMetadata::getInstance().getMetadataString();
logFileName = std::string(logFileNamePrefix) + logFileNameSeparator + osMetadata + logFileNameExtension;
M module-utils/log/Logger.hpp => module-utils/log/Logger.hpp +5 -0
@@ 56,6 56,11 @@ namespace Log
int flushLogs();
[[nodiscard]] std::size_t getMaxLineLength();
+ /// functions called immediately before and after dumping logs to a file
+ /// created to synchronize necessary peripherals with the CPU frequency
+ std::function<void()> preDumpToFile;
+ std::function<void()> postDumpToFile;
+
static constexpr auto CRIT_STR = "CRIT";
static constexpr auto IRQ_STR = "IRQ";
M pure_changelog.md => pure_changelog.md +1 -0
@@ 14,6 14,7 @@
* Fixed possible crash when entering phone number
* Fixed incorrect calculation of requested CPU frequency
+* Fixed CPU frequency setting when dumping logs to a file
## [1.9.0 2023-10-19]