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 <cstdio>
22 #include <string>
23 #include <vector>
24 #include <cerrno>
25 #include "bits/ioctl.h"
26 #include "rme_log_domain.h"
27
28 namespace OHOS {
29 namespace RME {
30 namespace {
31 constexpr size_t MAX_LENGTH = 100;
32 }
33 DEFINE_RMELOG_INTELLISENSE("rtg_interface");
34
35 const char RTG_SCHED_IPC_MAGIC = 0xAB;
36 static int g_fd = -1;
37
38 #define CMD_ID_SET_ENABLE \
39 _IOWR(RTG_SCHED_IPC_MAGIC, SET_ENABLE, struct rtg_enable_data)
40 #define CMD_ID_SET_RTG \
41 _IOWR(RTG_SCHED_IPC_MAGIC, SET_RTG, struct rtg_str_data)
42 #define CMD_ID_SET_CONFIG \
43 _IOWR(RTG_SCHED_IPC_MAGIC, SET_CONFIG, struct rtg_str_data)
44 #define CMD_ID_SET_RTG_ATTR \
45 _IOWR(RTG_SCHED_IPC_MAGIC, SET_RTG_ATTR, struct rtg_str_data)
46 #define CMD_ID_BEGIN_FRAME_FREQ \
47 _IOWR(RTG_SCHED_IPC_MAGIC, BEGIN_FRAME_FREQ, struct proc_state_data)
48 #define CMD_ID_END_FRAME_FREQ \
49 _IOWR(RTG_SCHED_IPC_MAGIC, END_FRAME_FREQ, struct proc_state_data)
50 #define CMD_ID_END_SCENE \
51 _IOWR(RTG_SCHED_IPC_MAGIC, END_SCENE, struct proc_state_data)
52 #define CMD_ID_SET_MIN_UTIL \
53 _IOWR(RTG_SCHED_IPC_MAGIC, SET_MIN_UTIL, struct proc_state_data)
54 #define CMD_ID_SET_MAX_UTIL \
55 _IOWR(RTG_SCHED_IPC_MAGIC, SET_MAX_UTIL, struct proc_state_data)
56 #define CMD_ID_SET_MARGIN \
57 _IOWR(RTG_SCHED_IPC_MAGIC, SET_MARGIN, struct proc_state_data)
58 #define CMD_ID_SEARCH_RTG \
59 _IOWR(RTG_SCHED_IPC_MAGIC, SEARCH_RTG, struct proc_state_data)
60 #define CMD_ID_GET_ENABLE \
61 _IOWR(RTG_SCHED_IPC_MAGIC, GET_ENABLE, struct rtg_enable_data)
62
BasicOpenRtgNode()63 __attribute__((constructor))void BasicOpenRtgNode()
64 {
65 char fileName[] = "/proc/self/sched_rtg_ctrl";
66 g_fd = open(fileName, O_RDWR);
67 if (g_fd < 0) {
68 RME_LOGI("rtg Open fail, errno = %{public}d(%{public}s), dev = %{public}s", errno, strerror(errno), fileName);
69 return;
70 }
71 RME_LOGI("rtg Open success");
72 return;
73 }
74
BasicCloseRtgNode()75 __attribute__((destructor))void BasicCloseRtgNode()
76 {
77 if (g_fd < 0) {
78 return;
79 }
80 RME_LOGI("rtg Close g_fd ret is %{public}d", g_fd);
81 close(g_fd);
82 g_fd = -1;
83 }
84
EnableRtg(bool flag)85 int EnableRtg(bool flag)
86 {
87 struct rtg_enable_data enableData;
88 char configStr[] = "load_freq_switch:1;sched_cycle:1";
89 enableData.enable = flag;
90 enableData.len = sizeof(configStr);
91 enableData.data = configStr;
92 if (g_fd < 0) {
93 return g_fd;
94 }
95 if (ioctl(g_fd, CMD_ID_SET_ENABLE, &enableData)) {
96 RME_LOGE("set rtg config enable failed, errno = %{public}d (%{public}s)", errno, strerror(errno));
97 } else {
98 RME_LOGI("set rtg config enable success.");
99 }
100 return 0;
101 };
102
AddThreadToRtg(int tid,int grpId,int prioType)103 int AddThreadToRtg(int tid, int grpId, int prioType)
104 {
105 if (g_fd < 0) {
106 return g_fd;
107 }
108 struct rtg_grp_data grp_data;
109 int ret;
110 (void)memset_s(&grp_data, sizeof(struct rtg_grp_data), 0, sizeof(struct rtg_grp_data));
111 grp_data.tid_num = 1;
112 grp_data.tids[0] = tid;
113 grp_data.grp_id = grpId;
114 grp_data.rtg_cmd = CMD_ADD_RTG_THREAD;
115 grp_data.prio_type = prioType;
116 ret = ioctl(g_fd, CMD_ID_SET_RTG, &grp_data);
117 return ret;
118 }
119
AddThreadsToRtg(vector<int> tids,int grpId,int prioType)120 int AddThreadsToRtg(vector<int> tids, int grpId, int prioType)
121 {
122 struct rtg_grp_data grp_data;
123 int ret;
124 if (g_fd < 0) {
125 return g_fd;
126 }
127 (void)memset_s(&grp_data, sizeof(struct rtg_grp_data), 0, sizeof(struct rtg_grp_data));
128 int num = static_cast<int>(tids.size());
129 if (num > MAX_TID_NUM) {
130 return -1;
131 }
132 grp_data.tid_num = num;
133 grp_data.grp_id = grpId;
134 grp_data.rtg_cmd = CMD_ADD_RTG_THREAD;
135 grp_data.prio_type = prioType;
136 for (int i = 0; i < num; i++) {
137 if (tids[i] < 0) {
138 return -1;
139 }
140 grp_data.tids[i] = tids[i];
141 }
142 ret = ioctl(g_fd, CMD_ID_SET_RTG, &grp_data);
143 if (!ret) {
144 RME_LOGI("add rtg grp success");
145 }
146 return ret;
147 };
148
RemoveRtgThread(int tid)149 int RemoveRtgThread(int tid)
150 {
151 if (g_fd < 0) {
152 return g_fd;
153 }
154 struct rtg_grp_data grp_data;
155 int ret;
156 (void)memset_s(&grp_data, sizeof(struct rtg_grp_data), 0, sizeof(struct rtg_grp_data));
157 grp_data.tid_num = 1;
158 grp_data.tids[0] = tid;
159 grp_data.rtg_cmd = CMD_REMOVE_RTG_THREAD;
160 ret = ioctl(g_fd, CMD_ID_SET_RTG, &grp_data);
161 if (ret < 0) {
162 RME_LOGE("remove grp failed, errno = %{public}d (%{public}s)", errno, strerror(errno));
163 } else {
164 RME_LOGI("remove grp success, get rtg id %{public}d.", ret);
165 }
166 return ret;
167 };
168
DestroyRtgGrp(int grpId)169 int DestroyRtgGrp(int grpId)
170 {
171 if (g_fd < 0) {
172 return g_fd;
173 }
174 struct rtg_grp_data grp_data;
175 int ret;
176 (void)memset_s(&grp_data, sizeof(struct rtg_grp_data), 0, sizeof(struct rtg_grp_data));
177 grp_data.rtg_cmd = CMD_DESTROY_RTG_GRP;
178 grp_data.grp_id = grpId;
179 ret = ioctl(g_fd, CMD_ID_SET_RTG, &grp_data);
180 if (ret < 0) {
181 RME_LOGE("destroy rtg grp failed, errno = %{public}d (%{public}s)", errno, strerror(errno));
182 } else {
183 RME_LOGI("destroy rtg grp success, get rtg id:%{public}d, ret:%{public}d.", grpId, ret);
184 }
185 return ret;
186 };
187
SetFrameRateAndPrioType(int rtgId,int rate,int rtgType)188 int SetFrameRateAndPrioType(int rtgId, int rate, int rtgType)
189 {
190 if (g_fd < 0) {
191 return g_fd;
192 }
193 int ret = 0;
194 char str_data[MAX_LENGTH] = {};
195 (void)sprintf_s(str_data, sizeof(str_data), "rtgId:%d;rate:%d;type:%d", rtgId, rate, rtgType);
196 struct rtg_str_data strData;
197 strData.len = strlen(str_data);
198 strData.data = str_data;
199
200 ret = ioctl(g_fd, CMD_ID_SET_RTG_ATTR, &strData);
201 if (ret < 0) {
202 RME_LOGE("set rtg attr failed, errno = %{public}d (%{public}s)", errno, strerror(errno));
203 } else {
204 RME_LOGI("set rtg attr success, get rtg id %{public}d.", ret);
205 }
206 return ret;
207 }
208
BeginFrameFreq(int stateParam)209 int BeginFrameFreq(int stateParam)
210 {
211 if (g_fd < 0) {
212 return g_fd;
213 }
214 int ret = 0;
215 struct proc_state_data state_data;
216 state_data.state_param = stateParam;
217
218 ret = ioctl(g_fd, CMD_ID_BEGIN_FRAME_FREQ, &state_data);
219 return ret;
220 }
221
EndFrameFreq(int stateParam)222 int EndFrameFreq(int stateParam)
223 {
224 if (g_fd < 0) {
225 return g_fd;
226 }
227 int ret = 0;
228 struct proc_state_data state_data;
229 state_data.state_param = stateParam;
230
231 ret = ioctl(g_fd, CMD_ID_END_FRAME_FREQ, &state_data);
232 return ret;
233 }
234
EndScene(int grpId)235 int EndScene(int grpId)
236 {
237 int ret = 0;
238 if (g_fd < 0) {
239 RME_LOGE("Open fail /proc/self/sched_rtg_ctrl");
240 return g_fd;
241 }
242 struct proc_state_data state_data;
243 state_data.grp_id = grpId;
244
245 ret = ioctl(g_fd, CMD_ID_END_SCENE, &state_data);
246 if (ret >= 0) {
247 RME_LOGI("set EndScene success, get ret %{public}d.", ret);
248 }
249 return ret;
250 }
251
SetMinUtil(int stateParam)252 int SetMinUtil(int stateParam)
253 {
254 int ret = 0;
255 struct proc_state_data state_data;
256 state_data.state_param = stateParam;
257
258 if (g_fd < 0) {
259 return g_fd;
260 }
261 ret = ioctl(g_fd, CMD_ID_SET_MIN_UTIL, &state_data);
262 if (ret < 0) {
263 RME_LOGE("set min util failed, errno = %{public}d (%{public}s)", errno, strerror(errno));
264 } else {
265 RME_LOGI("set min util success, get ret %{public}d.", ret);
266 }
267 return ret;
268 }
269
SetMaxUtil(int grpId,int stateParam)270 int SetMaxUtil(int grpId, int stateParam)
271 {
272 return 0;
273 }
274
SetMargin(int stateParam)275 int SetMargin(int stateParam)
276 {
277 int ret = 0;
278 struct proc_state_data state_data;
279 state_data.state_param = stateParam;
280
281 if (g_fd < 0) {
282 return g_fd;
283 }
284 ret = ioctl(g_fd, CMD_ID_SET_MARGIN, &state_data);
285 return ret;
286 }
287
SearchRtgForTid(int tid)288 int SearchRtgForTid(int tid)
289 {
290 if (g_fd < 0) {
291 return g_fd;
292 }
293 if (tid <= 0) {
294 RME_LOGI("Search tid err: invalid tid.");
295 return -1;
296 }
297 int ret = 0;
298 struct proc_state_data search_data;
299 (void)memset_s(&search_data, sizeof(struct proc_state_data), 0, sizeof(struct proc_state_data));
300 search_data.state_param = tid;
301 ret = ioctl(g_fd, CMD_ID_SEARCH_RTG, &search_data);
302 if (ret >= 0) {
303 RME_LOGD("Search tid %{public}d success with rtg_grp %{public}d", tid, ret);
304 }
305 return ret;
306 }
307
GetRtgEnable()308 int GetRtgEnable()
309 {
310 if (g_fd < 0) {
311 return g_fd;
312 }
313 struct rtg_enable_data enableData;
314 return ioctl(g_fd, CMD_ID_GET_ENABLE, &enableData);
315 }
316 } // namespace RME
317 } // namespace OHOS
318