1 /*
2 * Copyright (c) 2023 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 <cerrno>
16 #include <cstring>
17 #include <unistd.h>
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <fcntl.h>
21 #include <array>
22 #include "eu/qos_interface.h"
23 #include "dfx/log/ffrt_log_api.h"
24 #include "eu/osattr_manager.h"
25
26 namespace ffrt {
27 const int fd_buffer_len = 20;
28
CheckSchedAttrPara(const std::string & name,int min,int max,int paraValue)29 bool OSAttrManager::CheckSchedAttrPara(const std::string &name, int min, int max, int paraValue)
30 {
31 if (paraValue < min || paraValue > max) {
32 FFRT_LOGE("OSAttrManager::CheckAttrPara para %s is invalid", name.c_str());
33 return false;
34 }
35 return true;
36 }
37
UpdateSchedAttr(const QoS & qos,ffrt_os_sched_attr * attr)38 int OSAttrManager::UpdateSchedAttr(const QoS& qos, ffrt_os_sched_attr *attr)
39 {
40 FFRT_LOGI("OSAttrManager::UpdateSchedAttr start qos[%d] attr.lat_nice[%d] attr.cpumap[0x%s] attr.u_min[%d]\
41 attr.shares[%d]", qos(), attr->latency_nice, attr->cpumap, attr->uclamp_min, attr->shares);
42 if (qos() <= qos_max) {
43 FFRT_LOGE("qos[%d] attr update is not supported.\n", qos());
44 return -1;
45 }
46
47 struct SchedParaCheckInfo {
48 std::string paraName;
49 int min;
50 int max;
51 int paraValue;
52 };
53
54 std::vector<SchedParaCheckInfo> checkInfo {
55 { "share", CGROUP_SHARES_MIN, CGROUP_SHARES_MAX, attr->shares},
56 { "latencynice", CGROUP_LAT_NICE_MIN, CGROUP_LAT_NICE_MAX, attr->latency_nice},
57 { "uclampmin", CGROUP_UCLAMP_MIN, CGROUP_UCLAMP_MAX, attr->uclamp_min},
58 { "uclampmax", CGROUP_UCLAMP_MIN, CGROUP_UCLAMP_MAX, attr->uclamp_max},
59 { "vipprio", CGROUP_VIPPRIO_MIN, CGROUP_VIPPRIO_MAX, attr->vip_prio},
60 };
61
62 for (const auto &tmpPara : checkInfo) {
63 if (!CheckSchedAttrPara(tmpPara.paraName, tmpPara.min, tmpPara.max, tmpPara.paraValue)) {
64 return -1;
65 }
66 }
67
68 SetCGroupCtlPara(cpuSharesNode, attr->shares);
69 SetCGroupCtlPara(cpuLatencyniceNode, attr->latency_nice);
70 SetCGroupCtlPara(cpuUclampminNode, attr->uclamp_min);
71 SetCGroupCtlPara(cpuUclampmaxNode, attr->uclamp_max);
72 SetCGroupCtlPara(cpuvipprioNode, attr->vip_prio);
73 SetCGroupSetPara(cpuMapNode, static_cast<std::string>(attr->cpumap));
74 return 0;
75 }
76
SetCGroupCtlPara(const std::string & name,int32_t value)77 void OSAttrManager::SetCGroupCtlPara(const std::string &name, int32_t value)
78 {
79 const std::string filename = cpuctlGroupIvePath + name;
80 SetCGroupPara(filename, value);
81 }
82
SetCGroupSetPara(const std::string & name,const std::string & value)83 void OSAttrManager::SetCGroupSetPara(const std::string &name, const std::string &value)
84 {
85 const std::string filename = cpusetGroupIvePath + name;
86 SetCGroupPara(filename, value);
87 }
88
SetTidToCGroup(int32_t pid)89 void OSAttrManager::SetTidToCGroup(int32_t pid)
90 {
91 SetTidToCGroupPrivate(cpuctlGroupIvePath + cpuThreadNode, pid);
92 SetTidToCGroupPrivate(cpusetGroupIvePath + cpuThreadNode, pid);
93 }
94
SetTidToCGroupPrivate(const std::string & filename,int32_t pid)95 void OSAttrManager::SetTidToCGroupPrivate(const std::string &filename, int32_t pid)
96 {
97 constexpr int32_t maxThreadId = 0xffff;
98 if (pid <= 0 || pid >= maxThreadId) {
99 FFRT_LOGE("[cgroup_ctrl] invalid pid[%d]\n", pid);
100 return;
101 }
102 SetCGroupPara(filename, pid);
103 }
104
105 template <typename T>
SetCGroupPara(const std::string & filename,T & value)106 void OSAttrManager::SetCGroupPara(const std::string &filename, T& value)
107 {
108 char filePath[PATH_MAX_LENS] = {0};
109 if (filename.empty()) {
110 FFRT_LOGE("[cgroup_ctrl] invalid para, filename is empty");
111 return;
112 }
113
114 if ((strlen(filename.c_str()) > PATH_MAX_LENS) || (realpath(filename.c_str(), filePath) == nullptr)) {
115 FFRT_LOGE("[cgroup_ctrl] invalid file path:%s, error:%s\n", filename.c_str(), strerror(errno));
116 return;
117 }
118
119 int32_t fd = open(filePath, O_RDWR);
120 if (fd < 0) {
121 FFRT_LOGE("[cgroup_ctrl] fail to open filePath:%s", filePath);
122 return;
123 }
124
125 std::string valueStr;
126 if constexpr (std::is_same<T, int32_t>::value) {
127 valueStr = std::to_string(value);
128 } else if constexpr (std::is_same<T, const std::string>::value) {
129 valueStr = value;
130 } else {
131 FFRT_LOGE("[cgroup_ctrl] invalid value type\n");
132 close(fd);
133 return;
134 }
135
136 int32_t ret = write(fd, valueStr.c_str(), valueStr.size());
137 if (ret < 0) {
138 FFRT_LOGE("[cgroup_ctrl] fail to write path:%s valueStr:%s to fd:%d, errno:%d",
139 filePath, valueStr.c_str(), fd, errno);
140 close(fd);
141 return;
142 }
143
144 const uint32_t bufferLen = fd_buffer_len;
145 std::array<char, bufferLen> buffer {};
146 int32_t count = read(fd, buffer.data(), bufferLen);
147 if (count <= 0) {
148 FFRT_LOGE("[cgroup_ctrl] fail to read value:%s to fd:%d, errno:%d", buffer.data(), fd, errno);
149 } else {
150 FFRT_LOGI("[cgroup_ctrl] success to read %s buffer:%s", filePath, buffer.data());
151 }
152 close(fd);
153 }
154 } // namespace ffrt