• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 "cgroup_map.h"
16 #include <cstdint>              // for uint32_t
17 #include <string>               // for basic_string, operator<
18 #include <cstring>              // for strcmp
19 #include <type_traits>          // for remove_reference<>::type, move
20 #include <utility>              // for pair, make_pair
21 #include <vector>               // for vector
22 #include "cgroup_action.h"      // for CgroupAction
23 #include "cgroup_sched_log.h"
24 
25 namespace OHOS {
26 namespace ResourceSchedule {
27 namespace CgroupSetting {
28 namespace {
29     constexpr const char * const JSON_KEY_CGROUPS = "Cgroups";
30     constexpr const char * const JSON_KEY_CONTROLLER = "controller";
31     constexpr const char * const JSON_KEY_PATH = "path";
32     constexpr const char * const JSON_KEY_SCHED_POLICY = "sched_policy";
33 }
34 
GetInstance()35 CgroupMap& CgroupMap::GetInstance()
36 {
37     static CgroupMap instance;
38     return instance;
39 }
40 
SetThreadSchedPolicy(int tid,SchedPolicy policy,bool isThreadGroup)41 bool CgroupMap::SetThreadSchedPolicy(int tid, SchedPolicy policy, bool isThreadGroup)
42 {
43     for (auto it = controllers_.begin(); it != controllers_.end(); ++it) {
44         CgroupController& controller = it -> second;
45         if (controller.IsEnabled()) {
46             if (!controller.SetThreadSchedPolicy(tid, policy, isThreadGroup)) {
47                 CGS_LOGD("%{public}s failed, controller = %{public}s, policy = %{public}d.",
48                     __func__, controller.GetName().c_str(), policy);
49             }
50         }
51     }
52     return true;
53 }
54 
AddCgroupController(const std::string & name,CgroupController & controller)55 void CgroupMap::AddCgroupController(const std::string& name, CgroupController& controller)
56 {
57     controllers_.insert(std::make_pair(name, std::move(controller)));
58 }
59 
CheckCgroupConfigFormat(const nlohmann::json & cgroupObj)60 bool CgroupMap::CheckCgroupConfigFormat(const nlohmann::json& cgroupObj)
61 {
62     if (!cgroupObj.is_object()) {
63         CGS_LOGE("%{public}s cgroup config format error!", __func__);
64         return false;
65     }
66     if (!cgroupObj.contains(JSON_KEY_CONTROLLER) || !cgroupObj.at(JSON_KEY_CONTROLLER).is_string()) {
67         CGS_LOGE("%{public}s cgroup controller is not properly configured!", __func__);
68         return false;
69     }
70     if (!cgroupObj.contains(JSON_KEY_PATH) || !cgroupObj.at(JSON_KEY_PATH).is_string()) {
71         CGS_LOGE("%{public}s cgroup path is not properly configured!", __func__);
72         return false;
73     }
74     if (!cgroupObj.contains(JSON_KEY_SCHED_POLICY) || !cgroupObj.at(JSON_KEY_SCHED_POLICY).is_object()) {
75         CGS_LOGE("%{public}s cgroup policy is not properly configured!", __func__);
76         return false;
77     }
78     return true;
79 }
80 
LoadConfigFromJsonObj(const nlohmann::json & jsonObj)81 bool CgroupMap::LoadConfigFromJsonObj(const nlohmann::json& jsonObj)
82 {
83     // check json format
84     if (!jsonObj.is_object() || !jsonObj.contains(JSON_KEY_CGROUPS)
85         || !jsonObj.at(JSON_KEY_CGROUPS).is_array()) {
86         CGS_LOGE("%{public}s json config format error, CgroupMap: disabled!", __func__);
87         return false;
88     }
89     const nlohmann::json& jsonArrObj = jsonObj[JSON_KEY_CGROUPS];
90     int count = 0;
91     int32_t objSize = static_cast<int32_t>(jsonArrObj.size());
92     for (int32_t i = 0; i < objSize; ++i) {
93         const nlohmann::json& cgroupObj = jsonArrObj[i];
94         if (!CheckCgroupConfigFormat(cgroupObj)) {
95             continue;
96         }
97 
98         std::string name = cgroupObj[JSON_KEY_CONTROLLER].get<std::string>();
99         std::string rootPath = cgroupObj[JSON_KEY_PATH].get<std::string>();
100         if (name.empty() || rootPath.empty()) {
101             CGS_LOGE("%{public}s empty controller config.", __func__);
102             continue;
103         }
104 
105         CgroupController controller(name, rootPath);
106         if (LoadSchedPolicyConfig(controller, cgroupObj[JSON_KEY_SCHED_POLICY])) {
107             this->AddCgroupController(name, controller);
108             count++;
109         } else {
110             CGS_LOGE("%{public}s no valid policy config item.", __func__);
111         }
112     }
113 
114     if (count == 0) {
115         CGS_LOGW("%{public}s The number of valid cgroup config is 0, CgroupMap: disabled!", __func__);
116         return false;
117     }
118     CGS_LOGI("%{public}s CgroupMap: enabled!", __func__);
119     return true;
120 }
121 
LoadSchedPolicyConfig(CgroupController & controller,const nlohmann::json & policyObj)122 bool CgroupMap::LoadSchedPolicyConfig(CgroupController& controller, const nlohmann::json& policyObj)
123 {
124     if (!policyObj.is_object()) {
125         CGS_LOGE("%{public}s invalid policy config.", __func__);
126         return false;
127     }
128 
129     auto policyList = CgroupAction::GetInstance().GetSchedPolicyList();
130     uint32_t count = 0;
131     for (SchedPolicy policy : policyList) {
132         const char* keyString = GetSchedPolicyFullName(policy);
133         if (!keyString || !strcmp(keyString, "error")) {
134             continue;
135         }
136         if (!policyObj.contains(keyString) || !policyObj.at(keyString).is_string()) {
137             CGS_LOGD("%{public}s %{public}s is not properly configed.", __func__, keyString);
138             continue;
139         }
140         if (controller.AddSchedPolicy(policy, policyObj[keyString].get<std::string>())) {
141             count++;
142         }
143     }
144     return (count > 0);
145 }
146 
FindAllEnableCgroupControllers(std::vector<CgroupController * > & controllers)147 bool CgroupMap::FindAllEnableCgroupControllers(std::vector<CgroupController *> &controllers)
148 {
149     for (auto it = controllers_.begin(); it != controllers_.end(); ++it) {
150         if (it->second.IsEnabled()) {
151             controllers.emplace_back(&(it->second));
152         }
153     }
154     return controllers.size() != 0;
155 }
156 } // namespace CgroupSetting
157 } // namespace ResourceSchedule
158 } // namespace OHOS
159