19d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang/* 29d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang * Copyright (C) 2017 The Android Open Source Project 39d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang * 49d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang * Licensed under the Apache License, Version 2.0 (the "License"); 59d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang * you may not use this file except in compliance with the License. 69d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang * You may obtain a copy of the License at 79d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang * 89d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang * http://www.apache.org/licenses/LICENSE-2.0 99d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang * 109d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang * Unless required by applicable law or agreed to in writing, software 119d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang * distributed under the License is distributed on an "AS IS" BASIS, 129d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang * See the License for the specic language governing permissions and 149d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang * limitations under the License. 159d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang */ 169d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang 177ef92c9684700a19eef5f4e71d8261535bbdded8Wei Wang#define LOG_TAG "libperfmgr" 187ef92c9684700a19eef5f4e71d8261535bbdded8Wei Wang 199d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang#include <android-base/file.h> 209d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang#include <android-base/logging.h> 21b243f99965c7f9b780854233273f9d8f9e13b39cWei Wang#include <android-base/stringprintf.h> 224ea001c2d3dc3f5c8421a5e86098272b295b213eWei Wang#include <android-base/strings.h> 239d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang 249d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang#include "perfmgr/Node.h" 259d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang 269d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wangnamespace android { 279d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wangnamespace perfmgr { 289d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang 299d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei WangNode::Node(std::string name, std::string node_path, 309d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang std::vector<RequestGroup> req_sorted, std::size_t default_val_index, 319d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang bool reset_on_init, bool hold_fd) 329d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang : name_(name), 339d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang node_path_(node_path), 349d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang req_sorted_(std::move(req_sorted)), 359d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang default_val_index_(default_val_index), 369d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang reset_on_init_(reset_on_init), 379d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang hold_fd_(hold_fd) { 389d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang if (reset_on_init) { 399d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang // Assigning an invalid value so the next Update() will update the 409d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang // Node's value to default 417ef92c9684700a19eef5f4e71d8261535bbdded8Wei Wang current_val_index_ = req_sorted_.size(); 429d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang Update(); 439d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang } else { 449d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang current_val_index_ = default_val_index; 459d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang } 469d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang} 479d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang 489d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wangbool Node::AddRequest(std::size_t value_index, const std::string& hint_type, 499d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang ReqTime end_time) { 509d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang if (value_index >= req_sorted_.size()) { 519d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang LOG(ERROR) << "Value index out of bound: " << value_index 529d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang << " ,size: " << req_sorted_.size(); 539d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang return false; 549d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang } 559d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang // Add/Update request to the new end_time for the specific hint_type 569d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang req_sorted_[value_index].AddRequest(hint_type, end_time); 579d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang return true; 589d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang} 599d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang 609d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wangbool Node::RemoveRequest(const std::string& hint_type) { 619d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang bool ret = false; 629d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang // Remove all requests for the specific hint_type 639d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang for (auto& value : req_sorted_) { 649d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang ret = value.RemoveRequest(hint_type) || ret; 659d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang } 669d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang return ret; 679d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang} 689d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang 699d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wangstd::chrono::milliseconds Node::Update() { 709d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang std::size_t value_index = default_val_index_; 719d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang std::chrono::milliseconds expire_time = std::chrono::milliseconds::max(); 729d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang 739d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang // Find the highest outstanding request's expire time 749d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang for (std::size_t i = 0; i < req_sorted_.size(); i++) { 759d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang if (req_sorted_[i].GetExpireTime(&expire_time)) { 769d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang value_index = i; 779d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang break; 789d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang } 799d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang } 809d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang 819d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang // Update node only if request index changes 829d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang if (value_index != current_val_index_) { 837ef92c9684700a19eef5f4e71d8261535bbdded8Wei Wang std::string req_value = req_sorted_[value_index].GetRequestValue(); 849d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang 859d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang fd_.reset(TEMP_FAILURE_RETRY( 869d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang open(node_path_.c_str(), O_WRONLY | O_CLOEXEC | O_TRUNC))); 879d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang 889d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang if (fd_ == -1 || !android::base::WriteStringToFd(req_value, fd_)) { 899d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang LOG(ERROR) << "Failed to write to node: " << node_path_ 907ef92c9684700a19eef5f4e71d8261535bbdded8Wei Wang << " with value: " << req_value << ", fd: " << fd_; 917ef92c9684700a19eef5f4e71d8261535bbdded8Wei Wang // Retry in 500ms or sooner 927ef92c9684700a19eef5f4e71d8261535bbdded8Wei Wang expire_time = std::min(expire_time, std::chrono::milliseconds(500)); 939d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang } else { 949d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang // For regular file system, we need fsync 959d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang fsync(fd_); 969d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang // Some dev node requires file to remain open during the entire hint 979d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang // duration e.g. /dev/cpu_dma_latency, so fd_ is intentionally kept 989d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang // open during any requested value other than default one. If 999d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang // request a default value, node will write the value and then 1009d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang // release the fd. 1019d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang if ((!hold_fd_) || value_index == default_val_index_) { 1029d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang fd_.reset(); 1039d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang } 1047ef92c9684700a19eef5f4e71d8261535bbdded8Wei Wang // Update current index only when succeed 1057ef92c9684700a19eef5f4e71d8261535bbdded8Wei Wang current_val_index_ = value_index; 1069d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang } 1079d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang } 1089d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang return expire_time; 1099d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang} 1109d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang 1119d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wangstd::string Node::GetName() const { 1129d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang return name_; 1139d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang} 1149d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang 1159d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wangstd::string Node::GetPath() const { 1169d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang return node_path_; 1179d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang} 1189d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang 1199d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wangbool Node::GetValueIndex(const std::string value, std::size_t* index) const { 1209d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang bool found = false; 1219d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang for (std::size_t i = 0; i < req_sorted_.size(); i++) { 1229d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang if (req_sorted_[i].GetRequestValue() == value) { 1239d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang *index = i; 1249d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang found = true; 1259d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang break; 1269d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang } 1279d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang } 1289d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang return found; 1299d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang} 1309d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang 1319d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wangstd::size_t Node::GetDefaultIndex() const { 1329d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang return default_val_index_; 1339d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang} 1349d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang 1359d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wangbool Node::GetResetOnInit() const { 1369d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang return reset_on_init_; 1379d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang} 1389d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang 1399d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wangbool Node::GetHoldFd() const { 1409d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang return hold_fd_; 1419d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang} 1429d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang 1439d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wangstd::vector<std::string> Node::GetValues() const { 1449d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang std::vector<std::string> values; 1459d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang for (const auto& value : req_sorted_) { 1469d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang values.emplace_back(value.GetRequestValue()); 1479d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang } 1489d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang return values; 1499d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang} 1509d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang 151b243f99965c7f9b780854233273f9d8f9e13b39cWei Wangvoid Node::DumpToFd(int fd) { 152b243f99965c7f9b780854233273f9d8f9e13b39cWei Wang std::string node_value; 153b243f99965c7f9b780854233273f9d8f9e13b39cWei Wang if (!android::base::ReadFileToString(node_path_, &node_value)) { 154b243f99965c7f9b780854233273f9d8f9e13b39cWei Wang LOG(ERROR) << "Failed to read node path: " << node_path_; 155b243f99965c7f9b780854233273f9d8f9e13b39cWei Wang } 156b243f99965c7f9b780854233273f9d8f9e13b39cWei Wang node_value = android::base::Trim(node_value); 1574ea001c2d3dc3f5c8421a5e86098272b295b213eWei Wang std::string buf(android::base::StringPrintf( 1584ea001c2d3dc3f5c8421a5e86098272b295b213eWei Wang "%s\t%s\t%zu\t%s\n", name_.c_str(), node_path_.c_str(), 1594ea001c2d3dc3f5c8421a5e86098272b295b213eWei Wang current_val_index_, node_value.c_str())); 160b243f99965c7f9b780854233273f9d8f9e13b39cWei Wang if (!android::base::WriteStringToFd(buf, fd)) { 161b243f99965c7f9b780854233273f9d8f9e13b39cWei Wang LOG(ERROR) << "Failed to dump fd: " << fd; 162b243f99965c7f9b780854233273f9d8f9e13b39cWei Wang } 163b243f99965c7f9b780854233273f9d8f9e13b39cWei Wang} 164b243f99965c7f9b780854233273f9d8f9e13b39cWei Wang 1659d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang} // namespace perfmgr 1669d337a7df3ba6d6a8418f58ed59611678ae7b8cdWei Wang} // namespace android 167