~aleteoryx/muditaos

69e5fe52231248586d8590cc4017d52d1425700f — Maciej Gibowicz 3 years ago f050305
[MOS-144] Fix Increased CPU usage

On the locked screen, while refreshing the screen,
the CPU woke up to the maximum frequency,
which resulted in an increased power consumption.
M module-services/service-evtmgr/EventManager.cpp => module-services/service-evtmgr/EventManager.cpp +5 -13
@@ 56,18 56,6 @@ namespace
    constexpr auto loggerTimerName = "Logger";
} // namespace

EventManagerSentinel::EventManagerSentinel(std::shared_ptr<sys::CpuSentinel> cpuSentinel,
                                           bsp::CpuFrequencyMHz frequencyToHold)
    : cpuSentinel(cpuSentinel)
{
    cpuSentinel->HoldMinimumFrequency(frequencyToHold);
}

EventManagerSentinel::~EventManagerSentinel()
{
    cpuSentinel->ReleaseMinimumFrequency();
}

EventManagerCommon::EventManagerCommon(LogDumpFunction logDumpFunction, const std::string &name)
    : sys::Service(name, "", stackDepth), loggerTimer{sys::TimerFactory::createPeriodicTimer(
                                              this,


@@ 232,7 220,7 @@ sys::ReturnCodes EventManagerCommon::InitHandler()
    EventWorker->init(settings);
    EventWorker->run();

    cpuSentinel                  = std::make_shared<sys::CpuSentinel>(service::name::evt_manager, this);
    cpuSentinel                  = std::make_shared<sys::TimedCpuSentinel>(service::name::evt_manager, this);
    auto sentinelRegistrationMsg = std::make_shared<sys::SentinelRegistrationMessage>(cpuSentinel);
    bus.sendUnicast(sentinelRegistrationMsg, service::name::system_manager);



@@ 321,6 309,10 @@ int EventManagerCommon::dumpLogsToFile()

void EventManagerCommon::handleMinuteUpdate(time_t timestamp)
{
    // temporary frequency lock to handle time update event
    if (cpuSentinel) {
        cpuSentinel->HoldMinimumFrequencyForTime(bsp::CpuFrequencyMHz::Level_2, std::chrono::seconds(1));
    }
    if (onMinuteTick) {
        onMinuteTick(timestamp);
    }

M module-services/service-evtmgr/service-evtmgr/EventManagerCommon.hpp => module-services/service-evtmgr/service-evtmgr/EventManagerCommon.hpp +1 -11
@@ 23,16 23,6 @@

class WorkerEventCommon;

class EventManagerSentinel
{
  public:
    explicit EventManagerSentinel(std::shared_ptr<sys::CpuSentinel> cpuSentinel, bsp::CpuFrequencyMHz frequencyToHold);
    ~EventManagerSentinel();

  private:
    std::shared_ptr<sys::CpuSentinel> cpuSentinel;
};

class EventManagerCommon : public sys::Service
{
  public:


@@ 83,7 73,7 @@ class EventManagerCommon : public sys::Service

    std::shared_ptr<settings::Settings> settings;
    std::unique_ptr<WorkerEventCommon> EventWorker;
    std::shared_ptr<sys::CpuSentinel> cpuSentinel;
    std::shared_ptr<sys::TimedCpuSentinel> cpuSentinel;
    // application where key events are sent. This is also only application that is allowed to change keyboard long
    // press settings.
    std::string targetApplication;

M module-sys/SystemManager/CpuSentinel.cpp => module-sys/SystemManager/CpuSentinel.cpp +30 -1
@@ 1,13 1,18 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <SystemManager/CpuSentinel.hpp>
#include "system/messages/RequestCpuFrequencyMessage.hpp"
#include "system/Constants.hpp"
#include <Timers/TimerFactory.hpp>
#include <memory>

namespace sys
{
    namespace
    {
        constexpr std::chrono::seconds defaultHoldFrequencyTime{1};
    } // namespace

    CpuSentinel::CpuSentinel(std::string name,
                             sys::Service *service,


@@ 106,4 111,28 @@ namespace sys
            permanentFrequencyToHold.frequencyToHold = currentFrequency;
        }
    }

    TimedCpuSentinel::TimedCpuSentinel(std::string name, sys::Service *service)
        : CpuSentinel(name, service), timerHandle{sys::TimerFactory::createSingleShotTimer(
                                          owner, "holdFrequencyTimer", defaultHoldFrequencyTime, [this](sys::Timer &) {
                                              ReleaseMinimumFrequency();
                                          })}
    {}

    TimedCpuSentinel::~TimedCpuSentinel()
    {
        if (timerHandle.isActive()) {
            timerHandle.stop();
        }
    }

    void TimedCpuSentinel::HoldMinimumFrequencyForTime(bsp::CpuFrequencyMHz frequencyToHold,
                                                       std::chrono::milliseconds timeout)
    {
        if (currentFrequencyToHold != frequencyToHold) {
            HoldMinimumFrequency(frequencyToHold);
            timerHandle.restart(timeout);
        }
    }

} // namespace sys

M module-sys/SystemManager/include/SystemManager/CpuSentinel.hpp => module-sys/SystemManager/include/SystemManager/CpuSentinel.hpp +14 -1
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 9,6 9,7 @@
#include <string>
#include <functional>
#include <atomic>
#include <Timers/TimerHandle.hpp>

namespace sys
{


@@ 61,4 62,16 @@ namespace sys
        TaskHandle_t taskHandle = nullptr;
    };

    /// Sentinel releases the frequency lock automatically after the time specified in the parameter - timeout
    class TimedCpuSentinel : public CpuSentinel
    {
      public:
        TimedCpuSentinel(std::string name, sys::Service *service);
        ~TimedCpuSentinel();
        void HoldMinimumFrequencyForTime(bsp::CpuFrequencyMHz frequencyToHold, std::chrono::milliseconds timeout);

      private:
        sys::TimerHandle timerHandle;
    };

} // namespace sys

M module-sys/SystemManager/tests/unittest_CpuSentinelsGovernor.cpp => module-sys/SystemManager/tests/unittest_CpuSentinelsGovernor.cpp +33 -4
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#define CATCH_CONFIG_MAIN


@@ 7,13 7,42 @@
#include <SystemManager/CpuGovernor.hpp>
#include <SystemManager/CpuSentinel.hpp>

namespace sys
{
    class MockedService : public sys::Service
    {
      public:
        MockedService(const std::string &name) : sys::Service(name)
        {}

        sys::ReturnCodes InitHandler() override
        {
            return sys::ReturnCodes::Success;
        }
        sys::ReturnCodes DeinitHandler() override
        {
            return sys::ReturnCodes::Success;
        }
        sys::ReturnCodes SwitchPowerModeHandler(const sys::ServicePowerMode mode) override
        {
            return sys::ReturnCodes::Success;
        }
        sys::MessagePointer DataReceivedHandler(sys::DataMessage *req, sys::ResponseMessage *resp) override
        {
            return std::make_shared<sys::ResponseMessage>();
        };
    };

} // namespace sys

TEST_CASE("Power Manager CPU sentinels governor test")
{
    using namespace sys;
    auto mockedService                          = std::make_shared<MockedService>("TestService");
    std::shared_ptr<CpuSentinel> testSentinel_0 = nullptr;
    auto testSentinel_1                         = std::make_shared<CpuSentinel>("testSentinel_1", nullptr);
    auto testSentinel_2                         = std::make_shared<CpuSentinel>("testSentinel_2", nullptr);
    auto testSentinel_3                         = std::make_shared<CpuSentinel>("testSentinel_1", nullptr);
    auto testSentinel_1                         = std::make_shared<CpuSentinel>("testSentinel_1", mockedService.get());
    auto testSentinel_2                         = std::make_shared<CpuSentinel>("testSentinel_2", mockedService.get());
    auto testSentinel_3                         = std::make_shared<CpuSentinel>("testSentinel_1", mockedService.get());

    SECTION("Sentinel registration")
    {