2 * Copyright (C) 2017 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specic language governing permissions and
14 * limitations under the License.
17 #define LOG_TAG "libperfmgr"
19 #include <android-base/file.h>
20 #include <android-base/logging.h>
22 #include "perfmgr/NodeLooperThread.h"
27 bool NodeLooperThread::Request(const std::vector<NodeAction>& actions,
28 const std::string& hint_type) {
29 if (::android::Thread::exitPending()) {
30 LOG(WARNING) << "NodeLooperThread is exiting";
33 if (!::android::Thread::isRunning()) {
34 LOG(FATAL) << "NodeLooperThread stopped, abort...";
38 ::android::AutoMutex _l(lock_);
39 for (const auto& a : actions) {
40 if (a.node_index >= nodes_.size()) {
41 LOG(ERROR) << "Node index out of bound: " << a.node_index
42 << " ,size: " << nodes_.size();
45 // End time set to steady time point max
46 ReqTime end_time = ReqTime::max();
47 // Timeout is non-zero
48 if (a.timeout_ms != std::chrono::milliseconds::zero()) {
49 auto now = std::chrono::steady_clock::now();
50 // Overflow protection in case timeout_ms is too big to overflow
51 // time point which is unsigned integer
52 if (std::chrono::duration_cast<std::chrono::milliseconds>(
53 ReqTime::max() - now) > a.timeout_ms) {
54 end_time = now + a.timeout_ms;
57 ret = nodes_[a.node_index]->AddRequest(a.value_index, hint_type,
66 bool NodeLooperThread::Cancel(const std::vector<NodeAction>& actions,
67 const std::string& hint_type) {
68 if (::android::Thread::exitPending()) {
69 LOG(WARNING) << "NodeLooperThread is exiting";
72 if (!::android::Thread::isRunning()) {
73 LOG(FATAL) << "NodeLooperThread stopped, abort...";
77 ::android::AutoMutex _l(lock_);
78 for (const auto& a : actions) {
79 if (a.node_index >= nodes_.size()) {
80 LOG(ERROR) << "Node index out of bound: " << a.node_index
81 << " ,size: " << nodes_.size();
84 nodes_[a.node_index]->RemoveRequest(hint_type);
91 void NodeLooperThread::DumpToFd(int fd) {
92 ::android::AutoMutex _l(lock_);
93 for (auto& n : nodes_) {
98 bool NodeLooperThread::threadLoop() {
99 ::android::AutoMutex _l(lock_);
100 std::chrono::milliseconds timeout_ms = kMaxUpdatePeriod;
102 // Update 2 passes: some node may have dependency in other node
103 // e.g. update cpufreq min to VAL while cpufreq max still set to
104 // a value lower than VAL, is expected to fail in first pass
105 for (auto& n : nodes_) {
108 for (auto& n : nodes_) {
109 timeout_ms = std::min(n->Update(), timeout_ms);
112 nsecs_t sleep_timeout_ns = std::numeric_limits<nsecs_t>::max();
113 if (timeout_ms.count() < sleep_timeout_ns / 1000 / 1000) {
114 sleep_timeout_ns = timeout_ms.count() * 1000 * 1000;
116 // VERBOSE level won't print by default in user/userdebug build
117 LOG(VERBOSE) << "NodeLooperThread will wait for " << sleep_timeout_ns
119 wake_cond_.waitRelative(lock_, sleep_timeout_ns);
123 void NodeLooperThread::onFirstRef() {
124 auto ret = this->run("NodeLooperThread", PRIORITY_HIGHEST);
125 if (ret != NO_ERROR) {
126 LOG(ERROR) << "NodeLooperThread start fail";
128 LOG(INFO) << "NodeLooperThread started";
132 void NodeLooperThread::Stop() {
133 if (::android::Thread::isRunning()) {
134 LOG(INFO) << "NodeLooperThread stopping";
136 ::android::AutoMutex _l(lock_);
138 ::android::Thread::requestExit();
140 ::android::Thread::join();
141 LOG(INFO) << "NodeLooperThread stopped";
145 } // namespace perfmgr
146 } // namespace android