summaryrefslogtreecommitdiff
path: root/src/utest/perf/thread_event_tc.c
blob: 016c4b831cf14a3ea2521ccc2bdcccbe44897602 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/*
 * 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
 * 2025-11-30     westcity-YOLO  Add standardized utest documentation block
 */

/**
 * Test Case Name: Kernel Core Event Performance Test
 *
 * Test Objectives:
 * - Measures event object synchronization performance
 * - Validates event flag handling (OR/CLEAR) and priority
 * - Provides latency metrics for event-based thread communication
 *
 * Test Scenarios:
 * - **Event Flag Handling**: EVENT_FLAG with OR/CLEAR operation
 * - **Priority Synchronization**: Higher-priority thread (THREAD_PRIORITY+1) response
 * - **Stress Test**: Repeated event signaling (RT_UTEST_SYS_PERF_TC_COUNT times)
 * - **Thread Coordination**: Two threads exchanging events via semaphores
 *
 * Verification Metrics:
 * - Latency < 50μs (event recv/send cycle)
 * - 0 errors in event flag handling
 * - Consistent results across test cycles
 * - No memory leaks during test
 *
 * Dependencies:
 * - RT_USING_EVENT must be enabled
 * - RT_USING_UTEST framework
 * - Hardware timer support (for high-precision timing)
 *
 * Expected Results:
 * [  PASSED  ] [ result   ] testcase (core.event)
 * - Structured performance data table (Min/Max/Avg latency)
 * - Final line: "=== Event Performance Test Results End ==="
 * - Executable via: `utest_run core.event` in msh
 */

#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 >= RT_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 >= RT_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;
}