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 
16 #ifndef GNU_SOURCE
17 #define GNU_SOURCE
18 #endif
19 #include <cerrno>
20 #include <cstdio>
21 #include <unistd.h>
22 #include <sys/ioctl.h>
23 #include <fcntl.h>
24 #include <concurrent_task_log.h>
25 
26 #include "qos_interface.h"
27 
TrivalOpenRtgNode(void)28 static int TrivalOpenRtgNode(void)
29 {
30     char fileName[] = "/proc/self/sched_rtg_ctrl";
31     int fd = open(fileName, O_RDWR);
32     if (fd < 0) {
33         CONCUR_LOGE("[Interface] task %{public}d belong to user %{public}d open rtg node failed, errno = %{public}d",
34             getpid(), getuid(), errno);
35     }
36     return fd;
37 }
38 
TrivalOpenAuthCtrlNode(void)39 static int TrivalOpenAuthCtrlNode(void)
40 {
41     char fileName[] = "/dev/auth_ctrl";
42     int fd = open(fileName, O_RDWR);
43     if (fd < 0) {
44         CONCUR_LOGE("[Interface] task %{public}d belong to user %{public}d open auth node failed, errno = %{public}d",
45             getpid(), getuid(), errno);
46     }
47     return fd;
48 }
49 
TrivalOpenQosCtrlNode(void)50 static int TrivalOpenQosCtrlNode(void)
51 {
52     char fileName[] = "/proc/thread-self/sched_qos_ctrl";
53     int fd = open(fileName, O_RDWR);
54     if (fd < 0) {
55         CONCUR_LOGE("[Interface] task %{public}d belong to user %{public}d open qos node failed, errno = %{public}d",
56             getpid(), getuid(), errno);
57     }
58     return fd;
59 }
60 
EnableRtg(bool flag)61 int EnableRtg(bool flag)
62 {
63     struct RtgEnableData enableData;
64     char configStr[] = "load_freq_switch:1;sched_cycle:1;frame_max_util:1024";
65     int ret;
66 
67     enableData.enable = flag;
68     enableData.len = sizeof(configStr);
69     enableData.data = configStr;
70     int fd = TrivalOpenRtgNode();
71     if (fd < 0) {
72         return fd;
73     }
74 
75     ret = ioctl(fd, CMD_ID_SET_ENABLE, &enableData);
76     if (ret < 0) {
77         printf("set rtg config enable failed.\n");
78     }
79 
80     close(fd);
81 
82     return 0;
83 };
84 
AuthEnable(unsigned int pid, unsigned int uaFlag, unsigned int status)85 int AuthEnable(unsigned int pid, unsigned int uaFlag, unsigned int status)
86 {
87     struct AuthCtrlData data;
88     int fd;
89     int ret;
90 
91     fd = TrivalOpenAuthCtrlNode();
92     if (fd < 0) {
93         return fd;
94     }
95 
96     data.pid = pid;
97     data.rtgUaFlag = uaFlag;
98     data.qosUaFlag = AF_QOS_DELEGATED;
99     data.status = status;
100     data.type = static_cast<unsigned int>(AuthManipulateType::AUTH_ENABLE);
101 
102     ret = ioctl(fd, BASIC_AUTH_CTRL_OPERATION, &data);
103 #ifdef QOS_DEBUG
104     if (ret < 0) {
105         printf("auth enable failed for pid %u with status %u\n", pid, status);
106     }
107 #endif
108     close(fd);
109     return ret;
110 }
111 
AuthSwitch(unsigned int pid, unsigned int rtgFlag, unsigned int qosFlag, unsigned int status)112 int AuthSwitch(unsigned int pid, unsigned int rtgFlag, unsigned int qosFlag, unsigned int status)
113 {
114     struct AuthCtrlData data;
115     int fd;
116     int ret;
117 
118     fd = TrivalOpenAuthCtrlNode();
119     if (fd < 0) {
120         return fd;
121     }
122 
123     data.pid = pid;
124     data.rtgUaFlag = rtgFlag;
125     data.qosUaFlag = qosFlag;
126     data.status = status;
127     data.type = static_cast<unsigned int>(AuthManipulateType::AUTH_SWITCH);
128 
129     ret = ioctl(fd, BASIC_AUTH_CTRL_OPERATION, &data);
130 #ifdef QOS_DEBUG
131     if (ret < 0) {
132         printf("auth switch failed for pid %u with status %u\n", pid, status);
133     }
134 #endif
135     close(fd);
136     return ret;
137 }
138 
AuthDelete(unsigned int pid)139 int AuthDelete(unsigned int pid)
140 {
141     struct AuthCtrlData data;
142     int fd;
143     int ret;
144 
145     fd = TrivalOpenAuthCtrlNode();
146     if (fd < 0) {
147         return fd;
148     }
149 
150     data.pid = pid;
151     data.type = static_cast<unsigned int>(AuthManipulateType::AUTH_DELETE);
152 
153     ret = ioctl(fd, BASIC_AUTH_CTRL_OPERATION, &data);
154 #ifdef QOS_DEBUG
155     if (ret < 0) {
156         printf("auth delete failed for pid %u\n", pid);
157     }
158 #endif
159     close(fd);
160     return ret;
161 }
162 
AuthPause(unsigned int pid)163 int AuthPause(unsigned int pid)
164 {
165     struct AuthCtrlData data;
166     int fd;
167     int ret;
168 
169     fd = TrivalOpenAuthCtrlNode();
170     if (fd < 0) {
171         return fd;
172     }
173 
174     data.pid = pid;
175     data.type = static_cast<unsigned int>(AuthManipulateType::AUTH_SWITCH);
176     data.rtgUaFlag = 0;
177     data.qosUaFlag = AF_QOS_DELEGATED;
178     data.status = static_cast<unsigned int>(AuthStatus::AUTH_STATUS_BACKGROUND);
179 
180     ret = ioctl(fd, BASIC_AUTH_CTRL_OPERATION, &data);
181 #ifdef QOS_DEBUG
182     if (ret < 0) {
183         printf("auth pause failed for pid %u\n", pid);
184     }
185 #endif
186     close(fd);
187     return ret;
188 }
189 
AuthGet(unsigned int pid)190 int AuthGet(unsigned int pid)
191 {
192     struct AuthCtrlData data;
193     int fd;
194     int ret;
195 
196     fd = TrivalOpenAuthCtrlNode();
197     if (fd < 0) {
198         return fd;
199     }
200 
201     data.pid = pid;
202     data.type = static_cast<unsigned int>(AuthManipulateType::AUTH_GET);
203 
204     ret = ioctl(fd, BASIC_AUTH_CTRL_OPERATION, &data);
205     if (ret < 0) {
206         close(fd);
207         return ret;
208     }
209     close(fd);
210 
211     return static_cast<int>(data.status);
212 }
213 
AuthEnhance(unsigned int pid, bool enhanceStatus)214 int AuthEnhance(unsigned int pid, bool enhanceStatus)
215 {
216     int ret = 0;
217 #ifdef QOS_EXT_ENABLE
218     struct AuthCtrlData data;
219     int fd = TrivalOpenAuthCtrlNode();
220     if (fd < 0) {
221         return fd;
222     }
223 
224     data.pid = pid;
225     data.enhanceStatus = enhanceStatus;
226     ret = ioctl(fd, ENHANCE_AUTH_CTRL_OPERATION, &data);
227     close(fd);
228 #endif
229     return ret;
230 }
231 
QosApply(unsigned int level)232 int QosApply(unsigned int level)
233 {
234     int tid = gettid();
235     int ret;
236 
237     ret = QosApplyForOther(level, tid);
238     return ret;
239 }
240 
QosApplyForOther(unsigned int level, int tid)241 int QosApplyForOther(unsigned int level, int tid)
242 {
243     struct QosCtrlData data;
244     int fd;
245 
246     int ret;
247 
248     fd = TrivalOpenQosCtrlNode();
249     if (fd < 0) {
250         return fd;
251     }
252 
253     data.level = level;
254     data.type = static_cast<unsigned int>(QosManipulateType::QOS_APPLY);
255     data.pid = tid;
256 
257     ret = ioctl(fd, QOS_CTRL_BASIC_OPERATION, &data);
258     if (ret < 0) {
259         CONCUR_LOGE("[Interface] task %{public}d apply qos failed, errno = %{public}d", tid, errno);
260     }
261     close(fd);
262     return ret;
263 }
264 
QosLeave(void)265 int QosLeave(void)
266 {
267     struct QosCtrlData data;
268     int fd;
269     int ret;
270 
271     fd = TrivalOpenQosCtrlNode();
272     if (fd < 0) {
273         return fd;
274     }
275 
276     data.type = static_cast<unsigned int>(QosManipulateType::QOS_LEAVE);
277     data.pid = gettid();
278 
279     ret = ioctl(fd, QOS_CTRL_BASIC_OPERATION, &data);
280     if (ret < 0) {
281         CONCUR_LOGE("[Interface] task %{public}d leave qos failed, errno = %{public}d", gettid(), errno);
282     }
283     close(fd);
284     return ret;
285 }
286 
QosLeaveForOther(int tid)287 int QosLeaveForOther(int tid)
288 {
289     struct QosCtrlData data;
290     int fd;
291     int ret;
292 
293     fd = TrivalOpenQosCtrlNode();
294     if (fd < 0) {
295         return fd;
296     }
297 
298     data.type = static_cast<unsigned int>(QosManipulateType::QOS_LEAVE);
299     data.pid = tid;
300 
301     ret = ioctl(fd, QOS_CTRL_BASIC_OPERATION, &data);
302     if (ret < 0) {
303         CONCUR_LOGE("[Interface] task %{public}d leave qos failed, errno = %{public}d", tid, errno);
304     }
305     close(fd);
306     return ret;
307 }
308 
QosPolicySet(const struct QosPolicyDatas *policyDatas)309 int QosPolicySet(const struct QosPolicyDatas *policyDatas)
310 {
311     int fd;
312     int ret;
313 
314     fd = TrivalOpenQosCtrlNode();
315     if (fd < 0) {
316         return fd;
317     }
318 
319     ret = ioctl(fd, QOS_CTRL_POLICY_OPERATION, policyDatas);
320     if (ret < 0) {
321         CONCUR_LOGE("[Interface] set qos policy failed, errno = %{public}d", errno);
322     }
323     close(fd);
324     return ret;
325 }
326 
QosGet(int &level)327 int QosGet(int &level)
328 {
329     int tid = gettid();
330     return QosGetForOther(tid, level);
331 }
332 
QosGetForOther(int tid, int &level)333 int QosGetForOther(int tid, int &level)
334 {
335     int fd;
336     int ret = 0;
337 
338     fd = TrivalOpenQosCtrlNode();
339     if (fd < 0) {
340         return fd;
341     }
342 
343     struct QosCtrlData data;
344     data.type = static_cast<unsigned int>(QosManipulateType::QOS_GET);
345     data.pid = tid;
346     data.qos = -1;
347 
348     ret = ioctl(fd, QOS_CTRL_BASIC_OPERATION, &data);
349     if (ret < 0) {
350         CONCUR_LOGE("[Interface] task %{public}d get qos failed, errno = %{public}d", tid, errno);
351     }
352     level = data.qos;
353 
354     close(fd);
355     return ret;
356 }