diff options
author | TeYuan Wang <kamewang@google.com> | 2022-03-28 20:26:06 +0800 |
---|---|---|
committer | TeYuan Wang <kamewang@google.com> | 2022-04-20 19:59:27 +0800 |
commit | 708a1dfa926bc2ca1f0c9aaa6543ed95c9f1fc89 (patch) | |
tree | 8aeebcf79a58107a98ad8bb24f9b1bcd0f483942 /thermal/utils/power_files.cpp | |
parent | 996a9e16cedb40c0035235e7a81b32742e2a5725 (diff) |
thermal: Introduce PID 2.0
Support dynamically power budget distribution base on real power loading
Bug: 196478280
Test: run burn8 and manhattan and confirm thermal throttling,
Test: Verify thermal powerhint, and thermal event notification with emul_temp
Test: adb shell lshal debug android.hardware.thermal@2.0::IThermal/default
Change-Id: I9741762375f96e9b7c03db857f0e7d78c31eb5ee
Diffstat (limited to 'thermal/utils/power_files.cpp')
-rw-r--r-- | thermal/utils/power_files.cpp | 391 |
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; } |