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