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 <unistd.h>
25 #include <concurrent_task_log.h>
26 
27 #include "qos_interface.h"
28 
TrivalOpenRtgNode(void)29 static int TrivalOpenRtgNode(void)
30 {
31     char fileName[] = "/proc/self/sched_rtg_ctrl";
32     int fd = open(fileName, O_RDWR);
33     if (fd < 0) {
34         CONCUR_LOGE("[Interface] task %{public}d belong to user %{public}d open rtg node failed, errno = %{public}d",
35             getpid(), getuid(), errno);
36     }
37     return fd;
38 }
39 
TrivalOpenAuthCtrlNode(void)40 static int TrivalOpenAuthCtrlNode(void)
41 {
42     char fileName[] = "/dev/auth_ctrl";
43     int fd = open(fileName, O_RDWR);
44     if (fd < 0) {
45         CONCUR_LOGE("[Interface] task %{public}d belong to user %{public}d open auth node failed, errno = %{public}d",
46             getpid(), getuid(), errno);
47     }
48     return fd;
49 }
50 
TrivalOpenQosCtrlNode(void)51 static int TrivalOpenQosCtrlNode(void)
52 {
53     char fileName[] = "/proc/thread-self/sched_qos_ctrl";
54     int fd = open(fileName, O_RDWR);
55     if (fd < 0) {
56         CONCUR_LOGE("[Interface] task %{public}d belong to user %{public}d open qos node failed, errno = %{public}d",
57             getpid(), getuid(), errno);
58     }
59     return fd;
60 }
61 
EnableRtg(bool flag)62 int EnableRtg(bool flag)
63 {
64     struct RtgEnableData enableData;
65     char configStr[] = "load_freq_switch:1;sched_cycle:1;frame_max_util:1024";
66     int ret;
67 
68     enableData.enable = flag;
69     enableData.len = sizeof(configStr);
70     enableData.data = configStr;
71     int fd = TrivalOpenRtgNode();
72     if (fd < 0) {
73         return fd;
74     }
75 
76     ret = ioctl(fd, CMD_ID_SET_ENABLE, &enableData);
77     if (ret < 0) {
78         printf("set rtg config enable failed.\n");
79     }
80 
81     close(fd);
82 
83     return 0;
84 };
85 
AuthEnable(unsigned int pid,unsigned int uaFlag,unsigned int status)86 int AuthEnable(unsigned int pid, unsigned int uaFlag, unsigned int status)
87 {
88     struct AuthCtrlData data;
89     int fd;
90     int ret;
91 
92     fd = TrivalOpenAuthCtrlNode();
93     if (fd < 0) {
94         return fd;
95     }
96 
97     data.pid = pid;
98     data.rtgUaFlag = uaFlag;
99     data.qosUaFlag = AF_QOS_DELEGATED;
100     data.status = status;
101     data.type = static_cast<unsigned int>(AuthManipulateType::AUTH_ENABLE);
102 
103     ret = ioctl(fd, BASIC_AUTH_CTRL_OPERATION, &data);
104 #ifdef QOS_DEBUG
105     if (ret < 0) {
106         printf("auth enable failed for pid %u with status %u\n", pid, status);
107     }
108 #endif
109     close(fd);
110     return ret;
111 }
112 
AuthSwitch(unsigned int pid,unsigned int rtgFlag,unsigned int qosFlag,unsigned int status)113 int AuthSwitch(unsigned int pid, unsigned int rtgFlag, unsigned int qosFlag, unsigned int status)
114 {
115     struct AuthCtrlData data;
116     int fd;
117     int ret;
118 
119     fd = TrivalOpenAuthCtrlNode();
120     if (fd < 0) {
121         return fd;
122     }
123 
124     data.pid = pid;
125     data.rtgUaFlag = rtgFlag;
126     data.qosUaFlag = qosFlag;
127     data.status = status;
128     data.type = static_cast<unsigned int>(AuthManipulateType::AUTH_SWITCH);
129 
130     ret = ioctl(fd, BASIC_AUTH_CTRL_OPERATION, &data);
131 #ifdef QOS_DEBUG
132     if (ret < 0) {
133         printf("auth switch failed for pid %u with status %u\n", pid, status);
134     }
135 #endif
136     close(fd);
137     return ret;
138 }
139 
AuthDelete(unsigned int pid)140 int AuthDelete(unsigned int pid)
141 {
142     struct AuthCtrlData data;
143     int fd;
144     int ret;
145 
146     fd = TrivalOpenAuthCtrlNode();
147     if (fd < 0) {
148         return fd;
149     }
150 
151     data.pid = pid;
152     data.type = static_cast<unsigned int>(AuthManipulateType::AUTH_DELETE);
153 
154     ret = ioctl(fd, BASIC_AUTH_CTRL_OPERATION, &data);
155 #ifdef QOS_DEBUG
156     if (ret < 0) {
157         printf("auth delete failed for pid %u\n", pid);
158     }
159 #endif
160     close(fd);
161     return ret;
162 }
163 
AuthPause(unsigned int pid)164 int AuthPause(unsigned int pid)
165 {
166     struct AuthCtrlData data;
167     int fd;
168     int ret;
169 
170     fd = TrivalOpenAuthCtrlNode();
171     if (fd < 0) {
172         return fd;
173     }
174 
175     data.pid = pid;
176     data.type = static_cast<unsigned int>(AuthManipulateType::AUTH_SWITCH);
177     data.rtgUaFlag = 0;
178     data.qosUaFlag = AF_QOS_DELEGATED;
179     data.status = static_cast<unsigned int>(AuthStatus::AUTH_STATUS_BACKGROUND);
180 
181     ret = ioctl(fd, BASIC_AUTH_CTRL_OPERATION, &data);
182 #ifdef QOS_DEBUG
183     if (ret < 0) {
184         printf("auth pause failed for pid %u\n", pid);
185     }
186 #endif
187     close(fd);
188     return ret;
189 }
190 
AuthGet(unsigned int pid)191 int AuthGet(unsigned int pid)
192 {
193     struct AuthCtrlData data;
194     int fd;
195     int ret;
196 
197     fd = TrivalOpenAuthCtrlNode();
198     if (fd < 0) {
199         return fd;
200     }
201 
202     data.pid = pid;
203     data.type = static_cast<unsigned int>(AuthManipulateType::AUTH_GET);
204 
205     ret = ioctl(fd, BASIC_AUTH_CTRL_OPERATION, &data);
206     if (ret < 0) {
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 }