diff options
Diffstat (limited to 'power-libperfmgr/aidl/SessionTaskMap.cpp')
-rw-r--r-- | power-libperfmgr/aidl/SessionTaskMap.cpp | 261 |
1 files changed, 261 insertions, 0 deletions
diff --git a/power-libperfmgr/aidl/SessionTaskMap.cpp b/power-libperfmgr/aidl/SessionTaskMap.cpp new file mode 100644 index 00000000..62dae33c --- /dev/null +++ b/power-libperfmgr/aidl/SessionTaskMap.cpp @@ -0,0 +1,261 @@ +/* + * Copyright 2023 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 specific language governing permissions and + * limitations under the License. + */ + +#include "SessionTaskMap.h" + +#include <algorithm> +#include <sstream> + +namespace aidl { +namespace google { +namespace hardware { +namespace power { +namespace impl { +namespace pixel { + +bool SessionTaskMap::add(int64_t sessionId, const SessionValueEntry &sv, + const std::vector<pid_t> &taskIds) { + if (mSessions.find(sessionId) != mSessions.end()) { + return false; + } + + auto sessValPtr = std::make_shared<SessionValueEntry>(); + (*sessValPtr) = sv; + sessValPtr->sessionId = sessionId; + + auto &sessEntry = mSessions[sessionId]; + sessEntry.val = sessValPtr; + sessEntry.linkedTasks = taskIds; + + for (auto taskId : taskIds) { + mTasks[taskId].push_back(sessValPtr); + } + return true; +} + +void SessionTaskMap::addVote(int64_t sessionId, int voteId, int uclampMin, int uclampMax, + std::chrono::steady_clock::time_point startTime, + std::chrono::nanoseconds durationNs) { + auto sessItr = mSessions.find(sessionId); + if (sessItr == mSessions.end()) { + return; + } + + sessItr->second.val->votes->add(voteId, + VoteRange(true, uclampMin, uclampMax, startTime, durationNs)); +} + +std::shared_ptr<SessionValueEntry> SessionTaskMap::findSession(int64_t sessionId) { + auto sessItr = mSessions.find(sessionId); + if (sessItr == mSessions.end()) { + return nullptr; + } + return sessItr->second.val; +} + +void SessionTaskMap::getTaskVoteRange(pid_t taskId, std::chrono::steady_clock::time_point timeNow, + int *uclampMin, int *uclampMax) const { + UclampRange uclampRange; + auto taskItr = mTasks.find(taskId); + if (taskItr == mTasks.end()) { + return; + } + + for (const auto &sessInTask : taskItr->second) { + if (!sessInTask->isActive) { + continue; + } + sessInTask->votes->getUclampRange(&uclampRange, timeNow); + } + *uclampMin = uclampRange.uclampMin; + *uclampMax = uclampRange.uclampMax; +} + +std::vector<int64_t> SessionTaskMap::getSessionIds(pid_t taskId) const { + auto itr = mTasks.find(taskId); + if (itr == mTasks.end()) { + static const std::vector<int64_t> emptySessionIdVec; + return emptySessionIdVec; + } + std::vector<int64_t> res; + res.reserve(itr->second.size()); + for (const auto &i : itr->second) { + res.push_back(i->sessionId); + } + return res; +} + +std::vector<pid_t> &SessionTaskMap::getTaskIds(int64_t sessionId) { + auto taskItr = mSessions.find(sessionId); + if (taskItr == mSessions.end()) { + static std::vector<pid_t> emptyTaskIdVec; + return emptyTaskIdVec; + } + return taskItr->second.linkedTasks; +} + +bool SessionTaskMap::isAnyAppSessionActive(std::chrono::steady_clock::time_point timePoint) const { + for (auto &sessionVal : mSessions) { + if (!sessionVal.second.val->isAppSession) { + continue; + } + if (!sessionVal.second.val->isActive) { + continue; + } + if (!sessionVal.second.val->votes->allTimedOut(timePoint)) { + return true; + } + } + return false; +} + +bool SessionTaskMap::remove(int64_t sessionId) { + auto sessItr = mSessions.find(sessionId); + if (sessItr == mSessions.end()) { + return false; + } + + // For each task id in linked tasks need to remove the corresponding + // task to session mapping in the task map + for (const auto taskId : sessItr->second.linkedTasks) { + // Used linked task ids to cleanup + auto taskItr = mTasks.find(taskId); + if (taskItr == mTasks.end()) { + // Inconsisent state + continue; + } + + // Now lookup session id in task's set + auto taskSessItr = + std::find(taskItr->second.begin(), taskItr->second.end(), sessItr->second.val); + if (taskSessItr == taskItr->second.end()) { + // Should not happen + continue; + } + + // Remove session id from task map + taskItr->second.erase(taskSessItr); + if (taskItr->second.empty()) { + mTasks.erase(taskItr); + } + } + + // Now we can safely remove session entirely since there are no more + // mappings in task to session id + mSessions.erase(sessItr); + return true; +} + +bool SessionTaskMap::removeDeadTaskSessionMap(int64_t sessionId, pid_t taskId) { + auto sessItr = mSessions.find(sessionId); + if (sessItr == mSessions.end()) { + return false; + } + + auto taskItr = mTasks.find(taskId); + if (taskItr == mTasks.end()) { + // Inconsisent state + return false; + } + + // Now lookup session id in task's set + auto taskSessItr = + std::find(taskItr->second.begin(), taskItr->second.end(), sessItr->second.val); + if (taskSessItr == taskItr->second.end()) { + // Should not happen + return false; + } + + // Remove session id from task map + taskItr->second.erase(taskSessItr); + if (taskItr->second.empty()) { + mTasks.erase(taskItr); + } + + return true; +} + +bool SessionTaskMap::replace(int64_t sessionId, const std::vector<pid_t> &taskIds, + std::vector<pid_t> *addedThreads, std::vector<pid_t> *removedThreads) { + auto itr = mSessions.find(sessionId); + if (itr == mSessions.end()) { + return false; + } + + // Make copies of val and threads + auto svTmp = itr->second.val; + const auto previousTaskIds = itr->second.linkedTasks; + + // Determine newly added threads + if (addedThreads) { + for (auto tid : taskIds) { + auto taskSessItr = mTasks.find(tid); + if (taskSessItr == mTasks.end()) { + addedThreads->push_back(tid); + } + } + } + + // Remove session from mappings + remove(sessionId); + // Add session value and task mappings + add(sessionId, *svTmp, taskIds); + + // Determine completely removed threads + if (removedThreads) { + for (auto tid : previousTaskIds) { + auto taskSessItr = mTasks.find(tid); + if (taskSessItr == mTasks.end()) { + removedThreads->push_back(tid); + } + } + } + + return true; +} + +size_t SessionTaskMap::sizeSessions() const { + return mSessions.size(); +} + +size_t SessionTaskMap::sizeTasks() const { + return mTasks.size(); +} + +const std::string &SessionTaskMap::idString(int64_t sessionId) const { + auto sessItr = mSessions.find(sessionId); + if (sessItr == mSessions.end()) { + static const std::string emptyString; + return emptyString; + } + return sessItr->second.val->idString; +} + +bool SessionTaskMap::isAppSession(int64_t sessionId) const { + auto sessItr = mSessions.find(sessionId); + if (sessItr == mSessions.end()) { + return false; + } + + return sessItr->second.val->isAppSession; +} + +} // namespace pixel +} // namespace impl +} // namespace power +} // namespace hardware +} // namespace google +} // namespace aidl |