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