• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * SPDX-License-Identifier: GPL-2.0
4  *
5  * Unless required by applicable law or agreed to in writing, software
6  * distributed under the License is distributed on an "AS IS" BASIS,
7  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8  * See the License for the specific language governing permissions and
9  * limitations under the License.
10  */
11 
12 #include "rtg_test.h"
13 #include <cstdio>
14 #include <cstdlib>
15 #include <fcntl.h>
16 #include <cerrno>
17 #include <unistd.h>
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <sys/mman.h>
21 #include <sys/wait.h>
22 #include <sys/ioctl.h>
23 #include <ctime>
24 #include <climits>
25 #include <pthread.h>
26 #include <sys/syscall.h>
27 #include <securec.h>
28 #include <string>
29 #include <vector>
30 
31 using namespace testing::ext;
32 using namespace std;
33 
34 constexpr size_t MAX_LENGTH = 100;
35 const char RTG_SCHED_IPC_MAGIC = 0xAB;
36 const int RTG_ERR = -1;
37 const int RTG_SUCC = 0;
38 const int MAX_TID_NUM = 5;
39 const int MULTI_FRAME_NUM = 5;
40 
41 #define CMD_ID_SET_ENABLE \
42     _IOWR(RTG_SCHED_IPC_MAGIC, SET_ENABLE, struct RtgEnableData)
43 #define CMD_ID_SET_RTG \
44     _IOWR(RTG_SCHED_IPC_MAGIC, SET_RTG, struct RtgStrData)
45 #define CMD_ID_BEGIN_FRAME_FREQ \
46     _IOWR(RTG_SCHED_IPC_MAGIC, BEGIN_FRAME_FREQ, struct ProcStateData)
47 #define CMD_ID_END_FRAME_FREQ \
48     _IOWR(RTG_SCHED_IPC_MAGIC, END_FRAME_FREQ, struct ProcStateData)
49 #define CMD_ID_END_SCENE \
50     _IOWR(RTG_SCHED_IPC_MAGIC, END_SCENE, struct ProcStateData)
51 #define CMD_ID_SET_MIN_UTIL \
52     _IOWR(RTG_SCHED_IPC_MAGIC, SET_MIN_UTIL, struct ProcStateData)
53 #define CMD_ID_SET_MARGIN \
54     _IOWR(RTG_SCHED_IPC_MAGIC, SET_MARGIN, struct ProcStateData)
55 #define CMD_ID_SET_RTG_ATTR \
56     _IOWR(RTG_SCHED_IPC_MAGIC, SET_RTG_ATTR, struct RtgStrData)
57 #define CMD_ID_SET_CONFIG \
58     _IOWR(RTG_SCHED_IPC_MAGIC, SET_CONFIG, struct RtgStrData)
59 
60 struct RtgEnableData {
61     int enable;
62     int len;
63     char *data;
64 };
65 
66 struct RtgStrData {
67     int type;
68     int len;
69     char *data;
70 };
71 
72 struct ProcStateData {
73     int grpId;
74     int stateParam;
75 };
76 
77 enum GrpCtrlCmd {
78     CMD_CREATE_RTG_GRP,
79     CMD_ADD_RTG_THREAD,
80     CMD_REMOVE_RTG_THREAD,
81     CMD_CLEAR_RTG_GRP,
82     CMD_DESTROY_RTG_GRP
83 };
84 
85 struct RtgGrpData {
86     int rtgCmd;
87     int grpId;
88     int prioType;
89     int rtCnt;
90     int tidNum;
91     int tids[MAX_TID_NUM];
92 };
93 
94 struct RtgInfo {
95     int rtgNum;
96     int rtgs[MULTI_FRAME_NUM];
97 };
98 
99 enum RtgSchedCmdid {
100     SET_ENABLE = 1,
101     SET_RTG,
102     SET_CONFIG,
103     SET_RTG_ATTR,
104     BEGIN_FRAME_FREQ = 5,
105     END_FRAME_FREQ,
106     END_SCENE,
107     SET_MIN_UTIL,
108     SET_MARGIN,
109     LIST_RTG = 10,
110     LIST_RTG_THREAD,
111     SEARCH_RTG,
112     GET_ENABLE,
113     RTG_CTRL_MAX_NR,
114 };
115 
116 enum RtgType : int {
117     VIP = 0,
118     TOP_TASK_KEY,
119     NORMAL_TASK,
120     RTG_TYPE_MAX,
121 };
122 
BasicOpenRtgNode()123 static int BasicOpenRtgNode()
124 {
125     char fileName[] = "/proc/self/sched_rtg_ctrl";
126 
127     int fd = open(fileName, O_RDWR);
128     if (fd < 0) {
129         cout << "open node err." << endl;
130     }
131 
132     return fd;
133 }
134 
EnableRtg(bool flag)135 static int EnableRtg(bool flag)
136 {
137     struct RtgEnableData enableData;
138     char configStr[] = "load_freq_switch:1;sched_cycle:1";
139 
140     enableData.enable = flag;
141     enableData.len = sizeof(configStr);
142     enableData.data = configStr;
143     int fd = BasicOpenRtgNode();
144     if (fd < 0) {
145         return RTG_ERR;
146     }
147     if (ioctl(fd, CMD_ID_SET_ENABLE, &enableData)) {
148         close(fd);
149         return RTG_ERR;
150     }
151 
152     close(fd);
153     return 0;
154 }
155 
CreateNewRtgGrp(int prioType,int rtNum)156 static int CreateNewRtgGrp(int prioType, int rtNum)
157 {
158     struct RtgGrpData grpData;
159     int ret;
160     int fd = BasicOpenRtgNode();
161     if (fd < 0) {
162         return RTG_ERR;
163     }
164     (void)memset_s(&grpData, sizeof(struct RtgGrpData), 0, sizeof(struct RtgGrpData));
165     if ((prioType > 0) && (prioType < RTG_TYPE_MAX)) {
166         grpData.prioType = prioType;
167     }
168     if (rtNum > 0) {
169         grpData.rtCnt = rtNum;
170     }
171     grpData.rtgCmd = CMD_CREATE_RTG_GRP;
172     ret = ioctl(fd, CMD_ID_SET_RTG, &grpData);
173 
174     close(fd);
175     return ret;
176 }
177 
DestroyRtgGrp(int grpId)178 static int DestroyRtgGrp(int grpId)
179 {
180     struct RtgGrpData grpData;
181     int ret;
182     int fd = BasicOpenRtgNode();
183     if (fd < 0) {
184         return fd;
185     }
186     (void)memset_s(&grpData, sizeof(struct RtgGrpData), 0, sizeof(struct RtgGrpData));
187     grpData.rtgCmd = CMD_DESTROY_RTG_GRP;
188     grpData.grpId = grpId;
189     ret = ioctl(fd, CMD_ID_SET_RTG, &grpData);
190 
191     close(fd);
192     return ret;
193 }
194 
AddThreadToRtg(int tid,int grpId,int prioType)195 static int AddThreadToRtg(int tid, int grpId, int prioType)
196 {
197     struct RtgGrpData grpData;
198     int ret;
199     int fd = BasicOpenRtgNode();
200     if (fd < 0) {
201         return fd;
202     }
203     (void)memset_s(&grpData, sizeof(struct RtgGrpData), 0, sizeof(struct RtgGrpData));
204     grpData.tidNum = 1;
205     grpData.tids[0] = tid;
206     grpData.grpId = grpId;
207     grpData.rtgCmd = CMD_ADD_RTG_THREAD;
208     grpData.prioType = prioType;
209     ret = ioctl(fd, CMD_ID_SET_RTG, &grpData);
210 
211     close(fd);
212     return ret;
213 }
214 
BeginFrameFreq(int stateParam)215 static int BeginFrameFreq(int stateParam)
216 {
217     int ret = 0;
218     struct ProcStateData stateData;
219     stateData.stateParam = stateParam;
220     int fd = BasicOpenRtgNode();
221     if (fd < 0) {
222         return fd;
223     }
224     ret = ioctl(fd, CMD_ID_BEGIN_FRAME_FREQ, &stateData);
225 
226     close(fd);
227     return ret;
228 }
229 
EndFrameFreq(int stateParam)230 static int EndFrameFreq(int stateParam)
231 {
232     int ret = 0;
233     struct ProcStateData stateData;
234     stateData.stateParam = stateParam;
235     int fd = BasicOpenRtgNode();
236     if (fd < 0) {
237             return fd;
238         }
239     ret = ioctl(fd, CMD_ID_END_FRAME_FREQ, &stateData);
240 
241     close(fd);
242     return ret;
243 }
244 
EndScene(int grpId)245 static int EndScene(int grpId)
246 {
247     int ret = 0;
248     struct ProcStateData stateData;
249     stateData.grpId = grpId;
250 
251     int fd = BasicOpenRtgNode();
252     if (fd < 0) {
253         return fd;
254     }
255     ret = ioctl(fd, CMD_ID_END_SCENE, &stateData);
256 
257     close(fd);
258     return ret;
259 }
260 
SetStateParam(unsigned int cmd,int stateParam)261 static int SetStateParam(unsigned int cmd, int stateParam)
262 {
263     int ret = 0;
264     struct ProcStateData stateData;
265     stateData.stateParam = stateParam;
266 
267     int fd = BasicOpenRtgNode();
268     if (fd < 0) {
269         return fd;
270     }
271     ret = ioctl(fd, cmd, &stateData);
272 
273     close(fd);
274     return ret;
275 }
276 
SetFrameRateAndPrioType(int rtgId,int rate,int rtgType)277 static int SetFrameRateAndPrioType(int rtgId, int rate, int rtgType)
278 {
279     int ret = 0;
280     char formatData[MAX_LENGTH] = {};
281     (void)sprintf_s(formatData, sizeof(formatData), "rtgId:%d;rate:%d;type:%d", rtgId, rate, rtgType);
282     struct RtgStrData strData;
283     strData.len = strlen(formatData);
284     strData.data = formatData;
285 
286     int fd = BasicOpenRtgNode();
287     if (fd < 0) {
288         return fd;
289     }
290     ret = ioctl(fd, CMD_ID_SET_RTG_ATTR, &strData);
291 
292     close(fd);
293     return ret;
294 }
295 
AddThreadsToRtg(vector<int> tids,int grpId,int prioType)296 static int AddThreadsToRtg(vector<int> tids, int grpId, int prioType)
297 {
298     struct RtgGrpData grpData;
299     int ret;
300 
301     int fd = BasicOpenRtgNode();
302     if (fd < 0) {
303         return fd;
304     }
305     (void)memset_s(&grpData, sizeof(struct RtgGrpData), 0, sizeof(struct RtgGrpData));
306     int num = static_cast<int>(tids.size());
307     if (num > MAX_TID_NUM) {
308         return -1;
309     }
310     grpData.tidNum = num;
311     grpData.grpId = grpId;
312     grpData.rtgCmd = CMD_ADD_RTG_THREAD;
313     grpData.prioType = prioType;
314     for (int i = 0; i < num; i++) {
315         if (tids[i] < 0) {
316             return -1;
317         }
318         grpData.tids[i] = tids[i];
319     }
320     ret = ioctl(fd, CMD_ID_SET_RTG, &grpData);
321 
322     close(fd);
323     return ret;
324 }
325 
SetUp()326 void RtgTest::SetUp()
327 {
328     // must enable rtg before use the interface
329     int ret = EnableRtg(true);
330     ASSERT_EQ(RTG_SUCC, ret);
331 }
332 
TearDown()333 void RtgTest::TearDown()
334 {
335     // disable rtg after use the interface
336     int ret = EnableRtg(false);
337     ASSERT_EQ(RTG_SUCC, ret);
338 }
339 
SetUpTestCase()340 void RtgTest::SetUpTestCase() {}
341 
TearDownTestCase()342 void RtgTest::TearDownTestCase() {}
343 
344 /**
345  * @tc.name: setEnableSucc
346  * @tc.desc: Verify the enable rtg function.
347  * @tc.type: FUNC
348  */
349 HWTEST_F(RtgTest, setEnableSucc, Function | MediumTest | Level1)
350 {
351     int ret;
352 
353     // test set enable again
354     ret = EnableRtg(true);
355     ASSERT_EQ(RTG_SUCC, ret);
356 
357     // test set disable again
358     ret = EnableRtg(false);
359     ASSERT_EQ(RTG_SUCC, ret);
360 }
361 
362 /**
363  * @tc.name: createAndDestroyRtgSucc
364  * @tc.desc: Verify the create and destroy rtggrp function.
365  * @tc.type: FUNC
366  */
367 HWTEST_F(RtgTest, createAndDestroyRtgSucc, Function | MediumTest | Level1)
368 {
369     int ret;
370     int grpId;
371 
372     grpId = CreateNewRtgGrp(NORMAL_TASK, 0);
373     ASSERT_GT(grpId, 0);
374     ret = DestroyRtgGrp(grpId);
375     ASSERT_EQ(ret, 0);
376 }
377 
378 /**
379  * @tc.name: destoryErrorRtgGrp
380  * @tc.desc: Verify Destroy function with error param.
381  * @tc.type: FUNC
382  */
383 HWTEST_F(RtgTest, destoryErrorRtgGrp, Function | MediumTest | Level1)
384 {
385     int ret;
386     ret = DestroyRtgGrp(-1);
387     ASSERT_NE(RTG_SUCC, ret);
388 }
389 
390 /**
391  * @tc.name: addRtgGrpSucc
392  * @tc.desc: Verify add rtg function.
393  * @tc.type: FUNC
394  */
395 HWTEST_F(RtgTest, addRtgGrpSucc, Function | MediumTest | Level1)
396 {
397     int ret;
398     int grpId;
399     int pid = getpid();
400 
401     grpId = CreateNewRtgGrp(VIP, 0);
402     ASSERT_GT(grpId, 0);
403     ret = AddThreadToRtg(pid, grpId, VIP);
404     ASSERT_EQ(ret, 0);
405     ret = DestroyRtgGrp(grpId);
406     ASSERT_EQ(ret, 0);
407 }
408 
409 /**
410  * @tc.name: addRtgGrpFail
411  * @tc.desc: Verify add rtg function with error param.
412  * @tc.type: FUNC
413  */
414 HWTEST_F(RtgTest, addRtgGrpFail, Function | MediumTest | Level1)
415 {
416     int ret;
417     int grpId;
418     int pid = getpid();
419 
420     grpId = CreateNewRtgGrp(VIP, 0);
421     ASSERT_GT(grpId, 0);
422 
423     // error tid
424     ret = AddThreadToRtg(-1, grpId, VIP);
425     ASSERT_NE(ret, 0);
426 
427     // error grpid
428     ret = AddThreadToRtg(pid, -1, VIP);
429     ASSERT_NE(ret, RTG_SUCC);
430     ret = DestroyRtgGrp(grpId);
431     ASSERT_EQ(ret, 0);
432 }
433 
434 /**
435  * @tc.name: begainFrameFreqSucc
436  * @tc.desc: Verify rtg frame start function.
437  * @tc.type: FUNC
438  */
439 HWTEST_F(RtgTest, begainFrameFreqSucc, Function | MediumTest | Level1)
440 {
441     int ret;
442     int grpId;
443     int pid = getpid();
444     vector<int> pids = {};
445     pids.push_back(pid);
446     grpId = CreateNewRtgGrp(VIP, 0);
447     ASSERT_GT(grpId, 0);
448     ret = AddThreadsToRtg(pids, grpId, VIP);
449     ASSERT_EQ(ret, 0);
450     ret = BeginFrameFreq(0);
451     ASSERT_EQ(ret, 0);
452     ret = DestroyRtgGrp(grpId);
453     ASSERT_EQ(ret, 0);
454 }
455 
456 /**
457  * @tc.name: RtgInterfaceBeginFrameFreqWithNoAddThreadtoGrp
458  * @tc.desc: Verify rtg frame start function with NoAddThreadtoGrp.
459  * @tc.type: FUNC
460  */
461 HWTEST_F(RtgTest, RtgInterfaceBeginFrameFreqWithNoAddThreadtoGrp, Function | MediumTest | Level1)
462 {
463     int ret;
464     int grpId;
465     grpId = CreateNewRtgGrp(VIP, 0);
466     ASSERT_GT(grpId, 0);
467     ret = BeginFrameFreq(0);
468     ASSERT_NE(ret, 0);
469     ret = DestroyRtgGrp(grpId);
470     ASSERT_EQ(ret, 0);
471 }
472 
473 /**
474  * @tc.name: endFrameFreqSucc
475  * @tc.desc: Verify rtg frame end function.
476  * @tc.type: FUNC
477  */
478 HWTEST_F(RtgTest, endFrameFreqSucc, Function | MediumTest | Level1)
479 {
480     int ret;
481     int grpId;
482     int pid = getpid();
483     vector<int> pids = {};
484     pids.push_back(pid);
485     grpId = CreateNewRtgGrp(VIP, 0);
486     ASSERT_GT(grpId, 0);
487     ret = AddThreadsToRtg(pids, grpId, VIP);
488     ASSERT_EQ(ret, 0);
489     ret = EndFrameFreq(0);
490     ASSERT_EQ(ret, RTG_SUCC);
491     ret = DestroyRtgGrp(grpId);
492     ASSERT_EQ(ret, RTG_SUCC);
493 }
494 
495 /**
496  * @tc.name: endFrameFreqWithNoAddThreadtoGrp
497  * @tc.desc: Verify rtg frame end function with NoAddThreadtoGrp.
498  * @tc.type: FUNC
499  */
500 HWTEST_F(RtgTest, endFrameFreqWithNoAddThreadtoGrp, Function | MediumTest | Level1)
501 {
502     int ret;
503     int grpId;
504     grpId = CreateNewRtgGrp(VIP, 0);
505     ASSERT_GT(grpId, 0);
506     ret = EndFrameFreq(0);
507     ASSERT_NE(ret, RTG_SUCC);
508     ret = DestroyRtgGrp(grpId);
509     ASSERT_EQ(ret, RTG_SUCC);
510 }
511 
512 
513 /**
514  * @tc.name: endSceneSucc
515  * @tc.desc: Verify scene end function.
516  * @tc.type: FUNC
517  */
518 HWTEST_F(RtgTest, endSceneSucc, Function | MediumTest | Level1)
519 {
520     int ret;
521     int grpId;
522     int pid = getpid();
523     vector<int> pids = {};
524     pids.push_back(pid);
525     grpId = CreateNewRtgGrp(VIP, 0);
526     ASSERT_GT(grpId, 0);
527     ret = AddThreadsToRtg(pids, grpId, VIP);
528     ASSERT_EQ(ret, 0);
529     ret = EndScene(grpId);
530     ASSERT_EQ(ret, RTG_SUCC);
531     ret = DestroyRtgGrp(grpId);
532     ASSERT_EQ(ret, RTG_SUCC);
533 }
534 
535 /**
536  * @tc.name: endSceneFail
537  * @tc.desc: Verify scene end function.
538  * @tc.type: FUNC
539  */
540 HWTEST_F(RtgTest, endSceneFail, Function | MediumTest | Level1)
541 {
542     int ret;
543 
544     ret = EndScene(-1);
545     ASSERT_NE(ret, RTG_SUCC);
546 }
547 
548 /**
549  * @tc.name: setMinUtilSucc
550  * @tc.desc: Verify set min util function.
551  * @tc.type: FUNC
552  */
553 HWTEST_F(RtgTest, setMinUtilSucc, Function | MediumTest | Level1)
554 {
555     int ret;
556     int grpId;
557     int pid = getpid();
558     vector<int> pids = {};
559     pids.push_back(pid);
560     grpId = CreateNewRtgGrp(VIP, 0);
561     ASSERT_GT(grpId, 0);
562     ret = AddThreadsToRtg(pids, grpId, VIP);
563     ASSERT_EQ(ret, 0);
564     ret = SetStateParam(CMD_ID_SET_MIN_UTIL, 0);
565     ASSERT_EQ(ret, RTG_SUCC);
566     ret = DestroyRtgGrp(grpId);
567     ASSERT_EQ(ret, RTG_SUCC);
568 }
569 
570 /**
571  * @tc.name: setMinUtilWithNoAddThreadtoGrp
572  * @tc.desc: Verify set min util function with NoAddThreadtoGrp.
573  * @tc.type: FUNC
574  */
575 HWTEST_F(RtgTest, setMinUtilWithNoAddThreadtoGrp, Function | MediumTest | Level1)
576 {
577     int ret;
578     int grpId;
579     grpId = CreateNewRtgGrp(VIP, 0);
580     ASSERT_GT(grpId, 0);
581     ret = SetStateParam(CMD_ID_SET_MIN_UTIL, 0);
582     ASSERT_NE(ret, RTG_SUCC);
583     ret = DestroyRtgGrp(grpId);
584     ASSERT_EQ(ret, RTG_SUCC);
585 }
586 
587 /**
588  * @tc.name: setMarginSucc
589  * @tc.desc: Verify set min margin function.
590  * @tc.type: FUNC
591  */
592 HWTEST_F(RtgTest, setMarginSucc, Function | MediumTest | Level1)
593 {
594     int ret;
595     int grpId;
596     int pid = getpid();
597     vector<int> pids = {};
598     pids.push_back(pid);
599     grpId = CreateNewRtgGrp(VIP, 0);
600     ASSERT_GT(grpId, 0);
601     ret = AddThreadsToRtg(pids, grpId, VIP);
602     ASSERT_EQ(ret, 0);
603     ret = SetStateParam(CMD_ID_SET_MARGIN, 0);
604     ASSERT_EQ(ret, RTG_SUCC);
605     ret = DestroyRtgGrp(grpId);
606     ASSERT_EQ(ret, RTG_SUCC);
607 }
608 
609 /**
610  * @tc.name: setMarginWithNoAddThreadtoGrp
611  * @tc.desc: Verify set min margin function with NoAddThreadtoGrp.
612  * @tc.type: FUNC
613  */
614 HWTEST_F(RtgTest, setMarginWithNoAddThreadtoGrp, Function | MediumTest | Level1)
615 {
616     int ret;
617     int grpId;
618     grpId = CreateNewRtgGrp(VIP, 0);
619     ASSERT_GT(grpId, 0);
620     ret = SetStateParam(CMD_ID_SET_MARGIN, 0);
621     ASSERT_NE(ret, RTG_SUCC);
622     ret = DestroyRtgGrp(grpId);
623     ASSERT_EQ(ret, RTG_SUCC);
624 }
625 
626 /**
627  * @tc.name: SetRtgAttrSucc
628  * @tc.desc: Verify rtg attr set function.
629  * @tc.type: FUNC
630  */
631 HWTEST_F(RtgTest, SetRtgAttrSucc, Function | MediumTest | Level1)
632 {
633     int ret;
634     int grpId;
635 
636     grpId = CreateNewRtgGrp(VIP, 0);
637     ASSERT_GT(grpId, 0);
638     ret = SetFrameRateAndPrioType(grpId, 60, VIP);
639     ASSERT_EQ(ret, RTG_SUCC);
640     ret = DestroyRtgGrp(grpId);
641     ASSERT_EQ(ret, RTG_SUCC);
642 }
643 
644 /**
645  * @tc.name: SetRtgAttrFail
646  * @tc.desc: Verify rtg attr set function with error param.
647  * @tc.type: FUNC
648  */
649 HWTEST_F(RtgTest, SetRtgAttrFail, Function | MediumTest | Level1)
650 {
651     int ret;
652     int grpId;
653     grpId = CreateNewRtgGrp(VIP, 0);
654     ASSERT_GT(grpId, 0);
655     ret = SetFrameRateAndPrioType(grpId, 90, -1);
656     ASSERT_NE(ret, RTG_SUCC);
657     ret = DestroyRtgGrp(grpId);
658     ASSERT_EQ(ret, RTG_SUCC);
659 }
660 
661 /**
662  * @tc.name: RtgAddMutipleThreadsSucc
663  * @tc.desc: Verify rtg multiple add function.
664  * @tc.type: FUNC
665  */
666 HWTEST_F(RtgTest, RtgAddMutipleThreadsSucc, Function | MediumTest | Level1)
667 {
668     int ret;
669     int pid[3];
670     vector<int> threads;
671     int grpId;
672 
673     for (int i = 0; i < 3; i++) {
674         pid[i] = fork();
675         ASSERT_TRUE(pid[i] >= 0) << "> parent: fork errno = " << errno;
676         if (pid[i] == 0) {
677             usleep(50000);
678             _Exit(0);
679         }
680         threads.push_back(pid[i]);
681     }
682     grpId = CreateNewRtgGrp(NORMAL_TASK, 0);
683     ASSERT_GT(grpId, 0);
684     ret = AddThreadsToRtg(threads, grpId, NORMAL_TASK);
685     ASSERT_EQ(ret, RTG_SUCC);
686     ret = DestroyRtgGrp(grpId);
687     ASSERT_EQ(ret, RTG_SUCC);
688 }
689 
690 /**
691  * @tc.name: RtgAddMutipleThreadsOutOfLimit
692  * @tc.desc: Verify rtg multiple add function with out of limit threads.
693  * @tc.type: FUNC
694  */
695 HWTEST_F(RtgTest, RtgAddMutipleThreadsOutOfLimit, Function | MediumTest | Level1)
696 {
697     int ret;
698     int pid[8];
699     vector<int> threads;
700     int grpId;
701 
702     for (int i = 0; i < 8; i++) {
703         pid[i] = fork();
704         ASSERT_TRUE(pid[i] >= 0) << "> parent: fork errno = " << errno;
705         if (pid[i] == 0) {
706             usleep(50000);
707             _Exit(0);
708         }
709     threads.push_back(pid[i]);
710     }
711     grpId = CreateNewRtgGrp(NORMAL_TASK, 0);
712     ASSERT_GT(grpId, 0);
713     ret = AddThreadsToRtg(threads, grpId, NORMAL_TASK);
714     ASSERT_NE(ret, RTG_SUCC);
715     ret = DestroyRtgGrp(grpId);
716     ASSERT_EQ(ret, RTG_SUCC);
717 }
718