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 "process_group_log.h" // for PGCGS_LOGE, PGCGS_LOGD, PGCGS_LOGI
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 PGCGS_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
LoadConfigFromJsonObj(const nlohmann::json & jsonObj)60 bool CgroupMap::LoadConfigFromJsonObj(const nlohmann::json& jsonObj)
61 {
62 const nlohmann::json& jsonArrObj = jsonObj[JSON_KEY_CGROUPS];
63 // check json format
64 if (!jsonArrObj.is_array()) {
65 PGCGS_LOGE("%{public}s json config format error, CgroupMap: disabled!", __func__);
66 return false;
67 }
68 int count = 0;
69 int32_t objSize = static_cast<int32_t>(jsonArrObj.size());
70 for (int32_t i = 0; i < objSize; ++i) {
71 const nlohmann::json& cgroupObj = jsonArrObj[i];
72 const nlohmann::json& nameObj = cgroupObj[JSON_KEY_CONTROLLER];
73 const nlohmann::json& pathObj = cgroupObj[JSON_KEY_PATH];
74 if (!nameObj.is_string() || !pathObj.is_string()) {
75 PGCGS_LOGE("%{public}s invalid controller config.", __func__);
76 continue;
77 }
78 std::string name = nameObj.get<std::string>();
79 std::string rootPath = pathObj.get<std::string>();
80 if (name.empty() || rootPath.empty()) {
81 PGCGS_LOGE("%{public}s empty controller config.", __func__);
82 continue;
83 }
84
85 CgroupController controller(name, rootPath);
86 if (LoadSchedPolicyConfig(controller, cgroupObj[JSON_KEY_SCHED_POLICY])) {
87 this->AddCgroupController(name, controller);
88 count++;
89 } else {
90 PGCGS_LOGE("%{public}s no valid policy config item.", __func__);
91 }
92 }
93
94 if (count == 0) {
95 PGCGS_LOGW("%{public}s The number of valid cgroup config is 0, CgroupMap: disabled!", __func__);
96 return false;
97 }
98 PGCGS_LOGI("%{public}s CgroupMap: enabled!", __func__);
99 return true;
100 }
101
LoadSchedPolicyConfig(CgroupController & controller,const nlohmann::json & policyObj)102 bool CgroupMap::LoadSchedPolicyConfig(CgroupController& controller, const nlohmann::json& policyObj)
103 {
104 if (!policyObj.is_object()) {
105 PGCGS_LOGE("%{public}s invalid policy config.", __func__);
106 return false;
107 }
108
109 auto policyList = CgroupAction::GetInstance().GetSchedPolicyList();
110 uint32_t count = 0;
111 for (SchedPolicy policy : policyList) {
112 const char* keyString = GetSchedPolicyFullName(policy);
113 if (!keyString || !strcmp(keyString, "error")) {
114 continue;
115 }
116 const nlohmann::json& obj = policyObj[keyString];
117 if (!obj.is_string()) {
118 PGCGS_LOGE("%{public}s %s is not properly configed.", __func__, keyString);
119 continue;
120 }
121 if (controller.AddSchedPolicy(policy, obj.get<std::string>())) {
122 count++;
123 }
124 }
125 return (count > 0);
126 }
127
FindFristEnableCgroupController(CgroupController ** p)128 bool CgroupMap::FindFristEnableCgroupController(CgroupController** p)
129 {
130 for (auto it = controllers_.begin(); it != controllers_.end(); ++it) {
131 if (it->second.IsEnabled()) {
132 *p = &(it->second);
133 return true;
134 }
135 }
136 return false;
137 }
138 } // namespace CgroupSetting
139 } // namespace ResourceSchedule
140 } // namespace OHOS
141