thread_tc.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2021-09.01 yangjie the first version
  9. * 2021-10.11 mazhiyuan add idle, yield, suspend, control, priority, delay_until
  10. * 2025-11-12 Ze-Hou add standardized utest documentation block
  11. */
  12. /**
  13. * Test Case Name: Kernel Core Thread Test
  14. *
  15. * Test Objectives:
  16. * - Validate the core thread management features of the RT-Thread kernel:
  17. * 1. Thread creation methods (dynamic and static)
  18. * 2. Timing accuracy (resolution) of the rt_thread_delay API
  19. * 3. Use of the idle hook
  20. * 4. RT-Thread’s thread yield mechanism
  21. * 5. RT-Thread’s thread control interfaces
  22. * 6. Thread priorities
  23. * 7. Absolute delay functionality
  24. * 8. Time-slice scheduling among threads with the same priority
  25. *
  26. * Test Scenarios:
  27. * - Create, start, and delete a dynamic thread to verify dynamic thread lifecycle management
  28. * - Initialize, start, and detach a static thread to verify static thread lifecycle management
  29. * - Delay a thread for a specific tick count and check timing accuracy
  30. * - Register and remove an idle hook, verifying it is called as expected
  31. * - Use thread yield to test scheduler fairness among threads of the same priority
  32. * - Use thread control APIs to start, change priority, and close a thread, verifying each operation
  33. * - Create a thread with a specific priority and verify it runs as expected
  34. * - Use rt_thread_delay_until to test absolute delay and periodic task timing
  35. * - Create multiple threads with the same priority and test time-slice scheduling fairness
  36. *
  37. * Verification Metrics:
  38. * - Threads are created, started, deleted, and detached successfully
  39. * - The precision of both relative delay and absolute delay is correct.
  40. * - Idle hook is invoked as expected during thread idle periods
  41. * - Thread yield causes correct scheduling among threads of the same priority
  42. * - Thread control APIs (startup, change priority, close) work as intended and update thread state correctly
  43. * - Time-slice scheduling distributes CPU time fairly among threads of the same priority (difference < 30%)
  44. *
  45. * Dependencies:
  46. * - Enable Thread Test (RT-Thread Utestcases -> Kernel Core -> Thread Test)
  47. * - Test on any RT-Thread supported platform (e.g., qemu-virt64-riscv)
  48. *
  49. * Expected Results:
  50. * - After executing this test in msh, the expected output should be:
  51. * "[ PASSED ] [ result ] testcase (core.thread_tc)"
  52. */
  53. #define __RT_IPC_SOURCE__ /* include internal API for utest */
  54. #include <rtthread.h>
  55. #include <stdlib.h>
  56. #include "utest.h"
  57. #define THREAD_STACK_SIZE UTEST_THR_STACK_SIZE
  58. #define THREAD_TIMESLICE 10
  59. rt_align(RT_ALIGN_SIZE)
  60. static char thread2_stack[UTEST_THR_STACK_SIZE];
  61. static struct rt_thread thread2;
  62. #ifdef RT_USING_HEAP
  63. static rt_thread_t tid1 = RT_NULL;
  64. static rt_thread_t tid3 = RT_NULL;
  65. static rt_thread_t tid4 = RT_NULL;
  66. static rt_thread_t tid5 = RT_NULL;
  67. static rt_thread_t tid6 = RT_NULL;
  68. static rt_thread_t tid7 = RT_NULL;
  69. #endif /* RT_USING_HEAP */
  70. static volatile rt_uint32_t tid3_delay_pass_flag = 0;
  71. static volatile rt_uint32_t tid3_finish_flag = 0;
  72. static volatile rt_uint32_t tid4_finish_flag = 0;
  73. static volatile rt_uint32_t tid6_finish_flag = 0;
  74. static volatile rt_uint32_t thread5_source = 0;
  75. #ifndef RT_USING_SMP
  76. static volatile rt_uint32_t thread_yield_flag = 0;
  77. #endif
  78. static volatile rt_uint32_t entry_idle_hook_times = 0;
  79. static rt_thread_t __current_thread;
  80. static rt_uint8_t change_priority;
  81. static volatile rt_uint32_t count = 0;
  82. void thread1_entry(void *param)
  83. {
  84. while (1);
  85. }
  86. static void test_dynamic_thread(void)
  87. {
  88. rt_err_t ret_startup = -RT_ERROR;
  89. rt_err_t ret_delete = -RT_ERROR;
  90. tid1 = rt_thread_create("thread1",
  91. thread1_entry,
  92. (void *)1,
  93. THREAD_STACK_SIZE,
  94. UTEST_THR_PRIORITY + 1,
  95. THREAD_TIMESLICE - 5);
  96. if (tid1 == RT_NULL)
  97. {
  98. uassert_false(tid1 == RT_NULL);
  99. goto __exit;
  100. }
  101. ret_startup = rt_thread_startup(tid1);
  102. if (ret_startup != RT_EOK)
  103. {
  104. uassert_false(ret_startup != RT_EOK);
  105. goto __exit;
  106. }
  107. ret_delete = rt_thread_delete(tid1);
  108. if (ret_delete != RT_EOK)
  109. {
  110. uassert_false(ret_delete != RT_EOK);
  111. goto __exit;
  112. }
  113. uassert_true(tid1 != RT_NULL && ret_startup == RT_EOK && ret_delete == RT_EOK);
  114. __exit:
  115. if (tid1 != RT_NULL && ret_delete != RT_EOK)
  116. {
  117. rt_thread_delete(tid1);
  118. }
  119. return;
  120. }
  121. void thread2_entry(void *param)
  122. {
  123. while (1);
  124. }
  125. static void test_static_thread(void)
  126. {
  127. rt_err_t ret_init = -RT_ERROR;
  128. rt_err_t ret_startup = -RT_ERROR;
  129. rt_err_t ret_detach = -RT_ERROR;
  130. ret_init = rt_thread_init(&thread2,
  131. "thread2",
  132. thread2_entry,
  133. (void *)2,
  134. &thread2_stack[0],
  135. sizeof(thread2_stack),
  136. UTEST_THR_PRIORITY + 1,
  137. THREAD_TIMESLICE);
  138. if (ret_init != RT_EOK)
  139. {
  140. uassert_false(ret_init != RT_EOK);
  141. goto __exit;
  142. }
  143. ret_startup = rt_thread_startup(&thread2);
  144. if (ret_startup != RT_EOK)
  145. {
  146. uassert_false(ret_startup != RT_EOK);
  147. goto __exit;
  148. }
  149. ret_detach = rt_thread_detach(&thread2);
  150. if (ret_detach != RT_EOK)
  151. {
  152. uassert_false(ret_detach != RT_EOK);
  153. goto __exit;
  154. }
  155. uassert_true(ret_init == RT_EOK && ret_startup == RT_EOK && ret_detach == RT_EOK);
  156. __exit:
  157. if (ret_init == RT_EOK && ret_detach != RT_EOK)
  158. {
  159. rt_thread_detach(&thread2);
  160. }
  161. return;
  162. }
  163. static void thread3_entry(void *parameter)
  164. {
  165. rt_tick_t tick, latency_tick;
  166. tick = rt_tick_get();
  167. rt_thread_delay(15);
  168. latency_tick = rt_tick_get() - tick;
  169. if (latency_tick > 16 || latency_tick < 15)
  170. {
  171. tid3_finish_flag = 1;
  172. tid3_delay_pass_flag = 0;
  173. return;
  174. }
  175. tid3_delay_pass_flag = 1;
  176. tid3_finish_flag = 1;
  177. }
  178. static void test_thread_delay(void)
  179. {
  180. rt_err_t ret_startup = -RT_ERROR;
  181. tid3 = rt_thread_create("thread3",
  182. thread3_entry,
  183. RT_NULL,
  184. THREAD_STACK_SIZE,
  185. UTEST_THR_PRIORITY - 1,
  186. THREAD_TIMESLICE);
  187. if (tid3 == RT_NULL)
  188. {
  189. LOG_E("rt_thread_create failed!");
  190. uassert_false(tid3 == RT_NULL);
  191. goto __exit;
  192. }
  193. ret_startup = rt_thread_startup(tid3);
  194. if (ret_startup != RT_EOK)
  195. {
  196. LOG_E("rt_thread_startup failed!");
  197. uassert_false(1);
  198. goto __exit;
  199. }
  200. while (tid3_finish_flag != 1);
  201. uassert_true(tid3_delay_pass_flag == 1);
  202. __exit:
  203. return;
  204. }
  205. static void idle_hook(void)
  206. {
  207. entry_idle_hook_times ++;
  208. }
  209. static void thread4_entry(void *parameter)
  210. {
  211. rt_uint32_t delay_times = 5;
  212. while (delay_times --)
  213. {
  214. rt_thread_mdelay(300);
  215. }
  216. rt_thread_idle_delhook(idle_hook);
  217. tid4_finish_flag = 1;
  218. }
  219. static void test_idle_hook(void)
  220. {
  221. rt_err_t ret_startup = -RT_ERROR;
  222. rt_thread_idle_sethook(idle_hook);
  223. tid4 = rt_thread_create("thread4",
  224. thread4_entry,
  225. RT_NULL,
  226. THREAD_STACK_SIZE,
  227. UTEST_THR_PRIORITY - 1,
  228. THREAD_TIMESLICE);
  229. if (tid4 == RT_NULL)
  230. {
  231. LOG_E("rt_thread_create failed!");
  232. uassert_false(tid4 == RT_NULL);
  233. goto __exit;
  234. }
  235. ret_startup = rt_thread_startup(tid4);
  236. if (ret_startup != RT_EOK)
  237. {
  238. LOG_E("rt_thread_startup failed!");
  239. uassert_false(1);
  240. goto __exit;
  241. }
  242. while (tid4_finish_flag != 1)
  243. {
  244. rt_thread_mdelay(200);
  245. }
  246. uassert_true(entry_idle_hook_times > 0);
  247. __exit:
  248. return;
  249. }
  250. static void thread5_entry(void *parameter)
  251. {
  252. while (1)
  253. {
  254. thread5_source ++;
  255. rt_thread_delay(5);
  256. if (thread5_source == 5)
  257. {
  258. rt_thread_yield();
  259. }
  260. }
  261. }
  262. static void thread6_entry(void *parameter)
  263. {
  264. while (++ thread5_source <= 9);
  265. tid6_finish_flag = 1;
  266. }
  267. static void test_thread_yield(void)
  268. {
  269. rt_err_t ret_startup = -RT_ERROR;
  270. thread5_source = 0;
  271. tid5 = rt_thread_create("thread5",
  272. thread5_entry,
  273. RT_NULL,
  274. THREAD_STACK_SIZE,
  275. UTEST_THR_PRIORITY - 1,
  276. THREAD_TIMESLICE);
  277. if (tid5 == RT_NULL)
  278. {
  279. LOG_E("rt_thread_create failed!");
  280. uassert_false(tid5 == RT_NULL);
  281. goto __exit;
  282. }
  283. ret_startup = rt_thread_startup(tid5);
  284. if (ret_startup != RT_EOK)
  285. {
  286. LOG_E("rt_thread_startup failed!");
  287. uassert_false(1);
  288. goto __exit;
  289. }
  290. tid6 = rt_thread_create("thread6",
  291. thread6_entry,
  292. RT_NULL,
  293. THREAD_STACK_SIZE,
  294. UTEST_THR_PRIORITY - 1,
  295. THREAD_TIMESLICE);
  296. if (tid6 == RT_NULL)
  297. {
  298. LOG_E("rt_thread_create failed!");
  299. uassert_false(tid6 == RT_NULL);
  300. goto __exit;
  301. }
  302. ret_startup = rt_thread_startup(tid6);
  303. if (ret_startup != RT_EOK)
  304. {
  305. LOG_E("rt_thread_startup failed!");
  306. uassert_false(1);
  307. goto __exit;
  308. }
  309. while (tid6_finish_flag != 1);
  310. uassert_true(thread5_source == 10);
  311. __exit:
  312. if (tid5 != RT_NULL)
  313. {
  314. rt_thread_delete(tid5);
  315. }
  316. return;
  317. }
  318. static void thread7_entry(void *parameter)
  319. {
  320. while (1);
  321. }
  322. static void test_thread_control(void)
  323. {
  324. rt_err_t ret_control = -RT_ERROR;
  325. rt_err_t rst_delete = -RT_ERROR;
  326. rt_sched_lock_level_t slvl;
  327. tid7 = rt_thread_create("thread7",
  328. thread7_entry,
  329. RT_NULL,
  330. THREAD_STACK_SIZE,
  331. UTEST_THR_PRIORITY + 1,
  332. THREAD_TIMESLICE);
  333. if (tid7 == RT_NULL)
  334. {
  335. LOG_E("rt_thread_create failed!");
  336. uassert_false(tid7 == RT_NULL);
  337. goto __exit;
  338. }
  339. ret_control = rt_thread_control(tid7, RT_THREAD_CTRL_STARTUP, RT_NULL);
  340. if (ret_control != RT_EOK)
  341. {
  342. LOG_E("rt_thread_control failed!");
  343. uassert_false(1);
  344. goto __exit;
  345. }
  346. rt_thread_mdelay(200);
  347. rt_thread_control(tid7, RT_THREAD_CTRL_CHANGE_PRIORITY, &change_priority);
  348. rt_sched_lock(&slvl);
  349. if (rt_sched_thread_get_curr_prio(tid7) != change_priority)
  350. {
  351. LOG_E("rt_thread_control failed!");
  352. uassert_false(1);
  353. rt_sched_unlock(slvl);
  354. goto __exit;
  355. }
  356. rt_sched_unlock(slvl);
  357. rst_delete = rt_thread_control(tid7, RT_THREAD_CTRL_CLOSE, RT_NULL);
  358. if (rst_delete != RT_EOK)
  359. {
  360. LOG_E("rt_thread_control failed!");
  361. uassert_false(rst_delete != RT_EOK);
  362. goto __exit;
  363. }
  364. uassert_true(1);
  365. __exit:
  366. if (tid7 != RT_NULL && rst_delete != RT_EOK)
  367. {
  368. rt_thread_delete(tid7);
  369. }
  370. return;
  371. }
  372. static void thread8_entry(void *parameter)
  373. {
  374. for (; count < 10; count ++);
  375. }
  376. static void test_thread_priority(void)
  377. {
  378. rt_err_t ret_startup = -RT_ERROR;
  379. rt_thread_t tid8 = RT_NULL;
  380. tid8 = rt_thread_create("thread8",
  381. thread8_entry,
  382. RT_NULL,
  383. THREAD_STACK_SIZE,
  384. UTEST_THR_PRIORITY - 1,
  385. THREAD_TIMESLICE);
  386. if (tid8 == RT_NULL)
  387. {
  388. LOG_E("rt_thread_create failed!");
  389. uassert_false(tid8 == RT_NULL);
  390. return;
  391. }
  392. count = 0;
  393. ret_startup = rt_thread_startup(tid8);
  394. if (ret_startup != RT_EOK)
  395. {
  396. uassert_false(ret_startup != RT_EOK);
  397. return ;
  398. }
  399. uassert_true(count == 10);
  400. return;
  401. }
  402. static void test_delay_until(void)
  403. {
  404. rt_tick_t tick;
  405. rt_tick_t check_tick = 0;
  406. rt_tick_t delta = 0;
  407. tick = rt_tick_get();
  408. check_tick = tick;
  409. rt_thread_delay_until(&tick, 100);
  410. delta = rt_tick_get() - check_tick;
  411. rt_kprintf("delta[100] -> %d\n", delta);
  412. uassert_int_equal(delta, 100);
  413. check_tick = tick;
  414. rt_thread_delay(2);
  415. rt_thread_delay_until(&tick, 200);
  416. delta = rt_tick_get() - check_tick;
  417. rt_kprintf("delta[200] -> %d\n", delta);
  418. uassert_int_equal(delta, 200);
  419. check_tick = tick;
  420. rt_thread_delay(2);
  421. rt_thread_delay_until(&tick, 300);
  422. delta = rt_tick_get() - check_tick;
  423. rt_kprintf("delta[300] -> %d\n", delta);
  424. uassert_int_equal(delta, 300);
  425. check_tick = tick;
  426. rt_thread_delay(2);
  427. rt_thread_delay_until(&tick, 100);
  428. delta = rt_tick_get() - check_tick;
  429. uassert_int_equal(delta, 100);
  430. check_tick = tick;
  431. rt_thread_delay(2);
  432. rt_thread_delay_until(&tick, 50);
  433. delta = rt_tick_get() - check_tick;
  434. rt_kprintf("delta[50] -> %d\n", delta);
  435. uassert_int_equal(delta, 50);
  436. check_tick = tick;
  437. rt_thread_delay(2);
  438. rt_thread_delay_until(&tick, 20);
  439. delta = rt_tick_get() - check_tick;
  440. rt_kprintf("delta[20] -> %d\n", delta);
  441. uassert_int_equal(delta, 20);
  442. /**
  443. * the rt_kprints above can take few ticks to complete, maybe more than 10
  444. */
  445. tick = rt_tick_get();
  446. check_tick = tick;
  447. rt_thread_delay(2);
  448. rt_thread_delay_until(&tick, 10);
  449. delta = rt_tick_get() - check_tick;
  450. rt_kprintf("delta[10] -> %d\n", delta);
  451. uassert_int_equal(delta, 10);
  452. }
  453. static rt_thread_t tidA, tidB1, tidB2;
  454. static uint32_t timeslice_cntA, timeslice_cntB1, timeslice_cntB2;
  455. static void test_timeslice_threadA_entry(void *parameter)
  456. {
  457. while (1)
  458. {
  459. rt_thread_delay(2);
  460. timeslice_cntA++;
  461. if (timeslice_cntA > 10) return;
  462. }
  463. }
  464. static void test_timeslice_threadB1_entry(void *parameter)
  465. {
  466. while (1)
  467. {
  468. timeslice_cntB1++;
  469. if (timeslice_cntA > 10) return;
  470. }
  471. }
  472. static void test_timeslice_threadB2_entry(void *parameter)
  473. {
  474. while (1)
  475. {
  476. timeslice_cntB2++;
  477. if (timeslice_cntA > 10) return;
  478. }
  479. }
  480. void test_timeslice(void)
  481. {
  482. rt_err_t ret_startup = -RT_ERROR;
  483. uint32_t diff;
  484. timeslice_cntA = 0;
  485. timeslice_cntB1 = 0;
  486. timeslice_cntB2 = 0;
  487. tidA = rt_thread_create("timeslice", test_timeslice_threadA_entry, RT_NULL,
  488. 2048, UTEST_THR_PRIORITY + 1, 10);
  489. if (!tidA)
  490. {
  491. LOG_E("rt_thread_create failed!");
  492. return;
  493. }
  494. rt_thread_control(tidA, RT_THREAD_CTRL_BIND_CPU, (void *)1);
  495. ret_startup = rt_thread_startup(tidA);
  496. if (ret_startup != RT_EOK)
  497. {
  498. LOG_E("rt_thread_startup failed!");
  499. uassert_false(1);
  500. return ;
  501. }
  502. tidB1 = rt_thread_create("timeslice", test_timeslice_threadB1_entry, RT_NULL,
  503. 2048, UTEST_THR_PRIORITY + 2, 2);
  504. if (!tidB1)
  505. {
  506. LOG_E("rt_thread_create failed!");
  507. return;
  508. }
  509. rt_thread_control(tidB1, RT_THREAD_CTRL_BIND_CPU, (void *)1);
  510. ret_startup = rt_thread_startup(tidB1);
  511. if (ret_startup != RT_EOK)
  512. {
  513. LOG_E("rt_thread_startup failed!");
  514. uassert_false(1);
  515. return ;
  516. }
  517. tidB2 = rt_thread_create("timeslice", test_timeslice_threadB2_entry, RT_NULL,
  518. 2048, UTEST_THR_PRIORITY + 2, 2);
  519. if (!tidB2)
  520. {
  521. LOG_E("rt_thread_create failed!");
  522. return;
  523. }
  524. rt_thread_control(tidB2, RT_THREAD_CTRL_BIND_CPU, (void *)1);
  525. ret_startup = rt_thread_startup(tidB2);
  526. if (ret_startup != RT_EOK)
  527. {
  528. LOG_E("rt_thread_startup failed!");
  529. uassert_false(1);
  530. return ;
  531. }
  532. do{
  533. rt_thread_delay(2 * 20);
  534. }while(timeslice_cntA <= 10);
  535. rt_kprintf("A:%d,B1:%d,B2:%d\n", timeslice_cntA, timeslice_cntB1, timeslice_cntB2);
  536. diff = abs(timeslice_cntB1 - timeslice_cntB2);
  537. uassert_true(diff * 100 / timeslice_cntB1 < 30);
  538. uassert_true(timeslice_cntA == 11);
  539. }
  540. #ifndef RT_USING_SMP
  541. static volatile rt_uint32_t yield_count;
  542. static void test_thread_yield_inc_entry(void *parameter)
  543. {
  544. rt_uint32_t loop = 0;
  545. while (1)
  546. {
  547. if (loop++ > 10001)
  548. break;
  549. yield_count++;
  550. rt_thread_yield();
  551. }
  552. }
  553. static void test_thread_yield_entry(void *parameter)
  554. {
  555. rt_err_t ret_startup = -RT_ERROR;
  556. rt_thread_t tid;
  557. rt_uint32_t loop = 0;
  558. rt_uint32_t count_before;
  559. tid = rt_thread_create("inc", test_thread_yield_inc_entry, RT_NULL,
  560. 2048, 1, 10);
  561. if (!tid)
  562. {
  563. LOG_E("rt_thread_create failed!");
  564. return;
  565. }
  566. ret_startup = rt_thread_startup(tid);
  567. if (ret_startup != RT_EOK)
  568. {
  569. LOG_E("rt_thread_startup failed!");
  570. uassert_false(1);
  571. return ;
  572. }
  573. while (1)
  574. {
  575. if (loop++ > 10000)
  576. break;
  577. count_before = yield_count;
  578. rt_thread_yield();
  579. if (yield_count == count_before)
  580. {
  581. LOG_E("yield error!");
  582. return;
  583. }
  584. }
  585. thread_yield_flag = 1;
  586. }
  587. void test_thread_yield_nosmp(void)
  588. {
  589. rt_err_t ret_startup = -RT_ERROR;
  590. rt_thread_t tid;
  591. yield_count = 0;
  592. tid = rt_thread_create("chkcnt", test_thread_yield_entry, RT_NULL,
  593. 2048, 1, 10);
  594. if (!tid)
  595. {
  596. LOG_E("rt_thread_create failed!");
  597. return;
  598. }
  599. ret_startup = rt_thread_startup(tid);
  600. if (ret_startup != RT_EOK)
  601. {
  602. LOG_E("rt_thread_startup failed!");
  603. uassert_false(1);
  604. return ;
  605. }
  606. uassert_true(thread_yield_flag == 1);
  607. }
  608. // static rt_uint32_t thread9_count = 0;
  609. // static void thread9_entry(void *parameter)
  610. // {
  611. // while (1)
  612. // {
  613. // thread9_count ++;
  614. // }
  615. // }
  616. // static void test_thread_suspend(void)
  617. // {
  618. // static rt_thread_t tid;
  619. // rt_err_t ret_startup = -RT_ERROR;
  620. // uint32_t count_before_suspend, count_before_resume, count_after_resume;
  621. // tid = rt_thread_create("thread9",
  622. // thread9_entry,
  623. // RT_NULL,
  624. // THREAD_STACK_SIZE,
  625. // UTEST_THR_PRIORITY + 1,
  626. // THREAD_TIMESLICE);
  627. // if (tid == RT_NULL)
  628. // {
  629. // LOG_E("rt_thread_create failed!");
  630. // uassert_false(tid4 == RT_NULL);
  631. // goto __exit;
  632. // }
  633. // ret_startup = rt_thread_startup(tid);
  634. // if (ret_startup != RT_EOK)
  635. // {
  636. // LOG_E("rt_thread_startup failed!");
  637. // uassert_false(1);
  638. // goto __exit;
  639. // }
  640. // rt_thread_delay(5);
  641. // rt_thread_suspend(tid);
  642. // count_before_suspend = thread9_count;
  643. // uassert_true(count_before_suspend != 0);
  644. // rt_thread_delay(5);
  645. // count_before_resume = thread9_count;
  646. // uassert_true(count_before_suspend == count_before_resume);
  647. // rt_thread_resume(tid);
  648. // rt_thread_delay(5);
  649. // count_after_resume = thread9_count;
  650. // uassert_true(count_after_resume != count_before_resume);
  651. // __exit:
  652. // if (tid != RT_NULL)
  653. // {
  654. // rt_thread_delete(tid);
  655. // }
  656. // return;
  657. // }
  658. #endif
  659. static rt_err_t utest_tc_init(void)
  660. {
  661. __current_thread = rt_thread_self();
  662. change_priority = UTEST_THR_PRIORITY + 5;
  663. tid3_delay_pass_flag = 0;
  664. tid3_finish_flag = 0;
  665. tid4_finish_flag = 0;
  666. tid6_finish_flag = 0;
  667. entry_idle_hook_times = 0;
  668. count = 0;
  669. return RT_EOK;
  670. }
  671. static rt_err_t utest_tc_cleanup(void)
  672. {
  673. return RT_EOK;
  674. }
  675. static void testcase(void)
  676. {
  677. /* init, detach */
  678. UTEST_UNIT_RUN(test_static_thread);
  679. /* create, delete */
  680. UTEST_UNIT_RUN(test_dynamic_thread);
  681. /* delay */
  682. UTEST_UNIT_RUN(test_thread_delay);
  683. /* idle_sethook, idle_delhook */
  684. UTEST_UNIT_RUN(test_idle_hook);
  685. /* yield */
  686. UTEST_UNIT_RUN(test_thread_yield);
  687. #ifndef RT_USING_SMP
  688. /* yield_nosmp */
  689. UTEST_UNIT_RUN(test_thread_yield_nosmp);
  690. /* suspend, resume */
  691. // UTEST_UNIT_RUN(test_thread_suspend);
  692. #endif
  693. /* control */
  694. UTEST_UNIT_RUN(test_thread_control);
  695. UTEST_UNIT_RUN(test_thread_priority);
  696. /* delay_until */
  697. UTEST_UNIT_RUN(test_delay_until);
  698. /* timeslice */
  699. // UTEST_UNIT_RUN(test_timeslice); /* Can not running in Github Action QEMU */
  700. }
  701. UTEST_TC_EXPORT(testcase, "core.thread_tc", utest_tc_init, utest_tc_cleanup, 1000);
  702. /********************* end of file ************************/