You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
154 lines
5.0 KiB
154 lines
5.0 KiB
/*
|
|
* Copyright (C) 2017 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specic language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#define ATRACE_TAG (ATRACE_TAG_POWER | ATRACE_TAG_HAL)
|
|
#define LOG_TAG "libperfmgr"
|
|
|
|
#include "perfmgr/NodeLooperThread.h"
|
|
|
|
#include <android-base/file.h>
|
|
#include <android-base/logging.h>
|
|
#include <utils/Trace.h>
|
|
|
|
namespace android {
|
|
namespace perfmgr {
|
|
|
|
bool NodeLooperThread::Request(const std::vector<NodeAction>& actions,
|
|
const std::string& hint_type) {
|
|
if (::android::Thread::exitPending()) {
|
|
LOG(WARNING) << "NodeLooperThread is exiting";
|
|
return false;
|
|
}
|
|
if (!::android::Thread::isRunning()) {
|
|
LOG(WARNING) << "NodeLooperThread is not running, request " << hint_type;
|
|
}
|
|
|
|
bool ret = true;
|
|
::android::AutoMutex _l(lock_);
|
|
for (const auto& a : actions) {
|
|
if (a.node_index >= nodes_.size()) {
|
|
LOG(ERROR) << "Node index out of bound: " << a.node_index
|
|
<< " ,size: " << nodes_.size();
|
|
ret = false;
|
|
} else {
|
|
// End time set to steady time point max
|
|
ReqTime end_time = ReqTime::max();
|
|
// Timeout is non-zero
|
|
if (a.timeout_ms != std::chrono::milliseconds::zero()) {
|
|
auto now = std::chrono::steady_clock::now();
|
|
// Overflow protection in case timeout_ms is too big to overflow
|
|
// time point which is unsigned integer
|
|
if (std::chrono::duration_cast<std::chrono::milliseconds>(
|
|
ReqTime::max() - now) > a.timeout_ms) {
|
|
end_time = now + a.timeout_ms;
|
|
}
|
|
}
|
|
ret = nodes_[a.node_index]->AddRequest(a.value_index, hint_type,
|
|
end_time) &&
|
|
ret;
|
|
}
|
|
}
|
|
wake_cond_.signal();
|
|
return ret;
|
|
}
|
|
|
|
bool NodeLooperThread::Cancel(const std::vector<NodeAction>& actions,
|
|
const std::string& hint_type) {
|
|
if (::android::Thread::exitPending()) {
|
|
LOG(WARNING) << "NodeLooperThread is exiting";
|
|
return false;
|
|
}
|
|
if (!::android::Thread::isRunning()) {
|
|
LOG(WARNING) << "NodeLooperThread is not running, cancel " << hint_type;
|
|
}
|
|
|
|
bool ret = true;
|
|
::android::AutoMutex _l(lock_);
|
|
for (const auto& a : actions) {
|
|
if (a.node_index >= nodes_.size()) {
|
|
LOG(ERROR) << "Node index out of bound: " << a.node_index
|
|
<< " ,size: " << nodes_.size();
|
|
ret = false;
|
|
} else {
|
|
nodes_[a.node_index]->RemoveRequest(hint_type);
|
|
}
|
|
}
|
|
wake_cond_.signal();
|
|
return ret;
|
|
}
|
|
|
|
void NodeLooperThread::DumpToFd(int fd) {
|
|
::android::AutoMutex _l(lock_);
|
|
for (auto& n : nodes_) {
|
|
n->DumpToFd(fd);
|
|
}
|
|
}
|
|
|
|
bool NodeLooperThread::threadLoop() {
|
|
::android::AutoMutex _l(lock_);
|
|
std::chrono::milliseconds timeout_ms = kMaxUpdatePeriod;
|
|
|
|
// Update 2 passes: some node may have dependency in other node
|
|
// e.g. update cpufreq min to VAL while cpufreq max still set to
|
|
// a value lower than VAL, is expected to fail in first pass
|
|
ATRACE_BEGIN("update_nodes");
|
|
for (auto& n : nodes_) {
|
|
n->Update(false);
|
|
}
|
|
for (auto& n : nodes_) {
|
|
timeout_ms = std::min(n->Update(true), timeout_ms);
|
|
}
|
|
ATRACE_END();
|
|
|
|
nsecs_t sleep_timeout_ns = std::numeric_limits<nsecs_t>::max();
|
|
if (timeout_ms.count() < sleep_timeout_ns / 1000 / 1000) {
|
|
sleep_timeout_ns = timeout_ms.count() * 1000 * 1000;
|
|
}
|
|
// VERBOSE level won't print by default in user/userdebug build
|
|
LOG(VERBOSE) << "NodeLooperThread will wait for " << sleep_timeout_ns
|
|
<< "ns";
|
|
ATRACE_BEGIN("wait");
|
|
wake_cond_.waitRelative(lock_, sleep_timeout_ns);
|
|
ATRACE_END();
|
|
return true;
|
|
}
|
|
|
|
bool NodeLooperThread::Start() {
|
|
auto ret = this->run("NodeLooperThread", PRIORITY_HIGHEST);
|
|
if (ret != NO_ERROR) {
|
|
LOG(ERROR) << "NodeLooperThread start failed: " << ret;
|
|
} else {
|
|
LOG(INFO) << "NodeLooperThread started";
|
|
}
|
|
return ret == NO_ERROR;
|
|
}
|
|
|
|
void NodeLooperThread::Stop() {
|
|
if (::android::Thread::isRunning()) {
|
|
LOG(INFO) << "NodeLooperThread stopping";
|
|
{
|
|
::android::AutoMutex _l(lock_);
|
|
wake_cond_.signal();
|
|
::android::Thread::requestExit();
|
|
}
|
|
::android::Thread::join();
|
|
LOG(INFO) << "NodeLooperThread stopped";
|
|
}
|
|
}
|
|
|
|
} // namespace perfmgr
|
|
} // namespace android
|