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 
16 #ifndef GNU_SOURCE
17 #define GNU_SOURCE
18 #endif
19 #include <cstring>
20 #include <cstdio>
21 #include <cstdlib>
22 #include <unistd.h>
23 #include <sys/ioctl.h>
24 #include <fcntl.h>
25 #include <unistd.h>
26 #include <sys/syscall.h>
27 #include "dfx/log/ffrt_log_api.h"
28 #include "eu/qos_interface.h"
29 
30 #ifndef OHOS_STANDARD_SYSTEM
31 #define GET_TID() 10086
32 #else
33 #define GET_TID() syscall(SYS_gettid)
34 #endif
35 
TrivalOpenRtgNode(void)36 static int TrivalOpenRtgNode(void)
37 {
38     char fileName[] = "/proc/self/sched_rtg_ctrl";
39     int fd = open(fileName, O_RDWR);
40     if (fd < 0) {
41         FFRT_LOGE("task %d belong to user %d open rtg node failed\n", getpid(), getuid());
42     }
43 
44     return fd;
45 }
46 
TrivalOpenAuthCtrlNode(void)47 static int TrivalOpenAuthCtrlNode(void)
48 {
49     char fileName[] = "/dev/auth_ctrl";
50     int fd = open(fileName, O_RDWR);
51     if (fd < 0) {
52         FFRT_LOGE("task %d belong to user %d open auth node failed\n", getpid(), getuid());
53     }
54 
55     return fd;
56 }
57 
TrivalOpenQosCtrlNode(void)58 static int TrivalOpenQosCtrlNode(void)
59 {
60     char fileName[] = "/proc/thread-self/sched_qos_ctrl";
61     int fd = open(fileName, O_RDWR);
62     if (fd < 0) {
63         FFRT_LOGW("pid %d belong to user %d open qos node warn, fd:%d, eno:%d, %s\n",
64             getpid(), getuid(), fd, errno, strerror(errno));
65     }
66 
67     return fd;
68 }
69 
FFRTEnableRtg(bool flag)70 int FFRTEnableRtg(bool flag)
71 {
72     struct RtgEnableData enableData;
73     char configStr[] = "load_freq_switch:1;sched_cycle:1";
74     int ret;
75 
76     enableData.enable = flag;
77     enableData.len = sizeof(configStr);
78     enableData.data = configStr;
79     int fd = TrivalOpenRtgNode();
80     if (fd < 0) {
81         return fd;
82     }
83 
84     ret = ioctl(fd, CMD_ID_SET_ENABLE, &enableData);
85     if (ret < 0) {
86         FFRT_LOGE("set rtg config enable failed.\n");
87     }
88 
89     close(fd);
90 
91     return 0;
92 };
93 
FFRTAuthEnable(unsigned int uid,unsigned int uaFlag,unsigned int status)94 int FFRTAuthEnable(unsigned int uid, unsigned int uaFlag, unsigned int status)
95 {
96     struct AuthCtrlData data;
97     int fd;
98     int ret;
99 
100     fd = TrivalOpenAuthCtrlNode();
101     if (fd < 0) {
102         return fd;
103     }
104 
105     data.uid = uid;
106     data.rtgUaFlag = uaFlag;
107     data.qosUaFlag = AF_QOS_ALL;
108     data.status = status;
109     data.type = AUTH_ENABLE;
110 
111     ret = ioctl(fd, BASIC_AUTH_CTRL_OPERATION, &data);
112     if (ret < 0) {
113         FFRT_LOGE("auth enable failed for uid %d with status %d\n", uid, status);
114     }
115     close(fd);
116     return ret;
117 }
118 
FFRTAuthSwitch(unsigned int uid,unsigned int rtgFlag,unsigned int qosFlag,unsigned int status)119 int FFRTAuthSwitch(unsigned int uid, unsigned int rtgFlag, unsigned int qosFlag, unsigned int status)
120 {
121     struct AuthCtrlData data;
122     int fd;
123     int ret;
124 
125     fd = TrivalOpenAuthCtrlNode();
126     if (fd < 0) {
127         return fd;
128     }
129 
130     data.uid = uid;
131     data.rtgUaFlag = rtgFlag;
132     data.qosUaFlag = qosFlag;
133     data.status = status;
134     data.type = AUTH_SWITCH;
135 
136     ret = ioctl(fd, BASIC_AUTH_CTRL_OPERATION, &data);
137     if (ret < 0) {
138         FFRT_LOGE("auth switch failed for uid %d with status %d\n", uid, status);
139     }
140     close(fd);
141     return ret;
142 }
143 
FFRTAuthDelete(unsigned int uid)144 int FFRTAuthDelete(unsigned int uid)
145 {
146     struct AuthCtrlData data;
147     int fd;
148     int ret;
149 
150     fd = TrivalOpenAuthCtrlNode();
151     if (fd < 0) {
152         return fd;
153     }
154 
155     data.uid = uid;
156     data.type = AUTH_DELETE;
157 
158     ret = ioctl(fd, BASIC_AUTH_CTRL_OPERATION, &data);
159     if (ret < 0) {
160         FFRT_LOGE("auth delete failed for uid %d\n", uid);
161     }
162     close(fd);
163     return ret;
164 }
165 
FFRTAuthPause(unsigned int uid)166 int FFRTAuthPause(unsigned int uid)
167 {
168     struct AuthCtrlData data;
169     int fd;
170     int ret;
171 
172     fd = TrivalOpenAuthCtrlNode();
173     if (fd < 0) {
174         return fd;
175     }
176 
177     data.uid = uid;
178     data.type = AUTH_SWITCH;
179     data.rtgUaFlag = 0;
180     data.qosUaFlag = AF_QOS_DELEGATED;
181     data.status = AUTH_STATUS_BACKGROUND;
182 
183     ret = ioctl(fd, BASIC_AUTH_CTRL_OPERATION, &data);
184     if (ret < 0) {
185         FFRT_LOGE("auth pause failed for uid %d\n", uid);
186     }
187     close(fd);
188     return ret;
189 }
190 
FFRTAuthGet(unsigned int uid,unsigned int * uaFlag,unsigned int * status)191 int FFRTAuthGet(unsigned int uid, unsigned int *uaFlag, unsigned int *status)
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.uid = uid;
203     data.type = AUTH_GET;
204 
205     ret = ioctl(fd, BASIC_AUTH_CTRL_OPERATION, &data);
206     if (ret < 0) {
207         FFRT_LOGE("auth get failed for uid %d\n", uid);
208     }
209     close(fd);
210 
211     *uaFlag = data.rtgUaFlag;
212     *status = data.status;
213 
214     return ret;
215 }
216 
FFRTQosApply(unsigned int level)217 int FFRTQosApply(unsigned int level)
218 {
219     int tid = GET_TID();
220     int ret;
221 
222     ret = FFRTQosApplyForOther(level, tid);
223     return ret;
224 }
225 
FFRTQosApplyForOther(unsigned int level,int tid)226 int FFRTQosApplyForOther(unsigned int level, int tid)
227 {
228     struct QosCtrlData data;
229     int fd;
230 
231     int ret;
232 
233     fd = TrivalOpenQosCtrlNode();
234     if (fd < 0) {
235         return fd;
236     }
237 
238     data.level = level;
239     data.type = QOS_APPLY;
240     data.pid = tid;
241 
242     ret = ioctl(fd, QOS_CTRL_BASIC_OPERATION, &data);
243     if (ret < 0) {
244         FFRT_LOGW("tid %d, %s, ret:%d, eno:%d\n", tid, strerror(errno), ret, errno);
245     }
246     close(fd);
247     return ret;
248 }
249 
FFRTQosLeave(void)250 int FFRTQosLeave(void)
251 {
252     struct QosCtrlData data;
253     int fd;
254     int ret;
255 
256     fd = TrivalOpenQosCtrlNode();
257     if (fd < 0) {
258         return fd;
259     }
260 
261     data.type = QOS_LEAVE;
262     data.pid = GET_TID();
263 
264     ret = ioctl(fd, QOS_CTRL_BASIC_OPERATION, &data);
265     if (ret < 0) {
266         FFRT_LOGE("qos leave failed for task %d\n", getpid());
267     }
268 
269     close(fd);
270     return ret;
271 }
272 
FFRTQosLeaveForOther(int tid)273 int FFRTQosLeaveForOther(int tid)
274 {
275     struct QosCtrlData data;
276     int fd;
277     int ret;
278 
279     fd = TrivalOpenQosCtrlNode();
280     if (fd < 0) {
281         return fd;
282     }
283 
284     data.type = QOS_LEAVE;
285     data.pid = tid;
286 
287     ret = ioctl(fd, QOS_CTRL_BASIC_OPERATION, &data);
288     if (ret < 0) {
289         FFRT_LOGE("qos leave failed for task %d\n", tid);
290     }
291     close(fd);
292     return ret;
293 }
294 
QosPolicy(struct QosPolicyDatas * policyDatas)295 int QosPolicy(struct QosPolicyDatas *policyDatas)
296 {
297     int fd;
298     int ret;
299 
300     fd = TrivalOpenQosCtrlNode();
301     if (fd < 0) {
302         return fd;
303     }
304 
305     ret = ioctl(fd, QOS_CTRL_POLICY_OPERATION, policyDatas);
306     if (ret < 0) {
307         FFRT_LOGE("set qos policy failed for task %d\n", getpid());
308     }
309 
310     close(fd);
311     return ret;
312 }
313 
FFRTThreadCtrl(int tid,struct ThreadAttrCtrl & ctrlDatas)314 int FFRTThreadCtrl(int tid, struct ThreadAttrCtrl &ctrlDatas)
315 {
316     int fd;
317     int ret;
318     fd = TrivalOpenQosCtrlNode();
319     if (fd < 0) {
320         return fd;
321     }
322     ctrlDatas.tid = tid;
323     ret = ioctl(fd, QOS_THREAD_CTRL_OPERATION, &ctrlDatas);
324     if (ret < 0) {
325         FFRT_LOGE("set thread ctrl data failed for task %d, this func is not enable in OHOS\n", getpid());
326     }
327 
328     close(fd);
329     return ret;
330 }
331 
FFRTQosGet(struct QosCtrlData & data)332 int FFRTQosGet(struct QosCtrlData &data)
333 {
334     int tid = GET_TID();
335     return FFRTQosGetForOther(tid, data);
336 }
337 
FFRTQosGetForOther(int tid,struct QosCtrlData & data)338 int FFRTQosGetForOther(int tid, struct QosCtrlData &data)
339 {
340     int fd = TrivalOpenQosCtrlNode();
341     if (fd < 0) {
342         return fd;
343     }
344 
345     data.type = QOS_GET;
346     data.pid = tid;
347     data.qos = -1;
348     data.staticQos = -1;
349     data.dynamicQos = -1;
350 
351     int ret = ioctl(fd, QOS_CTRL_BASIC_OPERATION, &data);
352     if (ret < 0) {
353         FFRT_LOGE("%s: qos get failed for thread %d, return %d", __func__, tid, ret);
354     }
355     close(fd);
356 
357     return ret;
358 }
359 
360 static Func_affinity funcAffinity = nullptr;
setFuncAffinity(Func_affinity func)361 void setFuncAffinity(Func_affinity func)
362 {
363     funcAffinity = func;
364 }
365 
getFuncAffinity(void)366 Func_affinity getFuncAffinity(void)
367 {
368     return funcAffinity;
369 }
370 
371 static Func_priority funcPriority = nullptr;
setFuncPriority(Func_priority func)372 void setFuncPriority(Func_priority func)
373 {
374     funcPriority = func;
375 }
376 
getFuncPriority(void)377 Func_priority getFuncPriority(void)
378 {
379     return funcPriority;
380 }