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