diff --git a/examples/utest/configs/kernel/ipc.conf b/examples/utest/configs/kernel/ipc.conf index f8e687e6338a5dd3578d08872c391f23d09571a0..f961e082e17f31603ae06753c8386c287169a299 100644 --- a/examples/utest/configs/kernel/ipc.conf +++ b/examples/utest/configs/kernel/ipc.conf @@ -2,8 +2,10 @@ CONFIG_UTEST_SEMAPHORE_TC=y CONFIG_UTEST_EVENT_TC=y CONFIG_UTEST_MESSAGEQUEUE_TC=y CONFIG_UTEST_SIGNAL_TC=y +CONFIG_UTEST_MUTEX_TC=y # dependencies CONFIG_RT_USING_SEMAPHORE=y CONFIG_RT_USING_EVENT=y CONFIG_RT_USING_MESSAGEQUEUE=y CONFIG_RT_USING_SIGNALS=y +CONFIG_RT_USING_MUTEX=y \ No newline at end of file diff --git a/examples/utest/testcases/kernel/Kconfig b/examples/utest/testcases/kernel/Kconfig index f4673aebb9477e8f3bcab2fad4a677a18345cf51..fd4e1fecb96b5055151d828519d21f4950ee272d 100644 --- a/examples/utest/testcases/kernel/Kconfig +++ b/examples/utest/testcases/kernel/Kconfig @@ -31,4 +31,8 @@ config UTEST_SIGNAL_TC bool "signal test" default n +config UTEST_MUTEX_TC + bool "mutex test" + default n + endmenu diff --git a/examples/utest/testcases/kernel/SConscript b/examples/utest/testcases/kernel/SConscript index ca34db6fed13a8ea47df5c75feeaef7f02fd015e..4bf0a2e60b07559c40201fb4a7fb86cc530fe883 100644 --- a/examples/utest/testcases/kernel/SConscript +++ b/examples/utest/testcases/kernel/SConscript @@ -26,6 +26,9 @@ if GetDepend(['UTEST_MESSAGEQUEUE_TC']): if GetDepend(['UTEST_SIGNAL_TC']): src += ['signal_tc.c'] +if GetDepend(['UTEST_MUTEX_TC']): + src += ['mutex_tc.c'] + CPPPATH = [cwd] group = DefineGroup('utestcases', src, depend = [], CPPPATH = CPPPATH) diff --git a/examples/utest/testcases/kernel/mutex_tc.c b/examples/utest/testcases/kernel/mutex_tc.c new file mode 100644 index 0000000000000000000000000000000000000000..f50e3e43f7465143d773d76bb916f83fada7adc2 --- /dev/null +++ b/examples/utest/testcases/kernel/mutex_tc.c @@ -0,0 +1,676 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-09.01 luckyzjq the first version + */ + +#include +#include +#include "utest.h" + +static struct rt_mutex static_mutex; + +#ifdef RT_USING_HEAP +static rt_mutex_t dynamic_mutex; +#endif /* RT_USING_HEAP */ + +/* init test */ +static void test_static_mutex_init(void) +{ + rt_err_t result = -RT_ERROR; + + result = rt_mutex_init(&static_mutex, "static_mutex", RT_IPC_FLAG_PRIO); + if (RT_EOK != result) + { + uassert_true(RT_FALSE); + } + + result = rt_mutex_detach(&static_mutex); + if (RT_EOK != result) + { + uassert_true(RT_FALSE); + } + + result = rt_mutex_init(&static_mutex, "static_mutex", RT_IPC_FLAG_FIFO); + if (RT_EOK != result) + { + uassert_true(RT_FALSE); + } + + result = rt_mutex_detach(&static_mutex); + if (RT_EOK != result) + { + uassert_true(RT_FALSE); + } + + uassert_true(RT_TRUE); +} + +/* static take test */ +static void static_mutex_take_entry(void *param) +{ + rt_err_t result; + rt_mutex_t mutex; + + int rand_num = rand() % 0x1000; + mutex = (rt_mutex_t)param; + + result = rt_mutex_take(mutex, rand_num); + if (RT_EOK == result) + { + uassert_true(RT_FALSE); + } +} +static void test_static_mutex_take(void) +{ + rt_err_t result; + + result = rt_mutex_init(&static_mutex, "static_mutex", RT_IPC_FLAG_PRIO); + if (RT_EOK != result) + { + uassert_true(RT_FALSE); + return; + } + + /* take mutex and not release */ + result = rt_mutex_take(&static_mutex, RT_WAITING_FOREVER); + if (RT_EOK != result) + uassert_true(RT_FALSE); + + rt_thread_t tid = rt_thread_create("mutex_th", + static_mutex_take_entry, + &static_mutex, + 2048, + 10, + 10); + if (RT_NULL == tid) + { + uassert_true(RT_FALSE); + return; + } + + /* startup thread take second */ + rt_thread_startup(tid); + + /* let system schedule */ + rt_thread_mdelay(5); + + result = rt_mutex_detach(&static_mutex); + if (RT_EOK != result) + uassert_true(RT_FALSE); + + uassert_true(RT_TRUE); +} + +/* static release test */ +static void static_mutex_release_entry(void *param) +{ + rt_err_t result; + rt_mutex_t mutex; + + int rand_num = rand() % 0x1000; + mutex = (rt_mutex_t)param; + + result = rt_mutex_take(mutex, rand_num); + if (RT_EOK != result) + { + uassert_true(RT_FALSE); + } +} +static void test_static_mutex_release(void) +{ + rt_err_t result; + + result = rt_mutex_init(&static_mutex, "static_mutex", RT_IPC_FLAG_PRIO); + if (RT_EOK != result) + { + uassert_true(RT_FALSE); + return; + } + + /* take mutex */ + result = rt_mutex_take(&static_mutex, RT_WAITING_FOREVER); + if (RT_EOK != result) + uassert_true(RT_FALSE); + + /* release mutex */ + result = rt_mutex_release(&static_mutex); + if (RT_EOK != result) + uassert_true(RT_FALSE); + + rt_thread_t tid = rt_thread_create("mutex_th", + static_mutex_release_entry, + &static_mutex, + 2048, + 10, + 10); + if (RT_NULL == tid) + { + uassert_true(RT_FALSE); + return; + } + + /* startup thread and take mutex second */ + rt_thread_startup(tid); + + /* let system schedule */ + rt_thread_mdelay(5); + + result = rt_mutex_detach(&static_mutex); + if (RT_EOK != result) + uassert_true(RT_FALSE); + + uassert_true(RT_TRUE); +} + +/* static trytake test */ +static void static_mutex_trytake_entry(void *param) +{ + rt_err_t result; + rt_mutex_t mutex; + + mutex = (rt_mutex_t)param; + + result = rt_mutex_trytake(mutex); + if (RT_EOK == result) + { + uassert_true(RT_FALSE); + } +} +static void test_static_mutex_trytake(void) +{ + rt_err_t result; + + result = rt_mutex_init(&static_mutex, "static_mutex", RT_IPC_FLAG_PRIO); + if (RT_EOK != result) + { + uassert_true(RT_FALSE); + return; + } + + /* take mutex and not release */ + result = rt_mutex_take(&static_mutex, RT_WAITING_FOREVER); + if (RT_EOK != result) + uassert_true(RT_FALSE); + + rt_thread_t tid = rt_thread_create("mutex_th", + static_mutex_trytake_entry, + &static_mutex, + 2048, + 10, + 10); + if (RT_NULL == tid) + { + uassert_true(RT_FALSE); + return; + } + + /* startup thread and trytake mutex second */ + rt_thread_startup(tid); + + /* let system schedule */ + rt_thread_mdelay(5); + + result = rt_mutex_detach(&static_mutex); + if (RT_EOK != result) + uassert_true(RT_FALSE); + + uassert_true(RT_TRUE); +} + +static rt_thread_t tid1 = RT_NULL; +static rt_thread_t tid2 = RT_NULL; +static rt_thread_t tid3 = RT_NULL; + +/* static mutex priority reverse test */ +static void static_thread1_entry(void *param) +{ + /* let system schedule */ + rt_thread_mdelay(100); + + /* thread3 hode mutex thread2 take mutex */ + /* check thread2 and thread3 priority */ + if (tid2->current_priority != tid3->current_priority) + { + uassert_true(RT_FALSE); + } + else + { + uassert_true(RT_TRUE); + } +} + +static void static_thread2_entry(void *param) +{ + rt_err_t result; + rt_mutex_t mutex = (rt_mutex_t)param; + + /* let system schedule */ + rt_thread_mdelay(50); + + result = rt_mutex_take(mutex, RT_WAITING_FOREVER); + if (result == RT_EOK) + { + rt_mutex_release(mutex); + } +} +static void static_thread3_entry(void *param) +{ + rt_tick_t tick; + rt_err_t result; + rt_mutex_t mutex = (rt_mutex_t)param; + + result = rt_mutex_take(mutex, RT_WAITING_FOREVER); + if (result != RT_EOK) + { + uassert_true(RT_FALSE); + } + + tick = rt_tick_get(); + while (rt_tick_get() - tick < (RT_TICK_PER_SECOND / 2)); + + rt_mutex_release(mutex); +} + +static void test_static_pri_reverse(void) +{ + rt_err_t result; + tid1 = RT_NULL; + tid2 = RT_NULL; + tid3 = RT_NULL; + + result = rt_mutex_init(&static_mutex, "static_mutex", RT_IPC_FLAG_PRIO); + if (RT_EOK != result) + { + uassert_true(RT_FALSE); + return; + } + + /* thread1 */ + tid1 = rt_thread_create("thread1", + static_thread1_entry, + &static_mutex, + 1024, + 10 - 1, + 10); + if (tid1 != RT_NULL) + rt_thread_startup(tid1); + + /* thread2 */ + tid2 = rt_thread_create("thread2", + static_thread2_entry, + &static_mutex, + 1024, + 10, + 10); + if (tid2 != RT_NULL) + rt_thread_startup(tid2); + + /* thread3 */ + tid3 = rt_thread_create("thread3", + static_thread3_entry, + &static_mutex, + 1024, + 10 + 1, + 10); + if (tid3 != RT_NULL) + rt_thread_startup(tid3); + + rt_thread_mdelay(1000); + + result = rt_mutex_detach(&static_mutex); + if (RT_EOK != result) + uassert_true(RT_FALSE); + + uassert_true(RT_TRUE); +} + +/* create test */ +static void test_dynamic_mutex_create(void) +{ + rt_err_t result = -RT_ERROR; + + /* PRIO mode */ + dynamic_mutex = rt_mutex_create("dynamic_mutex", RT_IPC_FLAG_PRIO); + if (RT_NULL == result) + { + uassert_true(RT_FALSE); + } + + result = rt_mutex_delete(dynamic_mutex); + if (RT_EOK != result) + { + uassert_true(RT_FALSE); + } + + /* FIFO mode */ + dynamic_mutex = rt_mutex_create("dynamic_mutex", RT_IPC_FLAG_FIFO); + if (RT_NULL == dynamic_mutex) + { + uassert_true(RT_FALSE); + } + + result = rt_mutex_delete(dynamic_mutex); + if (RT_EOK != result) + { + uassert_true(RT_FALSE); + } + + uassert_true(RT_TRUE); +} + +/* dynamic take test */ +static void dynamic_mutex_take_entry(void *param) +{ + rt_err_t result; + rt_mutex_t mutex; + + int rand_num = rand() % 0x1000; + mutex = (rt_mutex_t)param; + + result = rt_mutex_take(mutex, rand_num); + if (RT_EOK == result) + { + uassert_true(RT_FALSE); + } +} +static void test_dynamic_mutex_take(void) +{ + rt_err_t result; + + dynamic_mutex = rt_mutex_create("dynamic_mutex", RT_IPC_FLAG_PRIO); + if (RT_NULL == dynamic_mutex) + { + uassert_true(RT_FALSE); + return; + } + + /* take mutex and not release */ + result = rt_mutex_take(dynamic_mutex, RT_WAITING_FOREVER); + if (RT_EOK != result) + uassert_true(RT_FALSE); + + rt_thread_t tid = rt_thread_create("mutex_th", + dynamic_mutex_take_entry, + dynamic_mutex, + 2048, + 10, + 10); + if (RT_NULL == tid) + { + uassert_true(RT_FALSE); + return; + } + + /* startup thread take second */ + rt_thread_startup(tid); + + /* let system schedule */ + rt_thread_mdelay(5); + + result = rt_mutex_delete(dynamic_mutex); + if (RT_EOK != result) + uassert_true(RT_FALSE); + + uassert_true(RT_TRUE); +} + +/* dynamic release test */ +static void dynamic_mutex_release_entry(void *param) +{ + rt_err_t result; + rt_mutex_t mutex; + + int rand_num = rand() % 0x1000; + mutex = (rt_mutex_t)param; + + result = rt_mutex_take(mutex, rand_num); + if (RT_EOK != result) + { + uassert_true(RT_FALSE); + } +} +static void test_dynamic_mutex_release(void) +{ + rt_err_t result; + + dynamic_mutex = rt_mutex_create("dynamic_mutex", RT_IPC_FLAG_PRIO); + if (RT_NULL == dynamic_mutex) + { + uassert_true(RT_FALSE); + return; + } + + /* take mutex */ + result = rt_mutex_take(dynamic_mutex, RT_WAITING_FOREVER); + if (RT_EOK != result) + uassert_true(RT_FALSE); + + /* release mutex */ + result = rt_mutex_release(dynamic_mutex); + if (RT_EOK != result) + uassert_true(RT_FALSE); + + rt_thread_t tid = rt_thread_create("mutex_th", + dynamic_mutex_release_entry, + dynamic_mutex, + 2048, + 10, + 10); + if (RT_NULL == tid) + { + uassert_true(RT_FALSE); + return; + } + + /* startup thread and take mutex second */ + rt_thread_startup(tid); + + /* let system schedule */ + rt_thread_mdelay(5); + + result = rt_mutex_delete(dynamic_mutex); + if (RT_EOK != result) + uassert_true(RT_FALSE); + + uassert_true(RT_TRUE); +} + +/* dynamic trytake test */ +static void dynamic_mutex_trytake_entry(void *param) +{ + rt_err_t result; + rt_mutex_t mutex; + + mutex = (rt_mutex_t)param; + + result = rt_mutex_trytake(mutex); + if (RT_EOK == result) + { + uassert_true(RT_FALSE); + } +} +static void test_dynamic_mutex_trytake(void) +{ + rt_err_t result; + + dynamic_mutex = rt_mutex_create("dynamic_mutex", RT_IPC_FLAG_PRIO); + if (RT_NULL == dynamic_mutex) + { + uassert_true(RT_FALSE); + return; + } + + /* take mutex and not release */ + result = rt_mutex_take(dynamic_mutex, RT_WAITING_FOREVER); + if (RT_EOK != result) + uassert_true(RT_FALSE); + + rt_thread_t tid = rt_thread_create("mutex_th", + dynamic_mutex_trytake_entry, + dynamic_mutex, + 2048, + 10, + 10); + if (RT_NULL == tid) + { + uassert_true(RT_FALSE); + return; + } + + /* startup thread and trytake mutex second */ + rt_thread_startup(tid); + + /* let system schedule */ + rt_thread_mdelay(5); + + result = rt_mutex_delete(dynamic_mutex); + if (RT_EOK != result) + uassert_true(RT_FALSE); + + uassert_true(RT_TRUE); +} + +/* dynamic mutex priority reverse test */ +static void dynamic_thread1_entry(void *param) +{ + /* let system schedule */ + rt_thread_mdelay(100); + + /* thread3 hode mutex thread2 take mutex */ + /* check thread2 and thread3 priority */ + if (tid2->current_priority != tid3->current_priority) + { + uassert_true(RT_FALSE); + } + else + { + uassert_true(RT_TRUE); + } +} + +static void dynamic_thread2_entry(void *param) +{ + rt_err_t result; + rt_mutex_t mutex = (rt_mutex_t)param; + + /* let system schedule */ + rt_thread_mdelay(50); + + result = rt_mutex_take(mutex, RT_WAITING_FOREVER); + if (result == RT_EOK) + { + rt_mutex_release(mutex); + } +} +static void dynamic_thread3_entry(void *param) +{ + rt_tick_t tick; + rt_err_t result; + rt_mutex_t mutex = (rt_mutex_t)param; + + result = rt_mutex_take(mutex, RT_WAITING_FOREVER); + if (result != RT_EOK) + { + uassert_true(RT_FALSE); + } + + tick = rt_tick_get(); + while (rt_tick_get() - tick < (RT_TICK_PER_SECOND / 2)); + + rt_mutex_release(mutex); +} + +static void test_dynamic_pri_reverse(void) +{ + rt_err_t result; + tid1 = RT_NULL; + tid2 = RT_NULL; + tid3 = RT_NULL; + + dynamic_mutex = rt_mutex_create("dynamic_mutex", RT_IPC_FLAG_PRIO); + if (RT_NULL == dynamic_mutex) + { + uassert_true(RT_FALSE); + return; + } + + /* thread1 */ + tid1 = rt_thread_create("thread1", + dynamic_thread1_entry, + dynamic_mutex, + 1024, + 10 - 1, + 10); + if (tid1 != RT_NULL) + rt_thread_startup(tid1); + + /* thread2 */ + tid2 = rt_thread_create("thread2", + dynamic_thread2_entry, + dynamic_mutex, + 1024, + 10, + 10); + if (tid2 != RT_NULL) + rt_thread_startup(tid2); + + /* thread3 */ + tid3 = rt_thread_create("thread3", + dynamic_thread3_entry, + dynamic_mutex, + 1024, + 10 + 1, + 10); + if (tid3 != RT_NULL) + rt_thread_startup(tid3); + + rt_thread_mdelay(1000); + + result = rt_mutex_delete(dynamic_mutex); + if (RT_EOK != result) + uassert_true(RT_FALSE); + + uassert_true(RT_TRUE); +} + +static rt_err_t utest_tc_init(void) +{ +#ifdef RT_USING_HEAP + dynamic_mutex = RT_NULL; +#endif /* RT_USING_HEAP */ + + return RT_EOK; +} + +static rt_err_t utest_tc_cleanup(void) +{ +#ifdef RT_USING_HEAP + dynamic_mutex = RT_NULL; +#endif /* RT_USING_HEAP */ + + return RT_EOK; +} + +static void testcase(void) +{ + UTEST_UNIT_RUN(test_static_mutex_init); + UTEST_UNIT_RUN(test_static_mutex_take); + UTEST_UNIT_RUN(test_static_mutex_release); + UTEST_UNIT_RUN(test_static_mutex_trytake); + UTEST_UNIT_RUN(test_static_pri_reverse); +#ifdef RT_USING_HEAP + UTEST_UNIT_RUN(test_dynamic_mutex_create); + UTEST_UNIT_RUN(test_dynamic_mutex_take); + UTEST_UNIT_RUN(test_dynamic_mutex_release); + UTEST_UNIT_RUN(test_dynamic_mutex_trytake); + UTEST_UNIT_RUN(test_dynamic_pri_reverse); +#endif +} +UTEST_TC_EXPORT(testcase, "testcases.kernel.mutex_tc", utest_tc_init, utest_tc_cleanup, 1000); + +/********************* end of file ************************/