1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <atomic>
17 #include <chrono>
18 #include <map>
19 #include <shared_mutex>
20
21 #include "rs_unmarshal_task_manager.h"
22
23 #include "platform/common/rs_log.h"
24
25 namespace OHOS::Rosen {
GetTaskDuration() const26 uint64_t UnmarshalTaskInfo::GetTaskDuration() const
27 {
28 if (state == UnmarshalTaskState::COMPLETED) {
29 return completeTimestamp - invokeTimestamp;
30 } else if (state == UnmarshalTaskState::RUNNING) {
31 return UnmarshalTaskUtil::GetTimestamp() - invokeTimestamp;
32 }
33 return 0;
34 }
35
Dump() const36 std::string UnmarshalTaskInfo::Dump() const
37 {
38 std::string dumpStr = "{";
39 dumpStr += "state: ";
40 dumpStr += UnmarshalTaskUtil::UnmarshalTaskStateToString(state);
41 dumpStr += ", name: ";
42 dumpStr += name;
43 dumpStr += ", timestamp: [";
44 dumpStr += std::to_string(invokeTimestamp);
45 dumpStr += ", ";
46 dumpStr += std::to_string(completeTimestamp);
47 dumpStr += "], uid: ";
48 dumpStr += std::to_string(uid);
49 dumpStr += "}";
50 return dumpStr;
51 }
52
53 class RSUnmarshalRunningTaskManager {
54 public:
Clear()55 void Clear()
56 {
57 std::unique_lock<std::shared_mutex> lock { runningTaskMutex_ };
58 runningTasks_.clear();
59 }
60
Push(UnmarshalTaskInfo info)61 void Push(UnmarshalTaskInfo info)
62 {
63 auto uid = info.uid;
64 std::unique_lock<std::shared_mutex> lock { runningTaskMutex_ };
65 runningTasks_.insert_or_assign(uid, std::move(info));
66 }
67
Pop(uint64_t uid)68 std::optional<UnmarshalTaskInfo> Pop(uint64_t uid)
69 {
70 std::unique_lock<std::shared_mutex> lock { runningTaskMutex_ };
71 if (auto node = runningTasks_.extract(uid)) {
72 return node.mapped();
73 }
74 return std::nullopt;
75 }
76
GetLongestTask() const77 std::optional<UnmarshalTaskInfo> GetLongestTask() const
78 {
79 std::shared_lock<std::shared_mutex> lock { runningTaskMutex_ };
80 if (runningTasks_.empty()) {
81 return std::nullopt;
82 }
83 std::optional<UnmarshalTaskInfo> ret;
84 uint64_t maxDuration = 0;
85 for (const auto& [_, info] : runningTasks_) {
86 auto duration = info.GetTaskDuration();
87 if (duration > maxDuration) {
88 maxDuration = duration;
89 ret = info;
90 }
91 }
92 return ret;
93 }
94
Dump() const95 std::string Dump() const
96 {
97 std::string dumpStr = "RSUnmarshalRunningTaskManager Dump : [";
98 {
99 std::shared_lock<std::shared_mutex> lock { runningTaskMutex_ };
100 for (const auto& [_, info] : runningTasks_) {
101 dumpStr += info.Dump();
102 dumpStr += ",";
103 }
104 }
105 if (!dumpStr.empty()) {
106 dumpStr.pop_back();
107 }
108 dumpStr += "]";
109 return dumpStr;
110 }
111
112 private:
113 mutable std::shared_mutex runningTaskMutex_;
114 std::map<uint64_t, UnmarshalTaskInfo> runningTasks_;
115 };
116
117 class RSUnmarshalCompletedTaskManager {
118 public:
Clear()119 void Clear()
120 {
121 std::unique_lock<std::shared_mutex> lock { completedTaskMutex_ };
122 taskRankingTable_.clear();
123 }
124
Push(UnmarshalTaskInfo info)125 void Push(UnmarshalTaskInfo info)
126 {
127 auto uid = info.uid;
128 auto duration = info.GetTaskDuration();
129 std::unique_lock<std::shared_mutex> lock { completedTaskMutex_ };
130 taskRankingTable_.insert_or_assign({ duration, uid }, std::move(info));
131 }
132
Pop()133 std::optional<UnmarshalTaskInfo> Pop()
134 {
135 std::unique_lock<std::shared_mutex> lock { completedTaskMutex_ };
136 if (taskRankingTable_.empty()) {
137 return std::nullopt;
138 }
139 return taskRankingTable_.extract(taskRankingTable_.cbegin()).mapped();
140 }
141
GetLongestTask() const142 std::optional<UnmarshalTaskInfo> GetLongestTask() const
143 {
144 std::shared_lock<std::shared_mutex> lock { completedTaskMutex_ };
145 if (taskRankingTable_.empty()) {
146 return std::nullopt;
147 }
148 return taskRankingTable_.cbegin()->second;
149 }
150
Dump() const151 std::string Dump() const
152 {
153 std::string dumpStr = "RSUnmarshalCompletedTaskManager Dump: [";
154 {
155 std::shared_lock<std::shared_mutex> lock { completedTaskMutex_ };
156 for (const auto& [_, info] : taskRankingTable_) {
157 dumpStr += info.Dump();
158 dumpStr += ",";
159 }
160 }
161 if (!dumpStr.empty()) {
162 dumpStr.pop_back();
163 }
164 dumpStr += "]";
165 return dumpStr;
166 }
167
168 private:
169 mutable std::shared_mutex completedTaskMutex_;
170 std::map<std::pair<uint64_t, uint64_t>, UnmarshalTaskInfo, std::greater<>> taskRankingTable_;
171 };
172
RSUnmarshalTaskManager()173 RSUnmarshalTaskManager::RSUnmarshalTaskManager() : runningTaskMgr_(std::make_unique<RSUnmarshalRunningTaskManager>()),
174 completedTaskMgr_(std::make_unique<RSUnmarshalCompletedTaskManager>())
175 {
176 }
177
Instance()178 RSUnmarshalTaskManager& RSUnmarshalTaskManager::Instance()
179 {
180 static RSUnmarshalTaskManager mgr;
181 return mgr;
182 }
183
BeginTask(std::string name)184 uint64_t RSUnmarshalTaskManager::BeginTask(std::string name)
185 {
186 auto uid = GetUid();
187 runningTaskMgr_->Push({
188 .state = UnmarshalTaskState::RUNNING,
189 .name = std::move(name),
190 .invokeTimestamp = UnmarshalTaskUtil::GetTimestamp(),
191 .uid = uid,
192 });
193 return uid;
194 }
195
EndTask(uint64_t uid)196 void RSUnmarshalTaskManager::EndTask(uint64_t uid)
197 {
198 if (auto taskInfo = runningTaskMgr_->Pop(uid)) {
199 auto& info = taskInfo.value();
200 info.state = UnmarshalTaskState::COMPLETED;
201 info.completeTimestamp = UnmarshalTaskUtil::GetTimestamp();
202 completedTaskMgr_->Push(std::move(info));
203 } else {
204 RS_LOGE("RSUnmarshalTaskManager EndTask Invalid Uid %{public}" PRIu64, uid);
205 }
206 }
207
Clear()208 void RSUnmarshalTaskManager::Clear()
209 {
210 completedTaskMgr_->Clear();
211 }
212
GetLongestTask() const213 std::optional<UnmarshalTaskInfo> RSUnmarshalTaskManager::GetLongestTask() const
214 {
215 if (auto completedTask = GetCompletedLongestTask()) {
216 if (auto runningTask = GetRunningLongestTask()) {
217 return (completedTask.value().GetTaskDuration() < runningTask.value().GetTaskDuration()) ?
218 runningTask : completedTask;
219 }
220 return completedTask;
221 }
222 return GetRunningLongestTask();
223 }
224
GetRunningLongestTask() const225 std::optional<UnmarshalTaskInfo> RSUnmarshalTaskManager::GetRunningLongestTask() const
226 {
227 return runningTaskMgr_->GetLongestTask();
228 }
229
GetCompletedLongestTask() const230 std::optional<UnmarshalTaskInfo> RSUnmarshalTaskManager::GetCompletedLongestTask() const
231 {
232 return completedTaskMgr_->GetLongestTask();
233 }
234
GetUid() const235 uint64_t RSUnmarshalTaskManager::GetUid() const
236 {
237 static std::atomic_uint64_t uid;
238 return uid.fetch_add(1, std::memory_order_relaxed);
239 }
240
Dump() const241 std::string RSUnmarshalTaskManager::Dump() const
242 {
243 std::string dumpStr = "RunningTasks: ";
244 dumpStr += runningTaskMgr_->Dump();
245 dumpStr += "|| completedTasks: ";
246 dumpStr += completedTaskMgr_->Dump();
247 return dumpStr;
248 }
249
250 namespace UnmarshalTaskUtil {
UnmarshalTaskStateToString(UnmarshalTaskState state)251 std::string UnmarshalTaskStateToString(UnmarshalTaskState state)
252 {
253 switch (state) {
254 case UnmarshalTaskState::COMPLETED : {
255 return "COMPLETED";
256 }
257 case UnmarshalTaskState::RUNNING : {
258 return "RUNNING";
259 }
260 case UnmarshalTaskState::UNINVOKED : {
261 return "UNINVOKED";
262 }
263 default : {
264 return "UNDEFSTATE";
265 }
266 }
267 }
268
GetTimestamp()269 uint64_t GetTimestamp()
270 {
271 return std::chrono::duration_cast<std::chrono::milliseconds>(
272 std::chrono::steady_clock::now().time_since_epoch()).count();
273 }
274 } // namespace UnmarshalTaskUtil
275 } // namespace OHOS::Rosen