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 #include "rtg_interface.h"
17 #include <sys/ioctl.h>
18 #include <fcntl.h>
19 #include <unistd.h>
20 #include <securec.h>
21 #include <cstdlib>
22 #include <cstdio>
23 #include <cerrno>
24 #include <string>
25 #include <iostream>
26 #include <linux/types.h>
27
28 #include "rme_log_domain.h"
29
30 namespace OHOS {
31 namespace RME {
32 namespace {
33 constexpr size_t MAX_LENGTH = 100;
34 constexpr size_t MAX_STR_LEN = 100;
35 constexpr int RTG_TYPE_MAX = 3;
36 }
37 DEFINE_RMELOG_INTELLISENSE("rtg_interface");
38
39 const char RTG_SCHED_IPC_MAGIC = 0xAB;
40
41 #define CMD_ID_SET_ENABLE \
42 _IOWR(RTG_SCHED_IPC_MAGIC, SET_ENABLE, struct rtg_enable_data)
43 #define CMD_ID_SET_RTG \
44 _IOWR(RTG_SCHED_IPC_MAGIC, SET_RTG, struct rtg_str_data)
45 #define CMD_ID_SET_CONFIG \
46 _IOWR(RTG_SCHED_IPC_MAGIC, SET_CONFIG, struct rtg_str_data)
47 #define CMD_ID_SET_RTG_ATTR \
48 _IOWR(RTG_SCHED_IPC_MAGIC, SET_RTG_ATTR, struct rtg_str_data)
49 #define CMD_ID_BEGIN_FRAME_FREQ \
50 _IOWR(RTG_SCHED_IPC_MAGIC, BEGIN_FRAME_FREQ, struct proc_state_data)
51 #define CMD_ID_END_FRAME_FREQ \
52 _IOWR(RTG_SCHED_IPC_MAGIC, END_FRAME_FREQ, struct proc_state_data)
53 #define CMD_ID_END_SCENE \
54 _IOWR(RTG_SCHED_IPC_MAGIC, END_SCENE, struct proc_state_data)
55 #define CMD_ID_SET_MIN_UTIL \
56 _IOWR(RTG_SCHED_IPC_MAGIC, SET_MIN_UTIL, struct proc_state_data)
57 #define CMD_ID_SET_MARGIN \
58 _IOWR(RTG_SCHED_IPC_MAGIC, SET_MARGIN, struct proc_state_data)
59 #define CMD_ID_LIST_RTG \
60 _IOWR(RTG_SCHED_IPC_MAGIC, LIST_RTG, struct rtg_info)
61 #define CMD_ID_LIST_RTG_THREAD \
62 _IOWR(RTG_SCHED_IPC_MAGIC, LIST_RTG_THREAD, struct rtg_grp_data)
63 #define CMD_ID_SEARCH_RTG \
64 _IOWR(RTG_SCHED_IPC_MAGIC, SEARCH_RTG, struct proc_state_data)
65 #define CMD_ID_GET_ENABLE \
66 _IOWR(RTG_SCHED_IPC_MAGIC, GET_ENABLE, struct rtg_enable_data)
67
BasicOpenRtgNode()68 int BasicOpenRtgNode()
69 {
70 char fileName[] = "/dev/sched_rtg_ctrl";
71 int fd = open(fileName, O_RDWR);
72 if (fd < 0) {
73 RME_LOGE("Open fail, errno = %{public}d(%{public}s), dev = %{public}s", errno, strerror(errno), fileName);
74 }
75 return fd;
76 }
77
EnableRtg(bool flag)78 int EnableRtg(bool flag)
79 {
80 struct rtg_enable_data enableData;
81 char configStr[] = "load_freq_switch:1;sched_cycle:1";
82
83 enableData.enable = flag;
84 enableData.len = sizeof(configStr);
85 enableData.data = configStr;
86 int fd = BasicOpenRtgNode();
87 if (fd < 0) {
88 return fd;
89 }
90 if (ioctl(fd, CMD_ID_SET_ENABLE, &enableData)) {
91 RME_LOGE("set rtg config enable failed, errno = %{public}d (%{public}s)", errno, strerror(errno));
92 } else {
93 RME_LOGI("set rtg config enable success.");
94 }
95 close(fd);
96 return 0;
97 };
98
CreateNewRtgGrp(int prioType,int rtNum)99 int CreateNewRtgGrp(int prioType, int rtNum)
100 {
101 struct rtg_grp_data grp_data;
102 int ret;
103 int fd = BasicOpenRtgNode();
104 if (fd < 0) {
105 return fd;
106 }
107 memset_s(&grp_data, sizeof(struct rtg_grp_data), 0, sizeof(struct rtg_grp_data));
108 if ((prioType > 0) && (prioType < RTG_TYPE_MAX)) {
109 grp_data.prio_type = prioType;
110 }
111 if (rtNum > 0) {
112 grp_data.rt_cnt = rtNum;
113 }
114 grp_data.rtg_cmd = CMD_CREATE_RTG_GRP;
115 ret = ioctl(fd, CMD_ID_SET_RTG, &grp_data);
116 if (ret < 0) {
117 RME_LOGE("create rtg grp failed, errno = %{public}d (%{public}s)", errno, strerror(errno));
118 } else {
119 RME_LOGI("create rtg grp success, get rtg id %{public}d.", ret);
120 }
121 close(fd);
122 return ret;
123 }
124
AddThreadToRtg(int tid,int grpId,int prioType)125 int AddThreadToRtg(int tid, int grpId, int prioType)
126 {
127 struct rtg_grp_data grp_data;
128 int ret;
129 int fd = BasicOpenRtgNode();
130 if (fd < 0) {
131 RME_LOGE("open node failed.");
132 return fd;
133 }
134 memset_s(&grp_data, sizeof(struct rtg_grp_data), 0, sizeof(struct rtg_grp_data));
135 grp_data.tid_num = 1;
136 grp_data.tids[0] = tid;
137 grp_data.grp_id = grpId;
138 grp_data.rtg_cmd = CMD_ADD_RTG_THREAD;
139 grp_data.prio_type = prioType;
140 ret = ioctl(fd, CMD_ID_SET_RTG, &grp_data);
141 close(fd);
142 return ret;
143 }
144
AddThreadsToRtg(vector<int> tids,int grpId,int prioType)145 int AddThreadsToRtg(vector<int> tids, int grpId, int prioType)
146 {
147 struct rtg_grp_data grp_data;
148 int ret;
149 int fd = BasicOpenRtgNode();
150 if (fd < 0) {
151 return fd;
152 }
153 memset_s(&grp_data, sizeof(struct rtg_grp_data), 0, sizeof(struct rtg_grp_data));
154 int num = tids.size();
155 if (num > MAX_TID_NUM) {
156 return -1;
157 }
158 grp_data.tid_num = num;
159 grp_data.grp_id = grpId;
160 grp_data.rtg_cmd = CMD_ADD_RTG_THREAD;
161 grp_data.prio_type = prioType;
162 for (int i = 0; i < num; i++) {
163 if (tids[i] < 0) {
164 return -1;
165 }
166 grp_data.tids[i] = tids[i];
167 }
168
169 ret = ioctl(fd, CMD_ID_SET_RTG, &grp_data);
170 if (ret < 0) {
171 RME_LOGE("add rtg grp failed, errno = %{public}d (%{public}s)", errno, strerror(errno));
172 } else if (ret == 0) {
173 RME_LOGI("add rtg grp success");
174 } else {
175 RME_LOGI("add rtg grp failed with %d threads", ret);
176 }
177 close(fd);
178 return ret;
179 };
180
RemoveRtgThread(int tid)181 int RemoveRtgThread(int tid)
182 {
183 struct rtg_grp_data grp_data;
184 int ret;
185 int fd = BasicOpenRtgNode();
186 if (fd < 0) {
187 return fd;
188 }
189 memset_s(&grp_data, sizeof(struct rtg_grp_data), 0, sizeof(struct rtg_grp_data));
190 grp_data.tid_num = 1;
191 grp_data.tids[0] = tid;
192 grp_data.rtg_cmd = CMD_REMOVE_RTG_THREAD;
193 ret = ioctl(fd, CMD_ID_SET_RTG, &grp_data);
194 if (ret < 0) {
195 RME_LOGE("remove grp failed, errno = %{public}d (%{public}s)", errno, strerror(errno));
196 } else {
197 RME_LOGI("remove grp success, get rtg id %{public}d.", ret);
198 }
199 close(fd);
200 return ret;
201 };
202
ClearRtgGrp(int GrpId)203 int ClearRtgGrp(int GrpId)
204 {
205 struct rtg_grp_data grp_data;
206 int ret;
207 int fd = BasicOpenRtgNode();
208 if (fd < 0) {
209 return fd;
210 }
211 memset_s(&grp_data, sizeof(struct rtg_grp_data), 0, sizeof(struct rtg_grp_data));
212 grp_data.rtg_cmd = CMD_CLEAR_RTG_GRP;
213 grp_data.grp_id = GrpId;
214 ret = ioctl(fd, CMD_ID_SET_RTG, &grp_data);
215 if (ret < 0) {
216 RME_LOGE("clear rtg grp failed, errno = %{public}d (%{public}s)", errno, strerror(errno));
217 } else {
218 RME_LOGI("clear rtg grp success, get rtg id %{public}d.", ret);
219 }
220 close(fd);
221 return ret;
222 };
223
DestroyRtgGrp(int GrpId)224 int DestroyRtgGrp(int GrpId)
225 {
226 struct rtg_grp_data grp_data;
227 int ret;
228 int fd = BasicOpenRtgNode();
229 if (fd < 0) {
230 return fd;
231 }
232 memset_s(&grp_data, sizeof(struct rtg_grp_data), 0, sizeof(struct rtg_grp_data));
233 grp_data.rtg_cmd = CMD_DESTROY_RTG_GRP;
234 grp_data.grp_id = GrpId;
235 ret = ioctl(fd, CMD_ID_SET_RTG, &grp_data);
236 if (ret < 0) {
237 RME_LOGE("destroy rtg grp failed, errno = %{public}d (%{public}s)", errno, strerror(errno));
238 } else {
239 RME_LOGI("destroy rtg grp success, get rtg id:%{public}d, ret:%{public}d.", GrpId, ret);
240 }
241 close(fd);
242 return ret;
243 };
244
245
SetMaxVipRtgs(int rtframe)246 int SetMaxVipRtgs(int rtframe)
247 {
248 int ret = 0;
249 char str_data[MAX_STR_LEN] = {};
250 (void)sprintf_s(str_data, sizeof(str_data), "rtframe:%d", rtframe);
251 struct rtg_str_data strData;
252 strData.len = strlen(str_data);
253 strData.data = str_data;
254
255 int fd = BasicOpenRtgNode();
256 if (fd < 0) {
257 return fd;
258 }
259 ret = ioctl(fd, CMD_ID_SET_CONFIG, &strData);
260 if (ret < 0) {
261 RME_LOGE("set single config failed, ret = %{public}d", ret);
262 } else {
263 RME_LOGI("set single config success, get rtg id %{public}d.", ret);
264 }
265 close(fd);
266 return ret;
267 }
268
SetFrameRateAndPrioType(int rtgId,int rate,int rtgType)269 int SetFrameRateAndPrioType(int rtgId, int rate, int rtgType)
270 {
271 int ret = 0;
272 char str_data[MAX_LENGTH] = {};
273 (void)sprintf_s(str_data, sizeof(str_data), "rtgId:%d;rate:%d;type:%d", rtgId, rate, rtgType);
274 struct rtg_str_data strData;
275 strData.len = strlen(str_data);
276 strData.data = str_data;
277
278 int fd = BasicOpenRtgNode();
279 if (fd < 0) {
280 return fd;
281 }
282 ret = ioctl(fd, CMD_ID_SET_RTG_ATTR, &strData);
283 if (ret < 0) {
284 RME_LOGE("set rtg attr failed, errno = %{public}d (%{public}s)", errno, strerror(errno));
285 } else {
286 RME_LOGI("set rtg attr success, get rtg id %{public}d.", ret);
287 }
288 close(fd);
289 return ret;
290 }
291
BeginFrameFreq(int grpId,int stateParam)292 int BeginFrameFreq(int grpId, int stateParam)
293 {
294 int ret = 0;
295 struct proc_state_data state_data;
296 state_data.grp_id = grpId;
297 state_data.state_param = stateParam;
298
299 int fd = BasicOpenRtgNode();
300 if (fd < 0) {
301 return fd;
302 }
303 ret = ioctl(fd, CMD_ID_BEGIN_FRAME_FREQ, &state_data);
304 close(fd);
305 return ret;
306 }
307
EndFrameFreq(int grpId)308 int EndFrameFreq(int grpId)
309 {
310 int ret = 0;
311 struct proc_state_data state_data;
312 state_data.grp_id = grpId;
313 state_data.state_param = 0;
314
315 int fd = BasicOpenRtgNode();
316 if (fd < 0) {
317 return fd;
318 }
319 ret = ioctl(fd, CMD_ID_END_FRAME_FREQ, &state_data);
320 close(fd);
321 return ret;
322 }
323
EndScene(int grpId)324 int EndScene(int grpId)
325 {
326 int ret = 0;
327 struct proc_state_data state_data;
328 state_data.grp_id = grpId;
329
330 int fd = BasicOpenRtgNode();
331 if (fd < 0) {
332 return fd;
333 }
334 ret = ioctl(fd, CMD_ID_END_SCENE, &state_data);
335 if (ret < 0) {
336 RME_LOGE("set EndScene failed, errno = %{public}d (%{public}s)", errno, strerror(errno));
337 } else {
338 RME_LOGI("set EndScene success, get ret %{public}d.", ret);
339 }
340 close(fd);
341
342 return ret;
343 }
344
SetMinUtil(int grpId,int stateParam)345 int SetMinUtil(int grpId, int stateParam)
346 {
347 int ret = 0;
348 struct proc_state_data state_data;
349 state_data.grp_id = grpId;
350 state_data.state_param = stateParam;
351
352 int fd = BasicOpenRtgNode();
353 if (fd < 0) {
354 return fd;
355 }
356 ret = ioctl(fd, CMD_ID_SET_MIN_UTIL, &state_data);
357 if (ret < 0) {
358 RME_LOGE("set min util failed, errno = %{public}d (%{public}s)", errno, strerror(errno));
359 } else {
360 RME_LOGI("set min util success, get ret %{public}d.", ret);
361 }
362 close(fd);
363 return ret;
364 }
365
SetMargin(int grpId,int stateParam)366 int SetMargin(int grpId, int stateParam)
367 {
368 int ret = 0;
369 struct proc_state_data state_data;
370 state_data.grp_id = grpId;
371 state_data.state_param = stateParam;
372
373 int fd = BasicOpenRtgNode();
374 if (fd < 0) {
375 return fd;
376 }
377 ret = ioctl(fd, CMD_ID_SET_MARGIN, &state_data);
378 close(fd);
379 return ret;
380 }
381
ListRtgGroup(vector<int> * rs)382 int ListRtgGroup(vector<int> *rs)
383 {
384 int ret = 0;
385 struct rtg_info rtg_info;
386 int fd = BasicOpenRtgNode();
387 if (fd < 0) {
388 return fd;
389 }
390 if (!rs) {
391 return -1;
392 }
393 memset_s(&rtg_info, sizeof(struct rtg_info), 0, sizeof(struct rtg_info));
394 ret = ioctl(fd, CMD_ID_LIST_RTG, &rtg_info);
395 if (ret < 0) {
396 RME_LOGE("list rtg group failed, errno = %{public}d (%{public}s)", errno, strerror(errno));
397 } else {
398 RME_LOGI("list rtg group success with num %{public}d", rtg_info.rtg_num);
399 rs->clear();
400 for (int i = 0; i < rtg_info.rtg_num; i++) {
401 rs->push_back(rtg_info.rtgs[i]);
402 }
403 }
404 close(fd);
405 return ret;
406 }
407
ListRtgThread(int grpId,vector<int> * rs)408 int ListRtgThread(int grpId, vector<int> *rs)
409 {
410 int ret = 0;
411 struct rtg_grp_data grp_data;
412 int fd = BasicOpenRtgNode();
413 if (fd < 0) {
414 return fd;
415 }
416 if (!rs) {
417 return -1;
418 }
419 memset_s(&grp_data, sizeof(struct rtg_grp_data), 0, sizeof(struct rtg_grp_data));
420 grp_data.grp_id = grpId;
421 ret = ioctl(fd, CMD_ID_LIST_RTG_THREAD, &grp_data);
422 if (ret < 0) {
423 RME_LOGE("list rtg thread failed, errno = %{public}d (%{public}s)", errno, strerror(errno));
424 } else {
425 RME_LOGI("list rtg thread success with tid num %{public}d", grp_data.tid_num);
426 rs->clear();
427 for (int i = 0; i < grp_data.tid_num; i++) {
428 rs->push_back(grp_data.tids[i]);
429 }
430 }
431 close(fd);
432 return ret;
433 }
434
SearchRtgForTid(int tid)435 int SearchRtgForTid(int tid)
436 {
437 int ret = 0;
438 struct proc_state_data search_data;
439 int fd = BasicOpenRtgNode();
440 if (fd < 0) {
441 return fd;
442 }
443 if (tid <= 0) {
444 RME_LOGI("Search tid err: invalid tid.");
445 return -1;
446 }
447 memset_s(&search_data, sizeof(struct proc_state_data), 0, sizeof(struct proc_state_data));
448 search_data.state_param = tid;
449 ret = ioctl(fd, CMD_ID_SEARCH_RTG, &search_data);
450 if (ret < 0) {
451 RME_LOGE("Search tid fail, errno = %{public}d (%{public}s)", errno, strerror(errno));
452 } else {
453 RME_LOGI("Search tid %{public}d success with rtg_grp %{public}d", tid, ret);
454 }
455 close(fd);
456 return ret;
457 }
458
GetRtgEnable()459 int GetRtgEnable()
460 {
461 struct rtg_enable_data enableData;
462 int fd = BasicOpenRtgNode();
463 if (fd < 0) {
464 return fd;
465 }
466 return ioctl(fd, CMD_ID_GET_ENABLE, &enableData);
467 }
468 } // namespace RME
469 } // namespace OHOS
470