blob: eb5c9b431789d18d68bb82e7e541c8e933d4d0ac [file] [log] [blame]
Wei Wangf72cfad2017-10-26 22:41:03 -07001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16
Wei Wanga8768fc2017-12-31 23:26:50 -080017#define LOG_TAG "libperfmgr"
18
Wei Wangf72cfad2017-10-26 22:41:03 -070019#include <android-base/file.h>
20#include <android-base/logging.h>
21
22#include "perfmgr/NodeLooperThread.h"
23
24namespace android {
25namespace perfmgr {
26
27bool NodeLooperThread::Request(const std::vector<NodeAction>& actions,
28 const std::string& hint_type) {
29 if (::android::Thread::exitPending()) {
30 LOG(WARNING) << "NodeLooperThread is exiting";
31 return false;
32 }
33 if (!::android::Thread::isRunning()) {
34 LOG(FATAL) << "NodeLooperThread stopped, abort...";
35 }
36
37 bool ret = true;
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();
43 ret = false;
44 } else {
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;
55 }
56 }
57 ret = nodes_[a.node_index]->AddRequest(a.value_index, hint_type,
58 end_time) &&
59 ret;
60 }
61 }
62 wake_cond_.signal();
63 return ret;
64}
65
66bool NodeLooperThread::Cancel(const std::vector<NodeAction>& actions,
67 const std::string& hint_type) {
68 if (::android::Thread::exitPending()) {
69 LOG(WARNING) << "NodeLooperThread is exiting";
70 return false;
71 }
72 if (!::android::Thread::isRunning()) {
73 LOG(FATAL) << "NodeLooperThread stopped, abort...";
74 }
75
76 bool ret = true;
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();
82 ret = false;
83 } else {
84 nodes_[a.node_index]->RemoveRequest(hint_type);
85 }
86 }
87 wake_cond_.signal();
88 return ret;
89}
90
Wei Wang6ac764e2018-01-30 15:14:09 -080091void NodeLooperThread::DumpToFd(int fd) {
92 ::android::AutoMutex _l(lock_);
93 for (auto& n : nodes_) {
94 n->DumpToFd(fd);
95 }
96}
97
Wei Wangf72cfad2017-10-26 22:41:03 -070098bool NodeLooperThread::threadLoop() {
99 ::android::AutoMutex _l(lock_);
100 std::chrono::milliseconds timeout_ms = kMaxUpdatePeriod;
Wei Wang7daf2292018-06-06 11:20:36 -0700101
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
Wei Wangf72cfad2017-10-26 22:41:03 -0700105 for (auto& n : nodes_) {
Wei Wang7daf2292018-06-06 11:20:36 -0700106 n->Update(false);
107 }
108 for (auto& n : nodes_) {
Wei Wangc43c2c02018-10-23 22:44:31 -0700109 timeout_ms = std::min(n->Update(true), timeout_ms);
Wei Wangf72cfad2017-10-26 22:41:03 -0700110 }
Wei Wangf8bea162018-01-01 22:23:52 -0800111
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;
115 }
Wei Wangf72cfad2017-10-26 22:41:03 -0700116 // VERBOSE level won't print by default in user/userdebug build
117 LOG(VERBOSE) << "NodeLooperThread will wait for " << sleep_timeout_ns
118 << "ns";
119 wake_cond_.waitRelative(lock_, sleep_timeout_ns);
120 return true;
121}
122
123void NodeLooperThread::onFirstRef() {
124 auto ret = this->run("NodeLooperThread", PRIORITY_HIGHEST);
125 if (ret != NO_ERROR) {
126 LOG(ERROR) << "NodeLooperThread start fail";
127 } else {
128 LOG(INFO) << "NodeLooperThread started";
129 }
130}
131
132void NodeLooperThread::Stop() {
133 if (::android::Thread::isRunning()) {
134 LOG(INFO) << "NodeLooperThread stopping";
135 {
136 ::android::AutoMutex _l(lock_);
137 wake_cond_.signal();
138 ::android::Thread::requestExit();
139 }
140 ::android::Thread::join();
141 LOG(INFO) << "NodeLooperThread stopped";
142 }
143}
144
145} // namespace perfmgr
146} // namespace android