summaryrefslogtreecommitdiff
path: root/thermal/utils/power_files.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'thermal/utils/power_files.cpp')
-rw-r--r--thermal/utils/power_files.cpp391
1 files changed, 136 insertions, 255 deletions
diff --git a/thermal/utils/power_files.cpp b/thermal/utils/power_files.cpp
index a559454..3561e84 100644
--- a/thermal/utils/power_files.cpp
+++ b/thermal/utils/power_files.cpp
@@ -39,56 +39,20 @@ constexpr std::string_view kEnergyValueNode("energy_value");
using android::base::ReadFileToString;
using android::base::StringPrintf;
-void PowerFiles::setPowerDataToDefault(std::string_view sensor_name) {
- std::unique_lock<std::shared_mutex> _lock(throttling_release_map_mutex_);
- if (!throttling_release_map_.count(sensor_name.data()) ||
- !power_status_map_.count(sensor_name.data())) {
- return;
- }
-
- auto &cdev_release_map = throttling_release_map_.at(sensor_name.data());
- PowerSample power_sample = {};
-
- for (auto &power_status_pair : power_status_map_.at(sensor_name.data())) {
- for (size_t i = 0; i < power_status_pair.second.power_history.size(); ++i) {
- for (size_t j = 0; j < power_status_pair.second.power_history[i].size(); ++j) {
- power_status_pair.second.power_history[i].pop();
- power_status_pair.second.power_history[i].emplace(power_sample);
- }
- }
- power_status_pair.second.last_updated_avg_power = NAN;
- }
-
- for (auto &cdev_release_pair : cdev_release_map) {
- cdev_release_pair.second.release_step = 0;
+bool PowerFiles::registerPowerRailsToWatch(std::string_view config_path) {
+ if (!ParsePowerRailInfo(config_path, &power_rail_info_map_)) {
+ LOG(ERROR) << "Failed to parse power rail info config";
+ return false;
}
-}
-int PowerFiles::getReleaseStep(std::string_view sensor_name, std::string_view cdev_name) {
- int release_step = 0;
- std::shared_lock<std::shared_mutex> _lock(throttling_release_map_mutex_);
-
- if (throttling_release_map_.count(sensor_name.data()) &&
- throttling_release_map_[sensor_name.data()].count(cdev_name.data())) {
- release_step = throttling_release_map_[sensor_name.data()][cdev_name.data()].release_step;
+ if (!power_rail_info_map_.size()) {
+ LOG(INFO) << " No power rail info config found";
+ return true;
}
- return release_step;
-}
-
-bool PowerFiles::registerPowerRailsToWatch(std::string_view sensor_name, std::string_view cdev_name,
- const BindedCdevInfo &binded_cdev_info,
- const CdevInfo &cdev_info,
- const PowerRailInfo &power_rail_info) {
- std::vector<std::queue<PowerSample>> power_history;
- PowerSample power_sample = {
- .energy_counter = 0,
- .duration = 0,
- };
-
- if (throttling_release_map_.count(sensor_name.data()) &&
- throttling_release_map_[sensor_name.data()].count(binded_cdev_info.power_rail)) {
- return true;
+ if (!findEnergySourceToWatch()) {
+ LOG(ERROR) << "Cannot find energy source";
+ return false;
}
if (!energy_info_map_.size() && !updateEnergyValues()) {
@@ -96,50 +60,59 @@ bool PowerFiles::registerPowerRailsToWatch(std::string_view sensor_name, std::st
return false;
}
- if (power_rail_info.virtual_power_rail_info != nullptr &&
- power_rail_info.virtual_power_rail_info->linked_power_rails.size()) {
- for (size_t i = 0; i < power_rail_info.virtual_power_rail_info->linked_power_rails.size();
- ++i) {
- if (energy_info_map_.count(
- power_rail_info.virtual_power_rail_info->linked_power_rails[i])) {
+ for (const auto &power_rail_info_pair : power_rail_info_map_) {
+ std::vector<std::queue<PowerSample>> power_history;
+ if (!power_rail_info_pair.second.power_sample_count ||
+ power_rail_info_pair.second.power_sample_delay == std::chrono::milliseconds::max()) {
+ continue;
+ }
+
+ PowerSample power_sample = {
+ .energy_counter = 0,
+ .duration = 0,
+ };
+
+ if (power_rail_info_pair.second.virtual_power_rail_info != nullptr &&
+ power_rail_info_pair.second.virtual_power_rail_info->linked_power_rails.size()) {
+ for (size_t i = 0;
+ i < power_rail_info_pair.second.virtual_power_rail_info->linked_power_rails.size();
+ ++i) {
+ if (!energy_info_map_.count(power_rail_info_pair.second.virtual_power_rail_info
+ ->linked_power_rails[i])) {
+ LOG(ERROR) << " Could not find energy source "
+ << power_rail_info_pair.second.virtual_power_rail_info
+ ->linked_power_rails[i];
+ return false;
+ }
power_history.emplace_back(std::queue<PowerSample>());
- for (int j = 0; j < power_rail_info.power_sample_count; j++) {
+ for (int j = 0; j < power_rail_info_pair.second.power_sample_count; j++) {
power_history[i].emplace(power_sample);
}
+ }
+ } else {
+ if (energy_info_map_.count(power_rail_info_pair.first)) {
+ power_history.emplace_back(std::queue<PowerSample>());
+ for (int j = 0; j < power_rail_info_pair.second.power_sample_count; j++) {
+ power_history[0].emplace(power_sample);
+ }
} else {
- LOG(ERROR) << "Could not find power rail "
- << power_rail_info.virtual_power_rail_info->linked_power_rails[i];
+ LOG(ERROR) << "Could not find energy source " << power_rail_info_pair.first;
return false;
}
}
- } else {
- if (energy_info_map_.count(power_rail_info.rail)) {
- power_history.emplace_back(std::queue<PowerSample>());
- for (int j = 0; j < power_rail_info.power_sample_count; j++) {
- power_history[0].emplace(power_sample);
- }
+
+ if (power_history.size()) {
+ power_status_map_[power_rail_info_pair.first] = {
+ .power_history = power_history,
+ .last_update_time = boot_clock::time_point::min(),
+ .last_updated_avg_power = NAN,
+ };
} else {
- LOG(ERROR) << "Could not find power rail " << power_rail_info.rail;
+ LOG(ERROR) << "power history size is zero";
return false;
}
+ LOG(INFO) << "Successfully to register power rail " << power_rail_info_pair.first;
}
-
- if (power_history.size()) {
- throttling_release_map_[sensor_name.data()][cdev_name.data()] = {
- .release_step = 0,
- .max_release_step = cdev_info.max_state,
- };
- power_status_map_[sensor_name.data()][binded_cdev_info.power_rail] = {
- .power_history = power_history,
- .time_remaining = power_rail_info.power_sample_delay,
- .last_updated_avg_power = NAN,
- };
- } else {
- return false;
- }
-
- LOG(INFO) << "Sensor " << sensor_name.data() << " successfully registers power rail "
- << binded_cdev_info.power_rail << " for cooling device " << cdev_name.data();
return true;
}
@@ -179,10 +152,6 @@ bool PowerFiles::findEnergySourceToWatch(void) {
return true;
}
-void PowerFiles::clearEnergyInfoMap(void) {
- energy_info_map_.clear();
-}
-
bool PowerFiles::updateEnergyValues(void) {
std::string deviceEnergyContent;
std::string deviceEnergyContents;
@@ -200,7 +169,6 @@ bool PowerFiles::updateEnergyValues(void) {
std::istringstream energyData(deviceEnergyContents);
- clearEnergyInfoMap();
while (std::getline(energyData, line)) {
/* Read rail energy */
uint64_t energy_counter = 0;
@@ -241,215 +209,128 @@ bool PowerFiles::updateEnergyValues(void) {
return true;
}
-bool PowerFiles::getAveragePower(std::string_view power_rail,
- std::queue<PowerSample> *power_history, bool power_sample_update,
- float *avg_power) {
- bool ret = true;
- const auto last_sample = power_history->front();
+float PowerFiles::updateAveragePower(std::string_view power_rail,
+ std::queue<PowerSample> *power_history) {
+ float avg_power = NAN;
if (!energy_info_map_.count(power_rail.data())) {
LOG(ERROR) << " Could not find power rail " << power_rail.data();
- return false;
+ return avg_power;
}
+ const auto last_sample = power_history->front();
const auto curr_sample = energy_info_map_.at(power_rail.data());
const auto duration = curr_sample.duration - last_sample.duration;
const auto deltaEnergy = curr_sample.energy_counter - last_sample.energy_counter;
if (!last_sample.duration) {
- LOG(VERBOSE) << "Power rail " << power_rail.data() << ": the last energy timestamp is zero";
+ LOG(VERBOSE) << "Power rail " << power_rail.data()
+ << ": all power samples have not been collected yet";
} else if (duration <= 0 || deltaEnergy < 0) {
LOG(ERROR) << "Power rail " << power_rail.data() << " is invalid: duration = " << duration
<< ", deltaEnergy = " << deltaEnergy;
- ret = false;
+ return avg_power;
} else {
- *avg_power = static_cast<float>(deltaEnergy) / static_cast<float>(duration);
- LOG(VERBOSE) << "Power rail " << power_rail.data() << ", avg power = " << *avg_power
+ avg_power = static_cast<float>(deltaEnergy) / static_cast<float>(duration);
+ LOG(VERBOSE) << "Power rail " << power_rail.data() << ", avg power = " << avg_power
<< ", duration = " << duration << ", deltaEnergy = " << deltaEnergy;
}
- if (power_sample_update) {
- power_history->pop();
- power_history->push(curr_sample);
- }
+ power_history->pop();
+ power_history->push(curr_sample);
- return ret;
+ return avg_power;
}
-bool PowerFiles::computeAveragePower(const PowerRailInfo &power_rail_info,
- PowerStatus *power_status, bool power_sample_update,
- float *avg_power) {
- bool ret = true;
-
- float avg_power_val = -1;
- float offset = power_rail_info.virtual_power_rail_info->offset;
- for (size_t i = 0; i < power_rail_info.virtual_power_rail_info->linked_power_rails.size();
- i++) {
- float coefficient = power_rail_info.virtual_power_rail_info->coefficients[i];
- float avg_power_number = -1;
- if (!getAveragePower(power_rail_info.virtual_power_rail_info->linked_power_rails[i],
- &power_status->power_history[i], power_sample_update,
- &avg_power_number)) {
- ret = false;
- continue;
- } else if (avg_power_number < 0) {
- continue;
- }
- switch (power_rail_info.virtual_power_rail_info->formula) {
- case FormulaOption::COUNT_THRESHOLD:
- if ((coefficient < 0 && avg_power_number < -coefficient) ||
- (coefficient >= 0 && avg_power_number >= coefficient))
- avg_power_val += 1;
- break;
- case FormulaOption::WEIGHTED_AVG:
- avg_power_val += avg_power_number * coefficient;
- break;
- case FormulaOption::MAXIMUM:
- if (i == 0)
- avg_power_val = std::numeric_limits<float>::lowest();
- if (avg_power_number * coefficient > avg_power_val)
- avg_power_val = avg_power_number * coefficient;
- break;
- case FormulaOption::MINIMUM:
- if (i == 0)
- avg_power_val = std::numeric_limits<float>::max();
- if (avg_power_number * coefficient < avg_power_val)
- avg_power_val = avg_power_number * coefficient;
- break;
- default:
- break;
- }
- }
- if (avg_power_val >= 0) {
- avg_power_val = avg_power_val + offset;
- }
+float PowerFiles::updatePowerRail(std::string_view power_rail) {
+ float avg_power = NAN;
- *avg_power = avg_power_val;
- return ret;
-}
-
-bool PowerFiles::throttlingReleaseUpdate(std::string_view sensor_name, std::string_view cdev_name,
- const ThrottlingSeverity severity,
- const std::chrono::milliseconds time_elapsed_ms,
- const BindedCdevInfo &binded_cdev_info,
- const PowerRailInfo &power_rail_info,
- bool power_sample_update, bool severity_changed) {
- std::unique_lock<std::shared_mutex> _lock(throttling_release_map_mutex_);
- float avg_power = -1;
+ if (!power_rail_info_map_.count(power_rail.data())) {
+ return avg_power;
+ }
- ATRACE_CALL();
- if (!throttling_release_map_.count(sensor_name.data()) ||
- !throttling_release_map_[sensor_name.data()].count(cdev_name.data()) ||
- !power_status_map_.count(sensor_name.data()) ||
- !power_status_map_[sensor_name.data()].count(binded_cdev_info.power_rail)) {
- return false;
+ if (!power_status_map_.count(power_rail.data())) {
+ return avg_power;
}
- auto &release_status = throttling_release_map_[sensor_name.data()].at(cdev_name.data());
- auto &power_status = power_status_map_[sensor_name.data()].at(binded_cdev_info.power_rail);
+ const auto &power_rail_info = power_rail_info_map_.at(power_rail.data());
+ auto &power_status = power_status_map_.at(power_rail.data());
- if (power_sample_update) {
- if (time_elapsed_ms > power_status.time_remaining) {
- power_status.time_remaining = power_rail_info.power_sample_delay;
- } else {
- power_status.time_remaining = power_status.time_remaining - time_elapsed_ms;
- LOG(VERBOSE) << "Power rail " << binded_cdev_info.power_rail
- << " : timeout remaining = " << power_status.time_remaining.count();
- if (!severity_changed) {
- return true;
- } else {
- // get the cached average power when thermal severity is changed
- power_sample_update = false;
- }
- }
- } else if (!severity_changed &&
- power_status.time_remaining != power_rail_info.power_sample_delay) {
- return false;
+ boot_clock::time_point now = boot_clock::now();
+ auto time_elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
+ now - power_status.last_update_time);
+
+ if (power_status.last_update_time != boot_clock::time_point::min() &&
+ time_elapsed_ms < power_rail_info.power_sample_delay) {
+ return power_status.last_updated_avg_power;
}
if (!energy_info_map_.size() && !updateEnergyValues()) {
LOG(ERROR) << "Failed to update energy values";
- release_status.release_step = 0;
- return false;
+ return avg_power;
}
- if (!power_sample_update && !std::isnan(power_status.last_updated_avg_power)) {
- avg_power = power_status.last_updated_avg_power;
+ if (power_rail_info.virtual_power_rail_info == nullptr) {
+ avg_power = updateAveragePower(power_rail, &power_status.power_history[0]);
} else {
- // Return false if we cannot get the average power of the target power rail
- if (!((power_rail_info.virtual_power_rail_info == nullptr)
- ? getAveragePower(binded_cdev_info.power_rail, &power_status.power_history[0],
- power_sample_update, &avg_power)
- : computeAveragePower(power_rail_info, &power_status, power_sample_update,
- &avg_power))) {
- release_status.release_step = 0;
- if (binded_cdev_info.throttling_with_power_link) {
- release_status.release_step = release_status.max_release_step;
- }
- return false;
- } else if (avg_power < 0) {
- if (binded_cdev_info.throttling_with_power_link) {
- release_status.release_step = release_status.max_release_step;
+ const auto offset = power_rail_info.virtual_power_rail_info->offset;
+ float avg_power_val = 0.0;
+ for (size_t i = 0; i < power_rail_info.virtual_power_rail_info->linked_power_rails.size();
+ i++) {
+ float coefficient = power_rail_info.virtual_power_rail_info->coefficients[i];
+ float avg_power_number = updateAveragePower(
+ power_rail_info.virtual_power_rail_info->linked_power_rails[i],
+ &power_status.power_history[i]);
+
+ switch (power_rail_info.virtual_power_rail_info->formula) {
+ case FormulaOption::COUNT_THRESHOLD:
+ if ((coefficient < 0 && avg_power_number < -coefficient) ||
+ (coefficient >= 0 && avg_power_number >= coefficient))
+ avg_power_val += 1;
+ break;
+ case FormulaOption::WEIGHTED_AVG:
+ avg_power_val += avg_power_number * coefficient;
+ break;
+ case FormulaOption::MAXIMUM:
+ if (i == 0)
+ avg_power_val = std::numeric_limits<float>::lowest();
+ if (avg_power_number * coefficient > avg_power_val)
+ avg_power_val = avg_power_number * coefficient;
+ break;
+ case FormulaOption::MINIMUM:
+ if (i == 0)
+ avg_power_val = std::numeric_limits<float>::max();
+ if (avg_power_number * coefficient < avg_power_val)
+ avg_power_val = avg_power_number * coefficient;
+ break;
+ default:
+ break;
}
- return true;
}
+ if (avg_power_val >= 0) {
+ avg_power_val = avg_power_val + offset;
+ }
+
+ avg_power = avg_power_val;
+ }
+
+ if (avg_power < 0) {
+ avg_power = NAN;
}
power_status.last_updated_avg_power = avg_power;
- bool is_over_budget = true;
- if (!binded_cdev_info.high_power_check) {
- if (avg_power < binded_cdev_info.power_thresholds[static_cast<int>(severity)]) {
- is_over_budget = false;
- }
- } else {
- if (avg_power > binded_cdev_info.power_thresholds[static_cast<int>(severity)]) {
- is_over_budget = false;
- }
+ power_status.last_update_time = now;
+ return avg_power;
+}
+
+bool PowerFiles::refreshPowerStatus(void) {
+ if (!updateEnergyValues()) {
+ LOG(ERROR) << "Failed to update energy values";
+ return false;
}
- LOG(INFO) << "Power rail " << binded_cdev_info.power_rail << ": power threshold = "
- << binded_cdev_info.power_thresholds[static_cast<int>(severity)]
- << ", avg power = " << avg_power;
-
- switch (binded_cdev_info.release_logic) {
- case ReleaseLogic::INCREASE:
- if (!is_over_budget) {
- if (std::abs(release_status.release_step) <
- static_cast<int>(release_status.max_release_step)) {
- release_status.release_step--;
- }
- } else {
- release_status.release_step = 0;
- }
- break;
- case ReleaseLogic::DECREASE:
- if (!is_over_budget) {
- if (release_status.release_step <
- static_cast<int>(release_status.max_release_step)) {
- release_status.release_step++;
- }
- } else {
- release_status.release_step = 0;
- }
- break;
- case ReleaseLogic::STEPWISE:
- if (!is_over_budget) {
- if (release_status.release_step <
- static_cast<int>(release_status.max_release_step)) {
- release_status.release_step++;
- }
- } else {
- if (std::abs(release_status.release_step) <
- static_cast<int>(release_status.max_release_step)) {
- release_status.release_step--;
- }
- }
- break;
- case ReleaseLogic::RELEASE_TO_FLOOR:
- release_status.release_step = is_over_budget ? 0 : release_status.max_release_step;
- break;
- case ReleaseLogic::NONE:
- default:
- break;
+
+ for (const auto &power_status_pair : power_status_map_) {
+ updatePowerRail(power_status_pair.first);
}
return true;
}