| // Copyright 2015 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "thermald/cpufreq_device.h" |
| |
| #include <string> |
| #include <vector> |
| |
| #include "base/check.h" |
| #include "base/files/file_enumerator.h" |
| #include "base/files/file_util.h" |
| #include "base/logging.h" |
| #include "base/strings/stringprintf.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/strings/string_split.h" |
| #include "base/strings/string_util.h" |
| |
| static const char *kCpuSysfsDir = "/sys/devices/system/cpu"; |
| |
| using std::string; |
| using std::vector; |
| |
| namespace thermald { |
| |
| CpufreqDevice::CpufreqDevice(int cpu_id) |
| : cpu_id_(cpu_id), |
| sysfs_base_path_(base::StringPrintf("%s/cpu%d/cpufreq", kCpuSysfsDir, |
| cpu_id)) { |
| } |
| |
| bool CpufreqDevice::SetMaximumFrequency(int max_frequency) { |
| base::FilePath sysfs_attr_path = sysfs_base_path_.Append("scaling_max_freq"); |
| if (!base::PathExists(sysfs_attr_path)) { |
| LOG(ERROR) << "Failed to set maximum cpu frequency: " |
| << sysfs_attr_path.value() << " does not exist"; |
| return false; |
| } |
| |
| const string str(base::NumberToString(max_frequency)); |
| if (!base::WriteFile(sysfs_attr_path, str.c_str(), str.length())) { |
| return false; |
| } |
| |
| DLOG(INFO) << "Set maximum frequency of CPU " << cpu_id_ << " to " |
| << (max_frequency / 1000) << " MHz"; |
| |
| return true; |
| } |
| |
| bool CpufreqDevice::GetAvailableFrequencies( |
| vector<int> *available_frequencies) { |
| DCHECK(available_frequencies); |
| |
| base::FilePath sysfs_attr_path(sysfs_base_path_.Append( |
| "scaling_available_frequencies")); |
| string str; |
| if (!base::ReadFileToString(sysfs_attr_path, &str)) { |
| LOG(ERROR) << "Failed to read from '" << sysfs_attr_path.value() << "'"; |
| return false; |
| } |
| base::TrimWhitespaceASCII(str, base::TRIM_TRAILING, &str); |
| |
| available_frequencies->clear(); |
| |
| vector<string> frequency_strings = |
| base::SplitString(str, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); |
| for (const string &frequency_string : frequency_strings) { |
| int freq; |
| base::StringToInt(frequency_string, &freq); |
| available_frequencies->push_back(freq); |
| } |
| |
| return true; |
| } |
| |
| bool CpufreqDevice::GetDevices( |
| std::vector<std::unique_ptr<CpufreqDevice>> *cpufreq_devices) { |
| DCHECK(cpufreq_devices); |
| |
| base::FilePath cpufreq_sysfs_dir(string(kCpuSysfsDir) + "/cpufreq"); |
| if (!DirectoryExists(cpufreq_sysfs_dir)) { |
| LOG(INFO) << "cpufreq is not enabled"; |
| return false; |
| } |
| |
| base::FilePath cpu_sysfs_dir(kCpuSysfsDir); |
| base::FileEnumerator enumerator(cpu_sysfs_dir, false, |
| base::FileEnumerator::DIRECTORIES, |
| FILE_PATH_LITERAL("cpu[0-9]*")); |
| for (base::FilePath cpu = enumerator.Next(); !cpu.empty(); |
| cpu = enumerator.Next()) { |
| int cpu_id; |
| base::StringToInt(cpu.BaseName().value().substr(3), &cpu_id); |
| cpufreq_devices->push_back(std::make_unique<CpufreqDevice>(cpu_id)); |
| } |
| |
| return true; |
| } |
| |
| } // namespace thermald |