Browse Source

testcase: add system performance testcase (#10452)

* add  sys pref frameworks

* add context switch test code

* add irq latency test code

* add  thread sem test code

* add  thread event test code

* add  thread mbox test code

* add  thread mq test code

* Adding a Test Documentation Note

* Modification of text description
rcitach 1 week ago
parent
commit
2cb69c8e08

+ 1 - 0
examples/utest/testcases/Kconfig

@@ -17,6 +17,7 @@ rsource "posix/Kconfig"
 rsource "mm/Kconfig"
 rsource "tmpfs/Kconfig"
 rsource "smp_call/Kconfig"
+rsource "perf/Kconfig"
 endif
 
 endmenu

+ 24 - 0
examples/utest/testcases/perf/Kconfig

@@ -0,0 +1,24 @@
+menu "SyStem Performance Testcase"
+
+config UTEST_SYS_PERF_TC
+    bool "SyStem Performance test"
+    default n
+
+config UTEST_SYS_PERF_TC_COUNT
+    int "Test the number of cycles"
+    default 1000
+    depends on UTEST_SYS_PERF_TC
+
+config UTEST_HWTIMER_DEV_NAME
+    string "Hardware timer device name"
+    default "timer0"
+    depends on RT_USING_HWTIMER && UTEST_SYS_PERF_TC
+    help
+        Specify the hardware timer device name used for context switch testing (e.g., timer0).
+
+config UTEST_SYS_IRQ_LATENCY
+    bool "SyStem IRQ LATENCY test"
+    default n
+    depends on RT_USING_HWTIMER && UTEST_SYS_PERF_TC
+
+endmenu

+ 12 - 0
examples/utest/testcases/perf/README.md

@@ -0,0 +1,12 @@
+# testcases 说明
+
+## 一、测试用例说明
+
+| 文件  | 说明 |
+|--------|--------|
+| context_switch.c  | 上下文切换测试代码  |
+| irq_latency.c  | 中断延时测试代码  |
+| rt_perf_thread_event.c  | 线程事件性能测试  |
+| rt_perf_thread_mbox.c  | 线程邮箱性能测试  |
+| rt_perf_thread_mq.c  | 线程消息队列性能测试  |
+| rt_perf_thread_sem.c  | 线程信号量性能测试  |

+ 10 - 0
examples/utest/testcases/perf/SConscript

@@ -0,0 +1,10 @@
+Import('rtconfig')
+from building import *
+
+cwd     = GetCurrentDir()
+src     = Glob('*.c')
+CPPPATH = [cwd]
+
+group = DefineGroup('utestcases', src, depend = ['UTEST_SYS_PERF_TC'], CPPPATH = CPPPATH)
+
+Return('group')

+ 106 - 0
examples/utest/testcases/perf/context_switch_tc.c

@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2006-2025, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2025-07-03     rcitach      test case for context_switch
+ */
+
+#include <rtthread.h>
+#include <rthw.h>
+#include <rtdevice.h>
+#include <utest.h>
+#include <utest_assert.h>
+#include <perf_tc.h>
+
+static rt_sem_t sem1, sem2;
+static rt_sem_t complete_sem = RT_NULL;
+
+static void local_modify_time(rt_perf_t *perf)
+{
+    if(perf)
+        perf->real_time = perf->real_time - perf->tmp_time;
+}
+
+static void perf_thread_event1(void *parameter)
+{
+    while (1)
+    {
+        rt_sem_take(sem1, RT_WAITING_FOREVER);
+        rt_sem_release(sem2);
+    }
+}
+
+static void perf_thread_event2(void *parameter)
+{
+    rt_perf_t *perf = (rt_perf_t *)parameter;
+
+    for (rt_uint32_t i = 0; i < UTEST_SYS_PERF_TC_COUNT; i++)
+    {
+        perf->tmp_time = 0;
+        rt_perf_start(perf);
+        rt_sem_take(sem2, RT_WAITING_FOREVER);
+        rt_sem_release(sem2);
+        rt_perf_stop(perf);
+
+        rt_mutex_take(perf->lock,RT_WAITING_FOREVER);
+        perf->count -= 1;
+        perf->tmp_time = perf->real_time;
+        rt_mutex_release(perf->lock);
+
+        rt_perf_start(perf);
+        rt_sem_take(sem2, RT_WAITING_FOREVER);
+        rt_sem_release(sem1);
+        rt_perf_stop(perf);
+    }
+    rt_sem_release(complete_sem);
+}
+
+rt_err_t context_switch_test(rt_perf_t *perf)
+{
+    rt_thread_t thread1 = RT_NULL;
+    rt_thread_t thread2 = RT_NULL;
+
+# if __STDC_VERSION__ >= 199901L
+    rt_strcpy(perf->name,__func__);
+#else
+    rt_strcpy(perf->name,"context_switch_test");
+#endif
+
+    perf->local_modify = local_modify_time;
+    sem1 = rt_sem_create("sem1", 1, RT_IPC_FLAG_FIFO);
+    sem2 = rt_sem_create("sem2", 0, RT_IPC_FLAG_FIFO);
+    complete_sem = rt_sem_create("complete_sem", 0, RT_IPC_FLAG_FIFO);
+
+    thread1 = rt_thread_create("perf_thread_event1", perf_thread_event1, perf,
+                                THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE);
+    if (thread1 == RT_NULL)
+    {
+        LOG_E("perf_thread_event1 create failed.");
+        return -RT_ERROR;
+    }
+
+    thread2 = rt_thread_create("perf_thread_event2", perf_thread_event2, perf,
+                                THREAD_STACK_SIZE, THREAD_PRIORITY + 1, THREAD_TIMESLICE);
+    if (thread2 == RT_NULL)
+    {
+        LOG_E("perf_thread_event2 create failed.");
+        return -RT_ERROR;
+    }
+
+    rt_thread_startup(thread1);
+    rt_thread_startup(thread2);
+
+    rt_sem_take(complete_sem, RT_WAITING_FOREVER);
+
+    rt_perf_dump(perf);
+    rt_thread_delete(thread1);
+    rt_sem_delete(complete_sem);
+    rt_sem_delete(sem1);
+    rt_sem_delete(sem2);
+
+    return RT_EOK;
+}
+

+ 80 - 0
examples/utest/testcases/perf/irq_latency_tc.c

@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2006-2025, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2025-07-03     rcitach      test case for irq latency
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+#include <utest.h>
+#include <utest_assert.h>
+#include <perf_tc.h>
+
+static rt_device_t hw_dev = RT_NULL;
+static rt_sem_t complete_sem = RT_NULL;
+static rt_hwtimerval_t timeout = {0};
+static rt_perf_t *perf_local = RT_NULL;
+
+static void modify_time(rt_perf_t *perf)
+{
+    if(perf)
+        perf->real_time = perf->real_time - perf->tmp_time;
+}
+
+static rt_err_t timer_callback(rt_device_t dev, rt_size_t size)
+{
+    rt_perf_stop(perf_local);
+    if (perf_local->count >= UTEST_SYS_PERF_TC_COUNT)
+    {
+        rt_sem_release(complete_sem);
+        return RT_EOK;
+    }
+    rt_perf_start_impl(perf_local, &timeout);
+    return RT_EOK;
+}
+
+rt_err_t rt_perf_irq_latency(rt_perf_t *perf)
+{
+# if __STDC_VERSION__ >= 199901L
+    rt_strcpy(perf->name,__func__);
+#else
+    rt_strcpy(perf->name,"rt_perf_irq_latency");
+#endif
+    int ret = RT_EOK;
+    rt_hwtimer_mode_t mode = HWTIMER_MODE_PERIOD;
+
+    perf_local = perf;
+    hw_dev = rt_device_find(UTEST_HWTIMER_DEV_NAME);
+    if (hw_dev == RT_NULL)
+    {
+        ret = RT_ERROR;
+        LOG_E("hwtimer sample run failed! can't find %s device!", UTEST_HWTIMER_DEV_NAME);
+        return ret;
+    }
+
+    complete_sem = rt_sem_create("complete", 0, RT_IPC_FLAG_FIFO);
+    timeout.sec = 0;
+    timeout.usec = 50;   /* No modification is necessary here, use the fixed value */
+
+    rt_mutex_take(perf->lock,RT_WAITING_FOREVER);
+    perf_local->tmp_time = (rt_uint32_t)(timeout.sec * 1000000u + timeout.usec);
+    perf_local->local_modify = modify_time;
+    rt_mutex_release(perf->lock);
+
+    rt_device_set_rx_indicate(hw_dev, timer_callback);
+    rt_device_control(hw_dev, HWTIMER_CTRL_MODE_SET, (void *)&mode);
+
+    rt_perf_start_impl(perf_local, &timeout);
+
+    rt_sem_take(complete_sem, RT_WAITING_FOREVER);
+    rt_perf_dump(perf_local);
+    rt_sem_delete(complete_sem);
+    rt_device_close(hw_dev);
+
+    return RT_EOK;
+}
+

+ 202 - 0
examples/utest/testcases/perf/perf_tc.c

@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2006-2025, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2025-07-03     rcitach      test case for irq latency
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+#include <rtservice.h>
+#include <utest.h>
+#include <utest_assert.h>
+#include <perf_tc.h>
+
+#define RET_INT             0
+#define RET_DECIMALS        1
+
+#define GET_INT(num)        split_double(num, RET_INT)
+#define GET_DECIMALS(num)   split_double(num, RET_DECIMALS)
+
+static rt_device_t hw_dev = RT_NULL;
+static rt_hwtimerval_t timeout_s = {0};
+
+typedef rt_err_t (*testcase_function)(rt_perf_t *perf);
+testcase_function test_func_ptrs[] =
+{
+    context_switch_test,
+    rt_perf_thread_sem,
+    rt_perf_thread_event,
+    rt_perf_thread_mq,
+    rt_perf_thread_mbox,
+    rt_perf_irq_latency,    /* Timer Interrupt Source */
+    RT_NULL
+};
+
+static rt_uint32_t rt_perf_get_timer_us(void)
+{
+    rt_hwtimerval_t timer_val = {0};
+    if (hw_dev && rt_device_read(hw_dev, 0, &timer_val, sizeof(rt_hwtimerval_t)))
+    {
+        return (rt_uint32_t)(timer_val.sec * 1000000u + timer_val.usec); /* return us */
+    }
+    return 0;
+}
+
+void rt_perf_start_impl(rt_perf_t *perf, rt_hwtimerval_t *timeout)
+{
+    if (hw_dev)
+    {
+        if (timeout == RT_NULL)
+            timeout = &timeout_s;
+        rt_device_write(hw_dev, 0, timeout, sizeof(rt_hwtimerval_t));
+    }
+    perf->begin_time = rt_perf_get_timer_us();
+}
+
+void rt_perf_stop(rt_perf_t *perf)
+{
+    perf->real_time = rt_perf_get_timer_us() - perf->begin_time;
+
+    if(perf->local_modify) perf->local_modify(perf);
+    if (perf->real_time > perf->max_time)
+    {
+        perf->max_time = perf->real_time;
+    }
+
+    if (perf->real_time < perf->min_time)
+    {
+        perf->min_time = perf->real_time;
+    }
+
+    perf->count++;
+    perf->tot_time += perf->real_time;
+
+    if(hw_dev)
+        rt_device_control(hw_dev, HWTIMER_CTRL_STOP, NULL);
+}
+
+static rt_int32_t split_double(double num, rt_uint32_t type)
+{
+    if (type == RET_INT)
+    {
+        return (rt_int32_t)num;
+    }
+    else if (type == RET_DECIMALS)
+    {
+        return (rt_int32_t)((num - (rt_int32_t)num) * 10000);
+    }
+    else
+    {
+        return (-1);
+    }
+
+    return (-1);
+}
+
+void rt_perf_dump( rt_perf_t *perf)
+{
+    static rt_uint32_t test_index = 1;
+    char avg_str[10] = {0};
+    if(perf->dump_head)
+    {
+        rt_kprintf("Test No | Test Name            | Count | Total Time (us) | Max Time (us) | Min Time (us) | Avg Time (us)\n");
+        rt_kprintf("--------|----------------------|-------|-----------------|---------------|---------------|--------------\n");
+        perf->dump_head = RT_FALSE;
+    }
+
+    if (perf->count)
+        perf->avg_time = (double)perf->tot_time / perf->count;
+    else
+        perf->avg_time = 0.0;
+
+    rt_sprintf(avg_str, "%u.%04u", GET_INT(perf->avg_time), GET_DECIMALS(perf->avg_time));
+
+    rt_kprintf("%7u | %-20s | %5u | %15u | %13u | %13u | %12s\n",
+                test_index++,
+                perf->name,
+                perf->count,
+                perf->tot_time,
+                perf->max_time,
+                perf->min_time,
+                avg_str);
+}
+
+static void rt_perf_clear(rt_perf_t *perf)
+{
+    perf->local_modify = NULL;
+    perf->begin_time = 0;
+    perf->real_time = 0;
+    perf->tot_time = 0;
+    perf->max_time = 0;
+    perf->min_time = RT_UINT32_MAX;
+    perf->count = 0;
+    perf->avg_time = 0;
+    perf->tmp_time = 0;
+}
+
+static void rt_perf_all_test(void)
+{
+
+    rt_perf_t *perf_data = rt_malloc(sizeof(rt_perf_t));
+    if (perf_data == RT_NULL)
+    {
+        return;
+    }
+    perf_data->lock = rt_mutex_create("perf", RT_IPC_FLAG_PRIO);
+    perf_data->dump_head = RT_TRUE;
+    rt_kprintf("\n === Performance Test Results Start ===\n");
+    for (int i = 0; test_func_ptrs[i] != RT_NULL; i++)
+    {
+        rt_perf_clear(perf_data);
+        if (test_func_ptrs[i](perf_data) != RT_EOK)
+        {
+            LOG_E("%s test fail",perf_data->name);
+            continue;
+        }
+    }
+    rt_kprintf("\n === Performance Test Results End ===\n");
+    rt_mutex_delete(perf_data->lock);
+    rt_free(perf_data);
+}
+
+static rt_err_t utest_tc_init(void)
+{
+    int ret = RT_EOK;
+
+    hw_dev = rt_device_find(UTEST_HWTIMER_DEV_NAME);
+    if (hw_dev == RT_NULL)
+    {
+        ret = RT_ERROR;
+        LOG_E("hwtimer sample run failed! can't find %s device!", UTEST_HWTIMER_DEV_NAME);
+        return ret;
+    }
+    ret = rt_device_open(hw_dev, RT_DEVICE_OFLAG_RDWR);
+    if (ret != RT_EOK)
+    {
+        LOG_E("open %s device failed!", UTEST_HWTIMER_DEV_NAME);
+        return ret;
+    }
+
+    timeout_s.sec  = 10;      /* No modification is necessary here, use the fixed value */
+    timeout_s.usec = 0;
+
+    return ret;
+}
+
+static rt_err_t utest_tc_cleanup(void)
+{
+    if(hw_dev) rt_device_close(hw_dev);
+    return RT_EOK;
+}
+
+static void testcase(void)
+{
+    UTEST_UNIT_RUN(rt_perf_all_test);
+}
+
+UTEST_TC_EXPORT(testcase, "testcase.pref.all", utest_tc_init, utest_tc_cleanup, 10);
+

+ 55 - 0
examples/utest/testcases/perf/perf_tc.h

@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2006-2025, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2025-07-03     rcitach      test case
+ */
+
+#ifndef PERF_TC_H__
+#define PERF_TC_H__
+
+#include <rtthread.h>
+#include <rtdevice.h>
+#include <rtservice.h>
+#include <rttypes.h>
+
+#define THREAD_STACK_SIZE       2048
+#define THREAD_PRIORITY         10
+#define THREAD_TIMESLICE        5
+typedef struct rt_perf
+{
+    char name[64];
+    volatile rt_uint32_t begin_time;
+    volatile rt_uint32_t real_time;
+    volatile rt_uint32_t tot_time;
+    volatile rt_uint32_t max_time;
+    volatile rt_uint32_t min_time;
+    volatile rt_uint32_t count;
+    volatile double avg_time;
+    volatile rt_uint32_t tmp_time;  /* Temporary data */
+    rt_mutex_t lock;
+    void (*local_modify)(struct rt_perf *perf);
+    rt_bool_t dump_head;
+} rt_perf_t;
+
+void rt_perf_start_impl(rt_perf_t *perf, rt_hwtimerval_t *timeout);
+void rt_perf_stop(rt_perf_t *perf);
+void rt_perf_dump( rt_perf_t *perf);
+
+static inline void rt_perf_start(rt_perf_t *perf)
+{
+    rt_perf_start_impl(perf, RT_NULL);
+}
+
+rt_err_t context_switch_test(rt_perf_t *perf);
+rt_err_t rt_perf_irq_latency(rt_perf_t *perf);
+rt_err_t rt_perf_thread_sem(rt_perf_t *perf);
+rt_err_t rt_perf_thread_event(rt_perf_t *perf);
+rt_err_t rt_perf_thread_mq(rt_perf_t *perf);
+rt_err_t rt_perf_thread_mbox(rt_perf_t *perf);
+
+#endif /* PERF_TC_H__ */
+

+ 112 - 0
examples/utest/testcases/perf/thread_event_tc.c

@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2006-2025, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2025-07-03     rcitach      test case for event
+ */
+
+#include <rtthread.h>
+#include <rthw.h>
+#include <rtdevice.h>
+#include <utest.h>
+#include <utest_assert.h>
+#include <perf_tc.h>
+
+#define EVENT_FLAG          (1 << 0)
+static rt_event_t perf_thread_event = RT_NULL;
+static rt_sem_t sem1 = RT_NULL;
+static rt_sem_t complete_sem = RT_NULL;
+
+static void perf_thread_event1(void *parameter)
+{
+    rt_err_t ret = RT_EOK;
+    rt_uint32_t recv = 0;
+    rt_perf_t *perf = (rt_perf_t *)parameter;
+    while (1)
+    {
+        ret = rt_event_recv(perf_thread_event, EVENT_FLAG,
+                           (RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR),
+                           RT_WAITING_FOREVER, &recv);
+        rt_perf_stop(perf);
+        if (ret != RT_EOK)
+        {
+            LOG_E("event recv error!");
+            rt_event_delete(perf_thread_event);
+            return;
+        }
+
+        if (perf->count >= UTEST_SYS_PERF_TC_COUNT)
+        {
+            rt_event_delete(perf_thread_event);
+            rt_sem_delete(sem1);
+            return;
+        }
+        rt_sem_release(sem1);
+    }
+}
+
+static void perf_thread_event2(void *parameter)
+{
+    rt_perf_t *perf = (rt_perf_t *)parameter;
+    while (1)
+    {
+        if (perf->count >= UTEST_SYS_PERF_TC_COUNT)
+        {
+            rt_sem_release(complete_sem);
+            return;
+        }
+        rt_sem_take(sem1, RT_WAITING_FOREVER);
+        rt_perf_start(perf);
+        rt_event_send(perf_thread_event, EVENT_FLAG);
+    }
+}
+
+rt_err_t rt_perf_thread_event(rt_perf_t *perf)
+{
+    rt_thread_t thread1 = RT_NULL;
+    rt_thread_t thread2 = RT_NULL;
+
+# if __STDC_VERSION__ >= 199901L
+    rt_strcpy(perf->name,__func__);
+#else
+    rt_strcpy(perf->name,"rt_perf_thread_event");
+#endif
+
+    perf_thread_event = rt_event_create("perf_thread_event", RT_IPC_FLAG_PRIO);
+    if (perf_thread_event == RT_NULL)
+    {
+        LOG_E("perf_thread_event create failed.");
+        return -RT_ERROR;
+    }
+
+    sem1 = rt_sem_create("sem1", 1, RT_IPC_FLAG_FIFO);
+    complete_sem = rt_sem_create("complete", 0, RT_IPC_FLAG_FIFO);
+
+    thread1 = rt_thread_create("perf_thread_event1", perf_thread_event1, perf,
+                                THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE);
+    if (thread1 == RT_NULL)
+    {
+        LOG_E("perf_thread_event1 create failed.");
+        return -RT_ERROR;
+    }
+
+    thread2 = rt_thread_create("perf_thread_event2", perf_thread_event2, perf,
+                                THREAD_STACK_SIZE, THREAD_PRIORITY + 1, THREAD_TIMESLICE);
+    if (thread2 == RT_NULL)
+    {
+        LOG_E("perf_thread_event2 create failed.");
+        return -RT_ERROR;
+    }
+
+    rt_thread_startup(thread1);
+    rt_thread_startup(thread2);
+
+    rt_sem_take(complete_sem, RT_WAITING_FOREVER);
+    rt_perf_dump(perf);
+    rt_sem_delete(complete_sem);
+    return RT_EOK;
+}
+

+ 110 - 0
examples/utest/testcases/perf/thread_mbox_tc.c

@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2006-2025, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2025-07-03     rcitach      test case for mbox
+ */
+
+#include <rtthread.h>
+#include <rthw.h>
+#include <rtdevice.h>
+#include <utest.h>
+#include <utest_assert.h>
+#include <perf_tc.h>
+
+static rt_sem_t sem1 = RT_NULL;
+static rt_sem_t complete_sem = RT_NULL;
+static rt_mailbox_t perf_thread_mbox = RT_NULL;
+
+static void perf_thread_mbox1(void *parameter)
+{
+    rt_ubase_t recv = 0;
+    rt_err_t ret = RT_EOK;
+    rt_perf_t *perf = (rt_perf_t *)parameter;
+    while (1)
+    {
+        ret = rt_mb_recv(perf_thread_mbox, &recv, RT_WAITING_FOREVER);
+        rt_perf_stop(perf);
+        if (ret != RT_EOK)
+        {
+            LOG_E("mbox recv value error!\n");
+            rt_mb_delete(perf_thread_mbox);
+            return;
+        }
+
+        if (perf->count >= UTEST_SYS_PERF_TC_COUNT)
+        {
+            rt_mb_delete(perf_thread_mbox);
+            rt_sem_delete(sem1);
+            return;
+        }
+        rt_sem_release(sem1);
+    }
+}
+
+static void perf_thread_mbox2(void *parameter)
+{
+    rt_perf_t *perf = (rt_perf_t *)parameter;
+    rt_err_t ret = RT_EOK;
+    while (1)
+    {
+        if (perf->count >= UTEST_SYS_PERF_TC_COUNT)
+        {
+            rt_sem_release(complete_sem);
+            return;
+        }
+        rt_sem_take(sem1, RT_WAITING_FOREVER);
+        rt_perf_start(perf);
+        rt_mb_send(perf_thread_mbox, 1);
+    }
+}
+
+rt_err_t rt_perf_thread_mbox(rt_perf_t *perf)
+{
+    rt_thread_t thread1 = RT_NULL;
+    rt_thread_t thread2 = RT_NULL;
+
+# if __STDC_VERSION__ >= 199901L
+    rt_strcpy(perf->name,__func__);
+#else
+    rt_strcpy(perf->name,"rt_perf_thread_mbox");
+#endif
+
+    perf_thread_mbox = rt_mb_create("perf_thread_mbox", 1, RT_IPC_FLAG_PRIO);
+    if (perf_thread_mbox == RT_NULL)
+    {
+        LOG_E("perf thread mbox create failed.");
+        return -RT_ERROR;
+    }
+
+    sem1 = rt_sem_create("sem1", 1, RT_IPC_FLAG_FIFO);
+    complete_sem = rt_sem_create("complete", 0, RT_IPC_FLAG_FIFO);
+
+    thread1 = rt_thread_create("perf_thread_mbox1", perf_thread_mbox1, perf,
+                                THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE);
+    if (thread1 == RT_NULL)
+    {
+        LOG_E("perf_thread_mbox1 create failed.");
+        return -RT_ERROR;
+    }
+
+    thread2 = rt_thread_create("perf_thread_mbox2", perf_thread_mbox2, perf,
+                                THREAD_STACK_SIZE, THREAD_PRIORITY + 1, THREAD_TIMESLICE);
+    if (thread2 == RT_NULL)
+    {
+        LOG_E("perf_thread_mbox2 create failed.");
+        return -RT_ERROR;
+    }
+
+    rt_thread_startup(thread1);
+    rt_thread_startup(thread2);
+
+    rt_sem_take(complete_sem, RT_WAITING_FOREVER);
+    rt_perf_dump(perf);
+    rt_sem_delete(complete_sem);
+    return RT_EOK;
+}
+

+ 109 - 0
examples/utest/testcases/perf/thread_mq_tc.c

@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2006-2025, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2025-07-03     rcitach      test case for messagequeue
+ */
+
+#include <rtthread.h>
+#include <rthw.h>
+#include <rtdevice.h>
+#include <utest.h>
+#include <utest_assert.h>
+#include <perf_tc.h>
+
+static rt_sem_t sem1 = RT_NULL;
+static rt_sem_t complete_sem = RT_NULL;
+static rt_mq_t perf_thread_mq = RT_NULL;
+
+static void perf_thread_mq1(void *parameter)
+{
+    char recv = 0;
+    rt_perf_t *perf = (rt_perf_t *)parameter;
+    while (1)
+    {
+        rt_mq_recv(perf_thread_mq, &recv, 1, RT_WAITING_FOREVER);
+        rt_perf_stop(perf);
+        if (recv != 'A')
+        {
+            LOG_E("mq recv value error!");
+            rt_mq_delete(perf_thread_mq);
+            return;
+        }
+
+        if (perf->count >= UTEST_SYS_PERF_TC_COUNT)
+        {
+            rt_mq_delete(perf_thread_mq);
+            rt_sem_delete(sem1);
+            return;
+        }
+        rt_sem_release(sem1);
+    }
+}
+
+static void perf_thread_mq2(void *parameter)
+{
+    rt_perf_t *perf = (rt_perf_t *)parameter;
+    char send = 'A';
+    while (1)
+    {
+        if (perf->count >= UTEST_SYS_PERF_TC_COUNT)
+        {
+            rt_sem_release(complete_sem);
+            return;
+        }
+        rt_sem_take(sem1, RT_WAITING_FOREVER);
+        rt_perf_start(perf);
+        rt_mq_send(perf_thread_mq, &send, 1);
+    }
+}
+
+rt_err_t rt_perf_thread_mq(rt_perf_t *perf)
+{
+    rt_thread_t thread1 = RT_NULL;
+    rt_thread_t thread2 = RT_NULL;
+
+# if __STDC_VERSION__ >= 199901L
+    rt_strcpy(perf->name,__func__);
+#else
+    rt_strcpy(perf->name,"rt_perf_thread_mq");
+#endif
+
+    perf_thread_mq = rt_mq_create("perf_thread_mq", 1, 1, RT_IPC_FLAG_PRIO);
+    if (perf_thread_mq == RT_NULL)
+    {
+        LOG_E("perf_thread_mq create failed.");
+        return -RT_ERROR;
+    }
+
+    sem1 = rt_sem_create("sem1", 1, RT_IPC_FLAG_FIFO);
+    complete_sem = rt_sem_create("complete", 0, RT_IPC_FLAG_FIFO);
+
+    thread1 = rt_thread_create("perf_thread_mq1", perf_thread_mq1, perf,
+                                THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE);
+    if (thread1 == RT_NULL)
+    {
+        LOG_E("perf_thread_mq1 create failed.");
+        return -RT_ERROR;
+    }
+
+    thread2 = rt_thread_create("perf_thread_mq2", perf_thread_mq2, perf,
+                                THREAD_STACK_SIZE, THREAD_PRIORITY + 1, THREAD_TIMESLICE);
+    if (thread2 == RT_NULL)
+    {
+        LOG_E("perf_thread_mq2 create failed.");
+        return -RT_ERROR;
+    }
+
+    rt_thread_startup(thread1);
+    rt_thread_startup(thread2);
+
+    rt_sem_take(complete_sem, RT_WAITING_FOREVER);
+    rt_perf_dump(perf);
+    rt_sem_delete(complete_sem);
+    return RT_EOK;
+}
+

+ 121 - 0
examples/utest/testcases/perf/thread_sem_tc.c

@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2006-2025, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2025-07-03     rcitach      test case for semaphore
+ */
+
+#include <rtthread.h>
+#include <rthw.h>
+#include <rtdevice.h>
+#include <utest.h>
+#include <utest_assert.h>
+#include <perf_tc.h>
+
+static rt_sem_t perf_thread_sem = RT_NULL;
+static rt_event_t perf_thread_event = RT_NULL;
+static rt_sem_t complete_sem = RT_NULL;
+
+#define EVENT_FLAG          (1 << 0)
+static void perf_thread_sem1(void *parameter)
+{
+    rt_err_t ret = RT_EOK;
+    rt_perf_t *perf = (rt_perf_t *)parameter;
+    rt_event_send(perf_thread_event, EVENT_FLAG);
+    while (1)
+    {
+        ret = rt_sem_take(perf_thread_sem, RT_WAITING_FOREVER);
+        rt_perf_stop(perf);
+        if(ret != RT_EOK)
+        {
+            LOG_E("Sem recv error!");
+            rt_sem_delete(perf_thread_sem);
+            return;
+        }
+
+        if (perf->count >= UTEST_SYS_PERF_TC_COUNT)
+        {
+            rt_event_delete(perf_thread_event);
+            rt_sem_delete(perf_thread_sem);
+            return;
+        }
+        rt_event_send(perf_thread_event, EVENT_FLAG);
+    }
+}
+
+static void perf_thread_sem2(void *parameter)
+{
+    rt_err_t ret = RT_EOK;
+    rt_perf_t *perf = (rt_perf_t *)parameter;
+    rt_uint32_t recv = 0;
+    while (1)
+    {
+        if (perf->count >= UTEST_SYS_PERF_TC_COUNT)
+        {
+            rt_sem_release(complete_sem);
+            return;
+        }
+        ret = rt_event_recv(perf_thread_event, EVENT_FLAG,
+                (RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR),
+                RT_WAITING_FOREVER, &recv);
+        if(ret != RT_EOK)
+        {
+            LOG_E("Event reception failed");
+            rt_event_delete(perf_thread_event);
+            rt_sem_release(complete_sem);
+            return;
+        }
+        rt_perf_start(perf);
+        rt_sem_release(perf_thread_sem);
+    }
+}
+
+rt_err_t rt_perf_thread_sem(rt_perf_t *perf)
+{
+    rt_thread_t thread1 = RT_NULL;
+    rt_thread_t thread2 = RT_NULL;
+
+# if __STDC_VERSION__ >= 199901L
+    rt_strcpy(perf->name,__func__);
+#else
+    rt_strcpy(perf->name,"rt_perf_thread_sem");
+#endif
+
+    perf_thread_sem = rt_sem_create("perf_thread_sem", 0, RT_IPC_FLAG_FIFO);
+    if (perf_thread_sem == RT_NULL)
+    {
+        LOG_E("perf_thread_sem create failed.");
+        return -RT_ERROR;
+    }
+
+    perf_thread_event = rt_event_create("perf_thread_event", RT_IPC_FLAG_PRIO);
+    complete_sem = rt_sem_create("complete", 0, RT_IPC_FLAG_FIFO);
+
+    thread1 = rt_thread_create("perf_thread_sem1", perf_thread_sem1, perf,
+                                THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE);
+    if (thread1 == RT_NULL)
+    {
+        LOG_E("perf_thread_sem1 create failed.");
+        return -RT_ERROR;
+    }
+
+    thread2 = rt_thread_create("perf_thread_sem2", perf_thread_sem2, perf,
+                                THREAD_STACK_SIZE, THREAD_PRIORITY + 1, THREAD_TIMESLICE);
+    if (thread2 == RT_NULL)
+    {
+        LOG_E("perf_thread_sem2 create failed.");
+        return -RT_ERROR;
+    }
+
+    rt_thread_startup(thread1);
+    rt_thread_startup(thread2);
+
+    rt_sem_take(complete_sem, RT_WAITING_FOREVER);
+    rt_perf_dump(perf);
+    rt_sem_delete(complete_sem);
+    return RT_EOK;
+}
+