• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 #include "socperf_thread_wrap.h"
16 
17 #include <set>               // for set
18 #include <unistd.h>          // for open, write
19 #include <fcntl.h>           // for O_RDWR, O_CLOEXEC
20 
21 #include "res_exe_type.h"
22 #include "res_sched_exe_client.h"
23 #include "socperf.h"
24 #include "socperf_trace.h"
25 
26 namespace OHOS {
27 namespace SOCPERF {
28 
SocPerfThreadWrap()29 SocPerfThreadWrap::SocPerfThreadWrap() : socperfQueue_("socperf", ffrt::queue_attr().qos(ffrt::qos_user_interactive))
30 {
31 }
32 
~SocPerfThreadWrap()33 SocPerfThreadWrap::~SocPerfThreadWrap()
34 {
35 }
36 
InitResourceNodeInfo()37 void SocPerfThreadWrap::InitResourceNodeInfo()
38 {
39     std::function<void()>&& initResourceNodeInfoFunc = [this]() {
40         for (auto iter = socPerfConfig_.resourceNodeInfo_.begin();
41             iter != socPerfConfig_.resourceNodeInfo_.end(); ++iter) {
42             std::shared_ptr<ResourceNode> resourceNode = iter->second;
43             if (resourceNode == nullptr) {
44                 continue;
45             }
46             auto resStatus = std::make_shared<ResStatus>();
47             resStatusInfo_.insert(std::pair<int32_t, std::shared_ptr<ResStatus>>(resourceNode->id, resStatus));
48         }
49         InitResStatus();
50     };
51     socperfQueue_.submit(initResourceNodeInfoFunc);
52 }
53 
DoFreqActionPack(std::shared_ptr<ResActionItem> head)54 void SocPerfThreadWrap::DoFreqActionPack(std::shared_ptr<ResActionItem> head)
55 {
56     if (head == nullptr) {
57         return;
58     }
59     std::function<void()>&& doFreqActionPackFunc = [this, head]() {
60         std::shared_ptr<ResActionItem> queueHead = head;
61         while (queueHead) {
62             if (socPerfConfig_.IsValidResId(queueHead->resId)) {
63                 UpdateResActionList(queueHead->resId, queueHead->resAction, false);
64             }
65             queueHead = queueHead->next;
66         }
67         SendResStatus();
68     };
69     socperfQueue_.submit(doFreqActionPackFunc);
70 }
71 
UpdatePowerLimitBoostFreq(bool powerLimitBoost)72 void SocPerfThreadWrap::UpdatePowerLimitBoostFreq(bool powerLimitBoost)
73 {
74     std::function<void()>&& updatePowerLimitBoostFreqFunc = [this, powerLimitBoost]() {
75         this->powerLimitBoost_ = powerLimitBoost;
76         for (auto iter = resStatusInfo_.begin(); iter != resStatusInfo_.end(); ++iter) {
77             if (resStatusInfo_[iter->first] == nullptr) {
78                 continue;
79             }
80             ArbitrateCandidate(iter->first);
81         }
82         SendResStatus();
83     };
84     socperfQueue_.submit(updatePowerLimitBoostFreqFunc);
85 }
86 
UpdateThermalLimitBoostFreq(bool thermalLimitBoost)87 void SocPerfThreadWrap::UpdateThermalLimitBoostFreq(bool thermalLimitBoost)
88 {
89     std::function<void()>&& updateThermalLimitBoostFreqFunc = [this, thermalLimitBoost]() {
90         this->thermalLimitBoost_ = thermalLimitBoost;
91         for (auto iter = resStatusInfo_.begin(); iter != resStatusInfo_.end(); ++iter) {
92             if (resStatusInfo_[iter->first] == nullptr) {
93                 continue;
94             }
95             ArbitrateCandidate(iter->first);
96         }
97         SendResStatus();
98     };
99     socperfQueue_.submit(updateThermalLimitBoostFreqFunc);
100 }
101 
UpdateLimitStatus(int32_t eventId,std::shared_ptr<ResAction> resAction,int32_t resId)102 void SocPerfThreadWrap::UpdateLimitStatus(int32_t eventId, std::shared_ptr<ResAction> resAction, int32_t resId)
103 {
104     if (resAction == nullptr) {
105         return;
106     }
107     std::function<void()>&& updateLimitStatusFunc = [this, eventId, resId, resAction]() {
108         if (eventId == INNER_EVENT_ID_DO_FREQ_ACTION) {
109             DoFreqAction(resId, resAction);
110         } else if (eventId == INNER_EVENT_ID_DO_FREQ_ACTION_LEVEL) {
111             DoFreqActionLevel(resId, resAction);
112         }
113         SendResStatus();
114         if (resAction->onOff && resStatusInfo_[resId] != nullptr) {
115             HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::RSS, "LIMIT_REQUEST",
116                             OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR,
117                             "CLIENT_ID", resAction->type,
118                             "RES_ID", resId,
119                             "CONFIG", resStatusInfo_[resId]->candidate);
120         }
121     };
122     socperfQueue_.submit(updateLimitStatusFunc);
123 }
124 
ClearAllAliveRequest()125 void SocPerfThreadWrap::ClearAllAliveRequest()
126 {
127     std::function<void()>&& updateLimitStatusFunc = [this]() {
128         for (const auto& item : this->resStatusInfo_) {
129             if (item.second == nullptr) {
130                 continue;
131             }
132             std::list<std::shared_ptr<ResAction>>& resActionList = item.second->resActionList[ACTION_TYPE_PERF];
133             resActionList.clear();
134             UpdateCandidatesValue(item.first, ACTION_TYPE_PERF);
135         }
136         SendResStatus();
137     };
138     socperfQueue_.submit(updateLimitStatusFunc);
139 }
140 
DoFreqAction(int32_t resId,std::shared_ptr<ResAction> resAction)141 void SocPerfThreadWrap::DoFreqAction(int32_t resId, std::shared_ptr<ResAction> resAction)
142 {
143     if (!socPerfConfig_.IsValidResId(resId) || resAction == nullptr) {
144         return;
145     }
146     UpdateResActionList(resId, resAction, false);
147 }
148 
InitResStatus()149 void SocPerfThreadWrap::InitResStatus()
150 {
151     std::vector<int32_t> qosId;
152     std::vector<int64_t> value;
153     std::vector<int64_t> endTime;
154     std::vector<int32_t> qosIdToRssEx;
155     std::vector<int64_t> valueToRssEx;
156     std::vector<int64_t> endTimeToRssEx;
157     for (auto iter = resStatusInfo_.begin(); iter != resStatusInfo_.end(); ++iter) {
158         int32_t resId = iter->first;
159         if (socPerfConfig_.resourceNodeInfo_.find(resId) != socPerfConfig_.resourceNodeInfo_.end()) {
160             if (socPerfConfig_.resourceNodeInfo_[resId]->persistMode == REPORT_TO_PERFSO) {
161                 qosId.push_back(resId);
162                 value.push_back(NODE_DEFAULT_VALUE);
163                 endTime.push_back(MAX_INT_VALUE);
164             } else {
165                 qosIdToRssEx.push_back(resId);
166                 valueToRssEx.push_back(NODE_DEFAULT_VALUE);
167                 endTimeToRssEx.push_back(MAX_INT_VALUE);
168             }
169         }
170     }
171     ReportToPerfSo(qosId, value, endTime);
172     ReportToRssExe(qosIdToRssEx, valueToRssEx, endTimeToRssEx);
173 }
174 
SetWeakInteractionStatus(bool enable)175 void SocPerfThreadWrap::SetWeakInteractionStatus(bool enable)
176 {
177     std::function<void()>&& weakInteractionFunc = [this, enable]() {
178         std::string trace_str("SetWeakInteractionStatus");
179         trace_str.append("[").append(enable ? "true" : "false").append("]");
180         StartTraceEx(HITRACE_LEVEL_INFO, HITRACE_TAG_SOCPERF, trace_str.c_str());
181         weakInteractionStatus_ = enable;
182         WeakInteraction();
183         SOC_PERF_LOGI("SetWeakInteractionStatus is %{public}d.", enable);
184         FinishTraceEx(HITRACE_LEVEL_INFO, HITRACE_TAG_SOCPERF);
185     };
186     socperfQueue_.submit(weakInteractionFunc);
187 }
188 
WeakInteraction()189 void SocPerfThreadWrap::WeakInteraction()
190 {
191     for (int i = 0; i < (int)socPerfConfig_.interAction_.size(); i++) {
192         std::shared_ptr<InterAction> interAction = socPerfConfig_.interAction_[i];
193         if (weakInteractionStatus_ && boostResCnt == 0 && interAction->status == BOOST_STATUS) {
194             interAction->status = BOOST_END_STATUS;
195             std::function<void()>&& updateLimitStatusFunc = [this, i]() {
196                 socPerfConfig_.interAction_[i]->status = WEAK_INTERACTION_STATUS;
197                 DoWeakInteraction(
198                     socPerfConfig_.configPerfActionsInfo_[DEFAULT_CONFIG_MODE][socPerfConfig_.interAction_[i]->cmdId],
199                     EVENT_ON, socPerfConfig_.interAction_[i]->actionType);
200                 std::string trace_str("WeakInteraction");
201                 trace_str.append(",cmdId[").append(std::to_string(socPerfConfig_.interAction_[i]->cmdId)).append("]");
202                 trace_str.append(",onOff[").append(std::to_string(EVENT_ON)).append("]");
203                 StartTraceEx(HITRACE_LEVEL_INFO, HITRACE_TAG_SOCPERF, trace_str.c_str());
204                 FinishTraceEx(HITRACE_LEVEL_INFO, HITRACE_TAG_SOCPERF);
205             };
206             ffrt::task_attr taskAttr;
207             taskAttr.delay(interAction->delayTime * SCALES_OF_MILLISECONDS_TO_MICROSECONDS);
208             interAction->timerTask = socperfQueue_.submit_h(updateLimitStatusFunc, taskAttr);
209         } else if ((!weakInteractionStatus_ || boostResCnt != 0) && interAction->status == WEAK_INTERACTION_STATUS) {
210             interAction->status = BOOST_STATUS;
211             DoWeakInteraction(
212                 socPerfConfig_.configPerfActionsInfo_[DEFAULT_CONFIG_MODE][interAction->cmdId],
213                 EVENT_OFF, interAction->actionType);
214             std::string trace_str("WeakInteraction");
215             trace_str.append(",cmdId[").append(std::to_string(interAction->cmdId)).append("]");
216             trace_str.append(",onOff[").append(std::to_string(EVENT_OFF)).append("]");
217             StartTraceEx(HITRACE_LEVEL_INFO, HITRACE_TAG_SOCPERF, trace_str.c_str());
218             FinishTraceEx(HITRACE_LEVEL_INFO, HITRACE_TAG_SOCPERF);
219         } else if ((!weakInteractionStatus_ || boostResCnt != 0) && interAction->status == BOOST_END_STATUS) {
220             interAction->status = BOOST_STATUS;
221             if (interAction->timerTask != nullptr) {
222                 socperfQueue_.cancel(interAction->timerTask);
223                 interAction->timerTask = nullptr;
224             }
225         }
226     }
227 }
228 
DoWeakInteraction(std::shared_ptr<Actions> actions,int32_t onOff,int32_t actionType)229 void SocPerfThreadWrap::DoWeakInteraction(std::shared_ptr<Actions> actions, int32_t onOff, int32_t actionType)
230 {
231     std::shared_ptr<ResActionItem> header = nullptr;
232     std::shared_ptr<ResActionItem> curItem = nullptr;
233     if (actions == nullptr) {
234         return;
235     }
236     for (auto iter = actions->actionList.begin(); iter != actions->actionList.end(); iter++) {
237         std::shared_ptr<Action> action = *iter;
238         for (int32_t i = 0; i < (int32_t)action->variable.size() - 1; i += RES_ID_AND_VALUE_PAIR) {
239             if (!socPerfConfig_.IsValidResId(action->variable[i])) {
240                 continue;
241             }
242             auto resActionItem = std::make_shared<ResActionItem>(action->variable[i]);
243             resActionItem->resAction = std::make_shared<ResAction>(action->variable[i + 1], 0,
244                 actionType, onOff, actions->id, MAX_INT_VALUE);
245             resActionItem->resAction->interaction = false;
246             if (curItem) {
247                 curItem->next = resActionItem;
248             } else {
249                 header = resActionItem;
250             }
251             curItem = resActionItem;
252         }
253     }
254     DoFreqActionPack(header);
255 }
256 
SendResStatus()257 void SocPerfThreadWrap::SendResStatus()
258 {
259     std::vector<int32_t> qosId;
260     std::vector<int64_t> value;
261     std::vector<int64_t> endTime;
262     std::vector<int32_t> qosIdToRssEx;
263     std::vector<int64_t> valueToRssEx;
264     std::vector<int64_t> endTimeToRssEx;
265     for (auto iter = resStatusInfo_.begin(); iter != resStatusInfo_.end(); ++iter) {
266         int32_t resId = iter->first;
267         std::shared_ptr<ResStatus> resStatus = iter->second;
268         if (socPerfConfig_.resourceNodeInfo_.find(resId) != socPerfConfig_.resourceNodeInfo_.end() &&
269             (resStatus->previousValue != resStatus->currentValue ||
270             resStatus->previousEndTime != resStatus->currentEndTime)) {
271             if (socPerfConfig_.resourceNodeInfo_[resId]->persistMode == REPORT_TO_PERFSO) {
272                 qosId.push_back(resId);
273                 value.push_back(resStatus->currentValue);
274                 endTime.push_back(resStatus->currentEndTime);
275             } else {
276                 qosIdToRssEx.push_back(resId);
277                 valueToRssEx.push_back(resStatus->currentValue);
278                 endTimeToRssEx.push_back(resStatus->currentEndTime);
279             }
280             resStatus->previousValue = resStatus->currentValue;
281             resStatus->previousEndTime = resStatus->currentEndTime;
282             if (socPerfConfig_.resourceNodeInfo_[resId]->trace) {
283                 CountTraceEx(HITRACE_LEVEL_INFO, HITRACE_TAG_SOCPERF,
284                     socPerfConfig_.resourceNodeInfo_[resId]->name.c_str(),
285                     resStatus->currentValue == MAX_INT32_VALUE ? NODE_DEFAULT_VALUE : resStatus->currentValue);
286             }
287         }
288     }
289     ReportToPerfSo(qosId, value, endTime);
290     ReportToRssExe(qosIdToRssEx, valueToRssEx, endTimeToRssEx);
291 
292     WeakInteraction();
293 }
294 
ReportToPerfSo(std::vector<int32_t> & qosId,std::vector<int64_t> & value,std::vector<int64_t> & endTime)295 void SocPerfThreadWrap::ReportToPerfSo(std::vector<int32_t>& qosId, std::vector<int64_t>& value,
296     std::vector<int64_t>& endTime)
297 {
298     if (!socPerfConfig_.reportFunc_) {
299         return;
300     }
301     if (qosId.size() > 0) {
302         socPerfConfig_.reportFunc_(qosId, value, endTime, "");
303         std::string log("send data to perf so");
304         for (unsigned long i = 0; i < qosId.size(); i++) {
305             log.append(",[id:").append(std::to_string(qosId[i]));
306             log.append(", value:").append(std::to_string(value[i])).append("]");
307         }
308         StartTraceEx(HITRACE_LEVEL_INFO, HITRACE_TAG_SOCPERF, log.c_str());
309         FinishTraceEx(HITRACE_LEVEL_INFO, HITRACE_TAG_SOCPERF);
310     }
311 }
312 
ReportToRssExe(std::vector<int32_t> & qosId,std::vector<int64_t> & value,std::vector<int64_t> & endTime)313 void SocPerfThreadWrap::ReportToRssExe(std::vector<int32_t>& qosId, std::vector<int64_t>& value,
314     std::vector<int64_t>& endTime)
315 {
316     if (qosId.size() > 0) {
317         nlohmann::json payload;
318         payload[QOSID_STRING] = qosId;
319         payload[VALUE_STRING] = value;
320         ResourceSchedule::ResSchedExeClient::GetInstance().SendRequestAsync(
321             ResourceSchedule::ResExeType::EWS_TYPE_SOCPERF_EXECUTOR_ASYNC_EVENT, SOCPERF_EVENT_WIRTE_NODE, payload);
322         std::string log("send data to rssexe so");
323         for (unsigned long i = 0; i < qosId.size(); i++) {
324             log.append(",[id:").append(std::to_string(qosId[i]));
325             log.append(", value:").append(std::to_string(value[i])).append("]");
326         }
327         StartTraceEx(HITRACE_LEVEL_INFO, HITRACE_TAG_SOCPERF, log.c_str());
328         FinishTraceEx(HITRACE_LEVEL_INFO, HITRACE_TAG_SOCPERF);
329     }
330 }
331 
DoFreqActionLevel(int32_t resId,std::shared_ptr<ResAction> resAction)332 void SocPerfThreadWrap::DoFreqActionLevel(int32_t resId, std::shared_ptr<ResAction> resAction)
333 {
334     int32_t realResId = resId - RES_ID_ADDITION;
335     if (!socPerfConfig_.IsValidResId(realResId) || !resAction) {
336         return;
337     }
338     int32_t level = (int32_t)resAction->value;
339     if (!GetResValueByLevel(realResId, level, resAction->value)) {
340         return;
341     }
342     UpdateResActionList(realResId, resAction, false);
343 }
344 
PostDelayTask(std::shared_ptr<ResActionItem> queueHead)345 void SocPerfThreadWrap::PostDelayTask(std::shared_ptr<ResActionItem> queueHead)
346 {
347     if (queueHead == nullptr) {
348         return;
349     }
350     std::unordered_map<int32_t, std::vector<std::shared_ptr<ResActionItem>>> resActionMap;
351     std::shared_ptr<ResActionItem> head = queueHead;
352     while (head) {
353         if (!head->resAction || head->resAction->duration == 0) {
354             head = head->next;
355             continue;
356         }
357         resActionMap[head->resAction->duration].push_back(head);
358         head = head->next;
359     }
360     for (auto item : resActionMap) {
361         ffrt::task_attr taskAttr;
362         taskAttr.delay(item.first * SCALES_OF_MILLISECONDS_TO_MICROSECONDS);
363         std::function<void()>&& postDelayTaskFunc = [this, item]() {
364             for (uint32_t i = 0; i < item.second.size(); i++) {
365                 UpdateResActionList(item.second[i]->resId, item.second[i]->resAction, true);
366             }
367             SendResStatus();
368         };
369         socperfQueue_.submit(postDelayTaskFunc, taskAttr);
370     }
371 }
372 
GetResValueByLevel(int32_t resId,int32_t level,int64_t & resValue)373 bool SocPerfThreadWrap::GetResValueByLevel(int32_t resId, int32_t level, int64_t& resValue)
374 {
375     if (socPerfConfig_.resourceNodeInfo_.find(resId) == socPerfConfig_.resourceNodeInfo_.end()
376         || socPerfConfig_.resourceNodeInfo_[resId]->available.empty()) {
377         SOC_PERF_LOGE("resId[%{public}d] is not valid.", resId);
378         return false;
379     }
380     if (level < 0) {
381         return false;
382     }
383 
384     std::set<int64_t> available;
385     for (auto a : socPerfConfig_.resourceNodeInfo_[resId]->available) {
386         available.insert(a);
387     }
388     int32_t len = (int32_t)available.size();
389     auto iter = available.begin();
390     if (level < len) {
391         std::advance(iter, len - 1 - level);
392     }
393     resValue = *iter;
394     return true;
395 }
396 
UpdateResActionList(int32_t resId,std::shared_ptr<ResAction> resAction,bool delayed)397 void SocPerfThreadWrap::UpdateResActionList(int32_t resId, std::shared_ptr<ResAction> resAction, bool delayed)
398 {
399     std::shared_ptr<ResStatus> resStatus = resStatusInfo_[resId];
400     int32_t type = resAction->type;
401 
402     if (delayed) {
403         UpdateResActionListByDelayedMsg(resId, type, resAction, resStatus);
404     } else {
405         UpdateResActionListByInstantMsg(resId, type, resAction, resStatus);
406     }
407 }
408 
UpdateResActionListByDelayedMsg(int32_t resId,int32_t type,std::shared_ptr<ResAction> resAction,std::shared_ptr<ResStatus> resStatus)409 void SocPerfThreadWrap::UpdateResActionListByDelayedMsg(int32_t resId, int32_t type,
410     std::shared_ptr<ResAction> resAction, std::shared_ptr<ResStatus> resStatus)
411 {
412     for (auto iter = resStatus->resActionList[type].begin();
413         iter != resStatus->resActionList[type].end(); ++iter) {
414         if (resAction == *iter) {
415             resStatus->resActionList[type].erase(iter);
416             UpdateCandidatesValue(resId, type);
417             if (resAction->interaction) {
418                 boostResCnt--;
419             }
420             break;
421         }
422     }
423 }
424 
HandleResAction(int32_t resId,int32_t type,std::shared_ptr<ResAction> resAction,std::shared_ptr<ResStatus> resStatus)425 void SocPerfThreadWrap::HandleResAction(int32_t resId, int32_t type,
426     std::shared_ptr<ResAction> resAction, std::shared_ptr<ResStatus> resStatus)
427 {
428     for (auto iter = resStatus->resActionList[type].begin();
429          iter != resStatus->resActionList[type].end(); ++iter) {
430         if (resAction->TotalSame(*iter)) {
431             resStatus->resActionList[type].erase(iter);
432             if (resAction->interaction) {
433                 boostResCnt--;
434             }
435             break;
436         }
437     }
438     resStatus->resActionList[type].push_back(resAction);
439     UpdateCandidatesValue(resId, type);
440     if (resAction->interaction) {
441         boostResCnt++;
442     }
443 }
444 
UpdateResActionListByInstantMsg(int32_t resId,int32_t type,std::shared_ptr<ResAction> resAction,std::shared_ptr<ResStatus> resStatus)445 void SocPerfThreadWrap::UpdateResActionListByInstantMsg(int32_t resId, int32_t type,
446     std::shared_ptr<ResAction> resAction, std::shared_ptr<ResStatus> resStatus)
447 {
448     switch (resAction->onOff) {
449         case EVENT_INVALID:
450         case EVENT_ON: {
451             HandleResAction(resId, type, resAction, resStatus);
452             break;
453         }
454         case EVENT_OFF: {
455             for (auto iter = resStatus->resActionList[type].begin();
456                 iter != resStatus->resActionList[type].end(); ++iter) {
457                 if (resAction->PartSame(*iter) && (*iter)->onOff == EVENT_ON) {
458                     resStatus->resActionList[type].erase(iter);
459                     UpdateCandidatesValue(resId, type);
460                     boostResCnt = boostResCnt - (resAction->interaction ? 1 : 0);
461                     break;
462                 }
463             }
464             break;
465         }
466         default: {
467             break;
468         }
469     }
470 }
471 
UpdateCandidatesValue(int32_t resId,int32_t type)472 void SocPerfThreadWrap::UpdateCandidatesValue(int32_t resId, int32_t type)
473 {
474     std::shared_ptr<ResStatus> resStatus = resStatusInfo_[resId];
475     int64_t prevValue = resStatus->candidatesValue[type];
476     int64_t prevEndTime = resStatus->candidatesEndTime[type];
477 
478     if (resStatus->resActionList[type].empty()) {
479         resStatus->candidatesValue[type] = INVALID_VALUE;
480         resStatus->candidatesEndTime[type] = MAX_INT_VALUE;
481     } else {
482         InnerArbitrateCandidatesValue(type, resStatus);
483     }
484 
485     if (resStatus->candidatesValue[type] != prevValue || resStatus->candidatesEndTime[type] != prevEndTime) {
486         ArbitrateCandidate(resId);
487     }
488 }
489 
InnerArbitrateCandidatesValue(int32_t type,std::shared_ptr<ResStatus> resStatus)490 void SocPerfThreadWrap::InnerArbitrateCandidatesValue(int32_t type, std::shared_ptr<ResStatus> resStatus)
491 {
492     // perf first action type:  ACTION_TYPE_PERF\ACTION_TYPE_PERFLVL
493     // power first action type: ACTION_TYPE_POWER\ACTION_TYPE_THERMAL
494     bool isPerfFirst = (type == ACTION_TYPE_PERF || type == ACTION_TYPE_PERFLVL);
495 
496     int64_t res = isPerfFirst ? MIN_INT_VALUE : MAX_INT_VALUE;
497     int64_t endTime = MIN_INT_VALUE;
498     for (auto iter = resStatus->resActionList[type].begin();
499         iter != resStatus->resActionList[type].end(); ++iter) {
500         if (((*iter)->value > res && isPerfFirst)
501             || ((*iter)->value < res && !isPerfFirst)) {
502             res = (*iter)->value;
503             endTime = (*iter)->endTime;
504         } else if ((*iter)->value == res) {
505             endTime = Max(endTime, (*iter)->endTime);
506         }
507     }
508     resStatus->candidatesValue[type] = res;
509     resStatus->candidatesEndTime[type] = endTime;
510 }
511 
ArbitrateCandidate(int32_t resId)512 void SocPerfThreadWrap::ArbitrateCandidate(int32_t resId)
513 {
514     std::shared_ptr<ResStatus> resStatus = resStatusInfo_[resId];
515     // if perf, power and thermal don't have valid value, send default value
516     if (ExistNoCandidate(resId, resStatus)) {
517         return;
518     }
519     // Arbitrate in perf, power and thermal
520     ProcessLimitCase(resId);
521     // perf request thermal level is highest priority in this freq adjuster
522     if (ArbitratePairResInPerfLvl(resId)) {
523         return;
524     }
525     // adjust resource value if it has 'max' config
526     ArbitratePairRes(resId, false);
527 }
528 
ProcessLimitCase(int32_t resId)529 void SocPerfThreadWrap::ProcessLimitCase(int32_t resId)
530 {
531     std::shared_ptr<ResStatus> resStatus = resStatusInfo_[resId];
532     int64_t candidatePerfValue = resStatus->candidatesValue[ACTION_TYPE_PERF];
533     int64_t candidatePowerValue = resStatus->candidatesValue[ACTION_TYPE_POWER];
534     int64_t candidateThermalValue = resStatus->candidatesValue[ACTION_TYPE_THERMAL];
535     if (!powerLimitBoost_ && !thermalLimitBoost_) {
536         if (candidatePerfValue != INVALID_VALUE) {
537             resStatus->candidate = Max(candidatePerfValue, candidatePowerValue, candidateThermalValue);
538         } else {
539             resStatus->candidate = (candidatePowerValue == INVALID_VALUE) ? candidateThermalValue :
540                 ((candidateThermalValue == INVALID_VALUE) ? candidatePowerValue :
541                 Min(candidatePowerValue, candidateThermalValue));
542         }
543     } else if (!powerLimitBoost_ && thermalLimitBoost_) {
544         resStatus->candidate = (candidateThermalValue != INVALID_VALUE) ? candidateThermalValue :
545             Max(candidatePerfValue, candidatePowerValue);
546     } else if (powerLimitBoost_ && !thermalLimitBoost_) {
547         resStatus->candidate = (candidatePowerValue != INVALID_VALUE) ? candidatePowerValue :
548             Max(candidatePerfValue, candidateThermalValue);
549     } else {
550         if (candidatePowerValue == INVALID_VALUE && candidateThermalValue == INVALID_VALUE) {
551             resStatus->candidate = candidatePerfValue;
552         } else {
553             resStatus->candidate = (candidatePowerValue == INVALID_VALUE) ? candidateThermalValue :
554                 ((candidateThermalValue == INVALID_VALUE) ? candidatePowerValue :
555                 Min(candidatePowerValue, candidateThermalValue));
556         }
557     }
558     resStatus->currentEndTime = Min(resStatus->candidatesEndTime[ACTION_TYPE_PERF],
559         resStatus->candidatesEndTime[ACTION_TYPE_POWER], resStatus->candidatesEndTime[ACTION_TYPE_THERMAL]);
560 }
561 
ArbitratePairResInPerfLvl(int32_t resId)562 bool SocPerfThreadWrap::ArbitratePairResInPerfLvl(int32_t resId)
563 {
564     std::shared_ptr<ResStatus> resStatus = resStatusInfo_[resId];
565     int32_t pairResId = INVALID_VALUE;
566     if (!socPerfConfig_.IsGovResId(resId)) {
567         pairResId = std::static_pointer_cast<ResNode>(socPerfConfig_.resourceNodeInfo_[resId])->pair;
568     }
569     // if resource self and resource's pair both not have perflvl value
570     if (resStatus->candidatesValue[ACTION_TYPE_PERFLVL] == INVALID_VALUE && (pairResId != INVALID_VALUE &&
571         resStatusInfo_[pairResId]->candidatesValue[ACTION_TYPE_PERFLVL] == INVALID_VALUE)) {
572         return false;
573     }
574     // if this resource has PerfRequestLvl value, the final arbitrate value change to PerfRequestLvl value
575     if (resStatus->candidatesValue[ACTION_TYPE_PERFLVL] != INVALID_VALUE) {
576         if (thermalLvl_ == 0 && resStatus->candidate != INVALID_VALUE) {
577             resStatus->candidate = Min(resStatus->candidate, resStatus->candidatesValue[ACTION_TYPE_PERFLVL]);
578         } else {
579             resStatus->candidate = resStatus->candidatesValue[ACTION_TYPE_PERFLVL];
580         }
581     }
582     // only limit max when PerfRequestLvl has max value
583     bool limit = false;
584     if (thermalLvl_ != 0 &&
585         !socPerfConfig_.IsGovResId(resId) &&
586         (socPerfConfig_.resourceNodeInfo_[resId]->isMaxValue ||
587         (pairResId != INVALID_VALUE && socPerfConfig_.resourceNodeInfo_[pairResId]->isMaxValue))) {
588         limit = true;
589     }
590     ArbitratePairRes(resId, limit);
591     return true;
592 }
593 
ArbitratePairRes(int32_t resId,bool perfRequestLimit)594 void SocPerfThreadWrap::ArbitratePairRes(int32_t resId, bool perfRequestLimit)
595 {
596     bool limit = powerLimitBoost_ || thermalLimitBoost_ || perfRequestLimit;
597     if (socPerfConfig_.IsGovResId(resId)) {
598         UpdateCurrentValue(resId, resStatusInfo_[resId]->candidate);
599         return;
600     }
601     int32_t pairResId = std::static_pointer_cast<ResNode>(socPerfConfig_.resourceNodeInfo_[resId])->pair;
602     if (pairResId == INVALID_VALUE) {
603         UpdateCurrentValue(resId, resStatusInfo_[resId]->candidate);
604         return;
605     }
606 
607     if (resStatusInfo_[pairResId]->candidate == NODE_DEFAULT_VALUE ||
608         resStatusInfo_[resId]->candidate == NODE_DEFAULT_VALUE) {
609         UpdatePairResValue(resId, resStatusInfo_[resId]->candidate, pairResId, resStatusInfo_[pairResId]->candidate);
610         return;
611     }
612 
613     if (socPerfConfig_.resourceNodeInfo_[resId]->isMaxValue) {
614         if (resStatusInfo_[resId]->candidate < resStatusInfo_[pairResId]->candidate) {
615             if (limit) {
616                 UpdatePairResValue(pairResId,
617                     resStatusInfo_[resId]->candidate, resId, resStatusInfo_[resId]->candidate);
618             } else {
619                 UpdatePairResValue(pairResId,
620                     resStatusInfo_[pairResId]->candidate, resId, resStatusInfo_[pairResId]->candidate);
621             }
622         } else {
623             UpdatePairResValue(pairResId,
624                 resStatusInfo_[pairResId]->candidate, resId, resStatusInfo_[resId]->candidate);
625         }
626     } else {
627         if (resStatusInfo_[resId]->candidate > resStatusInfo_[pairResId]->candidate) {
628             if (limit) {
629                 UpdatePairResValue(resId,
630                     resStatusInfo_[pairResId]->candidate, pairResId, resStatusInfo_[pairResId]->candidate);
631             } else {
632                 UpdatePairResValue(resId,
633                     resStatusInfo_[resId]->candidate, pairResId, resStatusInfo_[resId]->candidate);
634             }
635         } else {
636             UpdatePairResValue(resId,
637                 resStatusInfo_[resId]->candidate, pairResId, resStatusInfo_[pairResId]->candidate);
638         }
639     }
640 }
641 
UpdatePairResValue(int32_t minResId,int64_t minResValue,int32_t maxResId,int64_t maxResValue)642 void SocPerfThreadWrap::UpdatePairResValue(int32_t minResId, int64_t minResValue, int32_t maxResId,
643     int64_t maxResValue)
644 {
645     UpdateCurrentValue(minResId, minResValue);
646     UpdateCurrentValue(maxResId, maxResValue);
647 }
648 
UpdateCurrentValue(int32_t resId,int64_t currValue)649 void SocPerfThreadWrap::UpdateCurrentValue(int32_t resId, int64_t currValue)
650 {
651     resStatusInfo_[resId]->currentValue = currValue;
652 }
653 
ExistNoCandidate(int32_t resId,std::shared_ptr<ResStatus> resStatus)654 bool SocPerfThreadWrap::ExistNoCandidate(int32_t resId, std::shared_ptr<ResStatus> resStatus)
655 {
656     int64_t perfCandidate = resStatus->candidatesValue[ACTION_TYPE_PERF];
657     int64_t powerCandidate = resStatus->candidatesValue[ACTION_TYPE_POWER];
658     int64_t thermalCandidate = resStatus->candidatesValue[ACTION_TYPE_THERMAL];
659     int64_t perfLvlCandidate = resStatus->candidatesValue[ACTION_TYPE_PERFLVL];
660     if (perfCandidate == INVALID_VALUE && powerCandidate == INVALID_VALUE && thermalCandidate == INVALID_VALUE
661         && perfLvlCandidate == INVALID_VALUE) {
662         resStatus->candidate = NODE_DEFAULT_VALUE;
663         resStatus->currentEndTime = MAX_INT_VALUE;
664         ArbitratePairRes(resId, false);
665         return true;
666     }
667     return false;
668 }
669 } // namespace SOCPERF
670 } // namespace OHOS
671