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