blob: 02e48dbf7d61c79b3eae2ddbac783a7f6f3e210d [file] [log] [blame]
// 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