| // Copyright 2022 The ChromiumOS Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "discod/control_loop.h" |
| |
| #include <memory> |
| #include <utility> |
| |
| #include <base/logging.h> |
| #include <base/bind.h> |
| #include <base/threading/thread.h> |
| #include <base/time/time.h> |
| #include <brillo/blkdev_utils/disk_iostat.h> |
| |
| #include "discod/controls/ufs_write_booster_control_logic.h" |
| #include "discod/metrics/metrics.h" |
| |
| namespace discod { |
| |
| namespace { |
| |
| void LogControlLoopStatus(Status status) { |
| if (!status.ok()) { |
| LOG(ERROR) << status; |
| } |
| } |
| |
| } // namespace |
| |
| ControlLoop::ControlLoop( |
| std::unique_ptr<UfsWriteBoosterControlLogic> ufs_write_boost_control_logic, |
| std::unique_ptr<brillo::DiskIoStat> disk_io_stat, |
| std::unique_ptr<Metrics> metrics) |
| : base::Thread("discod_control_loop"), |
| ufs_write_boost_control_logic_(std::move(ufs_write_boost_control_logic)), |
| disk_io_stat_(std::move(disk_io_stat)), |
| metrics_(std::move(metrics)) {} |
| |
| void ControlLoop::StartControlLogic() { |
| VLOG(3) << __func__; |
| WaitUntilThreadStarted(); |
| LogControlLoopStatus(ufs_write_boost_control_logic_->Reset()); |
| ScheduleControlLogicTick(); |
| } |
| |
| void ControlLoop::EnableWriteBoost() { |
| VLOG(3) << __func__; |
| if (!IsRunning()) { |
| VLOG(3) << "Control Loop is not running"; |
| return; |
| } |
| task_runner()->PostTask(FROM_HERE, |
| base::BindOnce(&ControlLoop::HandleEnableWriteBooster, |
| base::Unretained(this))); |
| } |
| |
| void ControlLoop::HandleControlLogic() { |
| VLOG(3) << __func__; |
| std::optional<brillo::DiskIoStat::Snapshot> snapshot = |
| disk_io_stat_->GetSnapshot(); |
| |
| if (snapshot.has_value()) { |
| if (latest_snapshot_.IsValid()) { |
| LogControlLoopStatus(ufs_write_boost_control_logic_->Update( |
| snapshot->Delta(latest_snapshot_))); |
| } |
| latest_snapshot_ = snapshot.value(); |
| } |
| |
| ScheduleControlLogicTick(); |
| } |
| |
| void ControlLoop::HandleEnableWriteBooster() { |
| VLOG(3) << __func__; |
| LogControlLoopStatus(ufs_write_boost_control_logic_->Enable()); |
| } |
| |
| void ControlLoop::ScheduleControlLogicTick() { |
| VLOG(3) << __func__; |
| if (!IsRunning()) { |
| VLOG(3) << "Control Loop is not running"; |
| return; |
| } |
| task_runner()->PostDelayedTask( |
| FROM_HERE, |
| base::BindOnce(&ControlLoop::HandleControlLogic, base::Unretained(this)), |
| base::Seconds(1)); |
| } |
| |
| } // namespace discod |