123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756 |
- /*
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2021-09.01 yangjie the firet version
- * 2021-10.11 mazhiyuan add idle, yield, suspend, control, priority, delay_until
- */
- #define __RT_IPC_SOURCE__ /* include internal API for utest */
- #include <rtthread.h>
- #include <stdlib.h>
- #include "utest.h"
- #define THREAD_STACK_SIZE UTEST_THR_STACK_SIZE
- #define THREAD_TIMESLICE 10
- rt_align(RT_ALIGN_SIZE)
- static char thread2_stack[UTEST_THR_STACK_SIZE];
- static struct rt_thread thread2;
- #ifdef RT_USING_HEAP
- static rt_thread_t tid1 = RT_NULL;
- static rt_thread_t tid3 = RT_NULL;
- static rt_thread_t tid4 = RT_NULL;
- static rt_thread_t tid5 = RT_NULL;
- static rt_thread_t tid6 = RT_NULL;
- static rt_thread_t tid7 = RT_NULL;
- #endif /* RT_USING_HEAP */
- static volatile rt_uint32_t tid3_delay_pass_flag = 0;
- static volatile rt_uint32_t tid3_finish_flag = 0;
- static volatile rt_uint32_t tid4_finish_flag = 0;
- static volatile rt_uint32_t tid6_finish_flag = 0;
- static volatile rt_uint32_t thread5_source = 0;
- #ifndef RT_USING_SMP
- static volatile rt_uint32_t thread_yield_flag = 0;
- #endif
- static volatile rt_uint32_t entry_idle_hook_times = 0;
- static rt_thread_t __current_thread;
- static rt_uint8_t change_priority;
- static volatile rt_uint32_t count = 0;
- void thread1_entry(void *param)
- {
- while (1);
- }
- static void test_dynamic_thread(void)
- {
- rt_err_t ret_startup = -RT_ERROR;
- rt_err_t ret_delete = -RT_ERROR;
- tid1 = rt_thread_create("thread1",
- thread1_entry,
- (void *)1,
- THREAD_STACK_SIZE,
- UTEST_THR_PRIORITY + 1,
- THREAD_TIMESLICE - 5);
- if (tid1 == RT_NULL)
- {
- uassert_false(tid1 == RT_NULL);
- goto __exit;
- }
- ret_startup = rt_thread_startup(tid1);
- if (ret_startup != RT_EOK)
- {
- uassert_false(ret_startup != RT_EOK);
- goto __exit;
- }
- ret_delete = rt_thread_delete(tid1);
- if (ret_delete != RT_EOK)
- {
- uassert_false(ret_delete != RT_EOK);
- goto __exit;
- }
- uassert_true(tid1 != RT_NULL && ret_startup == RT_EOK && ret_delete == RT_EOK);
- __exit:
- if (tid1 != RT_NULL && ret_delete != RT_EOK)
- {
- rt_thread_delete(tid1);
- }
- return;
- }
- void thread2_entry(void *param)
- {
- while (1);
- }
- static void test_static_thread(void)
- {
- rt_err_t ret_init = -RT_ERROR;
- rt_err_t ret_startup = -RT_ERROR;
- rt_err_t ret_detach = -RT_ERROR;
- ret_init = rt_thread_init(&thread2,
- "thread2",
- thread2_entry,
- (void *)2,
- &thread2_stack[0],
- sizeof(thread2_stack),
- UTEST_THR_PRIORITY + 1,
- THREAD_TIMESLICE);
- if (ret_init != RT_EOK)
- {
- uassert_false(ret_init != RT_EOK);
- goto __exit;
- }
- ret_startup = rt_thread_startup(&thread2);
- if (ret_startup != RT_EOK)
- {
- uassert_false(ret_startup != RT_EOK);
- goto __exit;
- }
- ret_detach = rt_thread_detach(&thread2);
- if (ret_detach != RT_EOK)
- {
- uassert_false(ret_detach != RT_EOK);
- goto __exit;
- }
- uassert_true(ret_init == RT_EOK && ret_startup == RT_EOK && ret_detach == RT_EOK);
- __exit:
- if (ret_init == RT_EOK && ret_detach != RT_EOK)
- {
- rt_thread_detach(&thread2);
- }
- return;
- }
- static void thread3_entry(void *parameter)
- {
- rt_tick_t tick, latency_tick;
- tick = rt_tick_get();
- rt_thread_delay(15);
- latency_tick = rt_tick_get() - tick;
- if (latency_tick > 16 || latency_tick < 15)
- {
- tid3_finish_flag = 1;
- tid3_delay_pass_flag = 0;
- return;
- }
- tid3_delay_pass_flag = 1;
- tid3_finish_flag = 1;
- }
- static void test_thread_delay(void)
- {
- rt_err_t ret_startup = -RT_ERROR;
- tid3 = rt_thread_create("thread3",
- thread3_entry,
- RT_NULL,
- THREAD_STACK_SIZE,
- UTEST_THR_PRIORITY - 1,
- THREAD_TIMESLICE);
- if (tid3 == RT_NULL)
- {
- LOG_E("rt_thread_create failed!");
- uassert_false(tid3 == RT_NULL);
- goto __exit;
- }
- ret_startup = rt_thread_startup(tid3);
- if (ret_startup != RT_EOK)
- {
- LOG_E("rt_thread_startup failed!");
- uassert_false(1);
- goto __exit;
- }
- while (tid3_finish_flag != 1);
- uassert_true(tid3_delay_pass_flag == 1);
- __exit:
- return;
- }
- static void idle_hook(void)
- {
- entry_idle_hook_times ++;
- }
- static void thread4_entry(void *parameter)
- {
- rt_uint32_t delay_times = 5;
- while (delay_times --)
- {
- rt_thread_mdelay(300);
- }
- rt_thread_idle_delhook(idle_hook);
- tid4_finish_flag = 1;
- }
- static void test_idle_hook(void)
- {
- rt_err_t ret_startup = -RT_ERROR;
- rt_thread_idle_sethook(idle_hook);
- tid4 = rt_thread_create("thread4",
- thread4_entry,
- RT_NULL,
- THREAD_STACK_SIZE,
- UTEST_THR_PRIORITY - 1,
- THREAD_TIMESLICE);
- if (tid4 == RT_NULL)
- {
- LOG_E("rt_thread_create failed!");
- uassert_false(tid4 == RT_NULL);
- goto __exit;
- }
- ret_startup = rt_thread_startup(tid4);
- if (ret_startup != RT_EOK)
- {
- LOG_E("rt_thread_startup failed!");
- uassert_false(1);
- goto __exit;
- }
- while (tid4_finish_flag != 1)
- {
- rt_thread_mdelay(200);
- }
- uassert_true(entry_idle_hook_times > 0);
- __exit:
- return;
- }
- static void thread5_entry(void *parameter)
- {
- while (1)
- {
- thread5_source ++;
- rt_thread_delay(5);
- if (thread5_source == 5)
- {
- rt_thread_yield();
- }
- }
- }
- static void thread6_entry(void *parameter)
- {
- while (++ thread5_source <= 9);
- tid6_finish_flag = 1;
- }
- static void test_thread_yield(void)
- {
- rt_err_t ret_startup = -RT_ERROR;
- thread5_source = 0;
- tid5 = rt_thread_create("thread5",
- thread5_entry,
- RT_NULL,
- THREAD_STACK_SIZE,
- UTEST_THR_PRIORITY - 1,
- THREAD_TIMESLICE);
- if (tid5 == RT_NULL)
- {
- LOG_E("rt_thread_create failed!");
- uassert_false(tid5 == RT_NULL);
- goto __exit;
- }
- ret_startup = rt_thread_startup(tid5);
- if (ret_startup != RT_EOK)
- {
- LOG_E("rt_thread_startup failed!");
- uassert_false(1);
- goto __exit;
- }
- tid6 = rt_thread_create("thread6",
- thread6_entry,
- RT_NULL,
- THREAD_STACK_SIZE,
- UTEST_THR_PRIORITY - 1,
- THREAD_TIMESLICE);
- if (tid6 == RT_NULL)
- {
- LOG_E("rt_thread_create failed!");
- uassert_false(tid6 == RT_NULL);
- goto __exit;
- }
- ret_startup = rt_thread_startup(tid6);
- if (ret_startup != RT_EOK)
- {
- LOG_E("rt_thread_startup failed!");
- uassert_false(1);
- goto __exit;
- }
- while (tid6_finish_flag != 1);
- uassert_true(thread5_source == 10);
- __exit:
- if (tid5 != RT_NULL)
- {
- rt_thread_delete(tid5);
- }
- return;
- }
- static void thread7_entry(void *parameter)
- {
- while (1);
- }
- static void test_thread_control(void)
- {
- rt_err_t ret_control = -RT_ERROR;
- rt_err_t rst_delete = -RT_ERROR;
- rt_sched_lock_level_t slvl;
- tid7 = rt_thread_create("thread7",
- thread7_entry,
- RT_NULL,
- THREAD_STACK_SIZE,
- UTEST_THR_PRIORITY + 1,
- THREAD_TIMESLICE);
- if (tid7 == RT_NULL)
- {
- LOG_E("rt_thread_create failed!");
- uassert_false(tid7 == RT_NULL);
- goto __exit;
- }
- ret_control = rt_thread_control(tid7, RT_THREAD_CTRL_STARTUP, RT_NULL);
- if (ret_control != RT_EOK)
- {
- LOG_E("rt_thread_control failed!");
- uassert_false(1);
- goto __exit;
- }
- rt_thread_mdelay(200);
- rt_thread_control(tid7, RT_THREAD_CTRL_CHANGE_PRIORITY, &change_priority);
- rt_sched_lock(&slvl);
- if (rt_sched_thread_get_curr_prio(tid7) != change_priority)
- {
- LOG_E("rt_thread_control failed!");
- uassert_false(1);
- rt_sched_unlock(slvl);
- goto __exit;
- }
- rt_sched_unlock(slvl);
- rst_delete = rt_thread_control(tid7, RT_THREAD_CTRL_CLOSE, RT_NULL);
- if (rst_delete != RT_EOK)
- {
- LOG_E("rt_thread_control failed!");
- uassert_false(rst_delete != RT_EOK);
- goto __exit;
- }
- uassert_true(1);
- __exit:
- if (tid7 != RT_NULL && rst_delete != RT_EOK)
- {
- rt_thread_delete(tid7);
- }
- return;
- }
- static void thread8_entry(void *parameter)
- {
- for (; count < 10; count ++);
- }
- static void test_thread_priority(void)
- {
- rt_err_t ret_startup = -RT_ERROR;
- rt_thread_t tid8 = RT_NULL;
- tid8 = rt_thread_create("thread8",
- thread8_entry,
- RT_NULL,
- THREAD_STACK_SIZE,
- UTEST_THR_PRIORITY - 1,
- THREAD_TIMESLICE);
- if (tid8 == RT_NULL)
- {
- LOG_E("rt_thread_create failed!");
- uassert_false(tid8 == RT_NULL);
- return;
- }
- count = 0;
- ret_startup = rt_thread_startup(tid8);
- if (ret_startup != RT_EOK)
- {
- uassert_false(ret_startup != RT_EOK);
- return ;
- }
- uassert_true(count == 10);
- return;
- }
- static void test_delay_until(void)
- {
- rt_tick_t tick;
- rt_tick_t check_tick = 0;
- rt_tick_t delta = 0;
- tick = rt_tick_get();
- check_tick = tick;
- rt_thread_delay_until(&tick, 100);
- delta = rt_tick_get() - check_tick;
- rt_kprintf("delta[100] -> %d\n", delta);
- uassert_int_equal(delta, 100);
- check_tick = tick;
- rt_thread_delay(2);
- rt_thread_delay_until(&tick, 200);
- delta = rt_tick_get() - check_tick;
- rt_kprintf("delta[200] -> %d\n", delta);
- uassert_int_equal(delta, 200);
- check_tick = tick;
- rt_thread_delay(2);
- rt_thread_delay_until(&tick, 300);
- delta = rt_tick_get() - check_tick;
- rt_kprintf("delta[300] -> %d\n", delta);
- uassert_int_equal(delta, 300);
- check_tick = tick;
- rt_thread_delay(2);
- rt_thread_delay_until(&tick, 100);
- delta = rt_tick_get() - check_tick;
- uassert_int_equal(delta, 100);
- check_tick = tick;
- rt_thread_delay(2);
- rt_thread_delay_until(&tick, 50);
- delta = rt_tick_get() - check_tick;
- rt_kprintf("delta[50] -> %d\n", delta);
- uassert_int_equal(delta, 50);
- check_tick = tick;
- rt_thread_delay(2);
- rt_thread_delay_until(&tick, 20);
- delta = rt_tick_get() - check_tick;
- rt_kprintf("delta[20] -> %d\n", delta);
- uassert_int_equal(delta, 20);
- /**
- * the rt_kprints above can take few ticks to complete, maybe more than 10
- */
- tick = rt_tick_get();
- check_tick = tick;
- rt_thread_delay(2);
- rt_thread_delay_until(&tick, 10);
- delta = rt_tick_get() - check_tick;
- rt_kprintf("delta[10] -> %d\n", delta);
- uassert_int_equal(delta, 10);
- }
- static rt_thread_t tidA, tidB1, tidB2;
- static uint32_t timeslice_cntA, timeslice_cntB1, timeslice_cntB2;
- static void test_timeslice_threadA_entry(void *parameter)
- {
- while (1)
- {
- rt_thread_delay(2);
- timeslice_cntA++;
- if (timeslice_cntA > 10) return;
- }
- }
- static void test_timeslice_threadB1_entry(void *parameter)
- {
- while (1)
- {
- timeslice_cntB1++;
- if (timeslice_cntA > 10) return;
- }
- }
- static void test_timeslice_threadB2_entry(void *parameter)
- {
- while (1)
- {
- timeslice_cntB2++;
- if (timeslice_cntA > 10) return;
- }
- }
- void test_timeslice(void)
- {
- rt_err_t ret_startup = -RT_ERROR;
- uint32_t diff;
- timeslice_cntA = 0;
- timeslice_cntB1 = 0;
- timeslice_cntB2 = 0;
- tidA = rt_thread_create("timeslice", test_timeslice_threadA_entry, RT_NULL,
- 2048, UTEST_THR_PRIORITY + 1, 10);
- if (!tidA)
- {
- LOG_E("rt_thread_create failed!");
- return;
- }
- rt_thread_control(tidA, RT_THREAD_CTRL_BIND_CPU, (void *)1);
- ret_startup = rt_thread_startup(tidA);
- if (ret_startup != RT_EOK)
- {
- LOG_E("rt_thread_startup failed!");
- uassert_false(1);
- return ;
- }
- tidB1 = rt_thread_create("timeslice", test_timeslice_threadB1_entry, RT_NULL,
- 2048, UTEST_THR_PRIORITY + 2, 2);
- if (!tidB1)
- {
- LOG_E("rt_thread_create failed!");
- return;
- }
- rt_thread_control(tidB1, RT_THREAD_CTRL_BIND_CPU, (void *)1);
- ret_startup = rt_thread_startup(tidB1);
- if (ret_startup != RT_EOK)
- {
- LOG_E("rt_thread_startup failed!");
- uassert_false(1);
- return ;
- }
- tidB2 = rt_thread_create("timeslice", test_timeslice_threadB2_entry, RT_NULL,
- 2048, UTEST_THR_PRIORITY + 2, 2);
- if (!tidB2)
- {
- LOG_E("rt_thread_create failed!");
- return;
- }
- rt_thread_control(tidB2, RT_THREAD_CTRL_BIND_CPU, (void *)1);
- ret_startup = rt_thread_startup(tidB2);
- if (ret_startup != RT_EOK)
- {
- LOG_E("rt_thread_startup failed!");
- uassert_false(1);
- return ;
- }
- do{
- rt_thread_delay(2 * 20);
- }while(timeslice_cntA <= 10);
- rt_kprintf("A:%d,B1:%d,B2:%d\n", timeslice_cntA, timeslice_cntB1, timeslice_cntB2);
- diff = abs(timeslice_cntB1 - timeslice_cntB2);
- uassert_true(diff * 100 / timeslice_cntB1 < 30);
- uassert_true(timeslice_cntA == 11);
- }
- #ifndef RT_USING_SMP
- static volatile rt_uint32_t yield_count;
- static void test_thread_yield_inc_entry(void *parameter)
- {
- rt_uint32_t loop = 0;
- while (1)
- {
- if (loop++ > 10001)
- break;
- yield_count++;
- rt_thread_yield();
- }
- }
- static void test_thread_yield_entry(void *parameter)
- {
- rt_err_t ret_startup = -RT_ERROR;
- rt_thread_t tid;
- rt_uint32_t loop = 0;
- rt_uint32_t count_before;
- tid = rt_thread_create("inc", test_thread_yield_inc_entry, RT_NULL,
- 2048, 1, 10);
- if (!tid)
- {
- LOG_E("rt_thread_create failed!");
- return;
- }
- ret_startup = rt_thread_startup(tid);
- if (ret_startup != RT_EOK)
- {
- LOG_E("rt_thread_startup failed!");
- uassert_false(1);
- return ;
- }
- while (1)
- {
- if (loop++ > 10000)
- break;
- count_before = yield_count;
- rt_thread_yield();
- if (yield_count == count_before)
- {
- LOG_E("yield error!");
- return;
- }
- }
- thread_yield_flag = 1;
- }
- void test_thread_yield_nosmp(void)
- {
- rt_err_t ret_startup = -RT_ERROR;
- rt_thread_t tid;
- yield_count = 0;
- tid = rt_thread_create("chkcnt", test_thread_yield_entry, RT_NULL,
- 2048, 1, 10);
- if (!tid)
- {
- LOG_E("rt_thread_create failed!");
- return;
- }
- ret_startup = rt_thread_startup(tid);
- if (ret_startup != RT_EOK)
- {
- LOG_E("rt_thread_startup failed!");
- uassert_false(1);
- return ;
- }
- uassert_true(thread_yield_flag == 1);
- }
- // static rt_uint32_t thread9_count = 0;
- // static void thread9_entry(void *parameter)
- // {
- // while (1)
- // {
- // thread9_count ++;
- // }
- // }
- // static void test_thread_suspend(void)
- // {
- // static rt_thread_t tid;
- // rt_err_t ret_startup = -RT_ERROR;
- // uint32_t count_before_suspend, count_before_resume, count_after_resume;
- // tid = rt_thread_create("thread9",
- // thread9_entry,
- // RT_NULL,
- // THREAD_STACK_SIZE,
- // UTEST_THR_PRIORITY + 1,
- // THREAD_TIMESLICE);
- // if (tid == RT_NULL)
- // {
- // LOG_E("rt_thread_create failed!");
- // uassert_false(tid4 == RT_NULL);
- // goto __exit;
- // }
- // ret_startup = rt_thread_startup(tid);
- // if (ret_startup != RT_EOK)
- // {
- // LOG_E("rt_thread_startup failed!");
- // uassert_false(1);
- // goto __exit;
- // }
- // rt_thread_delay(5);
- // rt_thread_suspend(tid);
- // count_before_suspend = thread9_count;
- // uassert_true(count_before_suspend != 0);
- // rt_thread_delay(5);
- // count_before_resume = thread9_count;
- // uassert_true(count_before_suspend == count_before_resume);
- // rt_thread_resume(tid);
- // rt_thread_delay(5);
- // count_after_resume = thread9_count;
- // uassert_true(count_after_resume != count_before_resume);
- // __exit:
- // if (tid != RT_NULL)
- // {
- // rt_thread_delete(tid);
- // }
- // return;
- // }
- #endif
- static rt_err_t utest_tc_init(void)
- {
- __current_thread = rt_thread_self();
- change_priority = UTEST_THR_PRIORITY + 5;
- tid3_delay_pass_flag = 0;
- tid3_finish_flag = 0;
- tid4_finish_flag = 0;
- tid6_finish_flag = 0;
- entry_idle_hook_times = 0;
- count = 0;
- return RT_EOK;
- }
- static rt_err_t utest_tc_cleanup(void)
- {
- return RT_EOK;
- }
- static void testcase(void)
- {
- /* init, detach */
- UTEST_UNIT_RUN(test_static_thread);
- /* create, delete */
- UTEST_UNIT_RUN(test_dynamic_thread);
- /* delay */
- UTEST_UNIT_RUN(test_thread_delay);
- /* idle_sethook, idle_delhook */
- UTEST_UNIT_RUN(test_idle_hook);
- /* yield */
- UTEST_UNIT_RUN(test_thread_yield);
- #ifndef RT_USING_SMP
- /* yield_nosmp */
- UTEST_UNIT_RUN(test_thread_yield_nosmp);
- /* suspend, resume */
- // UTEST_UNIT_RUN(test_thread_suspend);
- #endif
- /* control */
- UTEST_UNIT_RUN(test_thread_control);
- UTEST_UNIT_RUN(test_thread_priority);
- /* delay_until */
- UTEST_UNIT_RUN(test_delay_until);
- /* timeslice */
- // UTEST_UNIT_RUN(test_timeslice); /* Can not running in Github Action QEMU */
- }
- UTEST_TC_EXPORT(testcase, "testcases.kernel.thread_tc", utest_tc_init, utest_tc_cleanup, 1000);
- /********************* end of file ************************/
|