summaryrefslogtreecommitdiff
path: root/power-libperfmgr/aidl/SessionTaskMap.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'power-libperfmgr/aidl/SessionTaskMap.cpp')
-rw-r--r--power-libperfmgr/aidl/SessionTaskMap.cpp261
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