Skip to content

Commit e05d1db

Browse files
committed
add context switch test code
1 parent ca09785 commit e05d1db

File tree

1 file changed

+177
-0
lines changed

1 file changed

+177
-0
lines changed
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
/*
2+
* Copyright (c) 2006-2025, RT-Thread Development Team
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*
6+
* Change Logs:
7+
* Date Author Notes
8+
* 2025-07-03 rcitach test case for context_switch
9+
*/
10+
11+
#include <rtthread.h>
12+
#include <rthw.h>
13+
#include <rtdevice.h>
14+
#include <utest.h>
15+
#include <utest_assert.h>
16+
17+
static rt_sem_t sem1, sem2;
18+
static rt_thread_t thread1, thread2;
19+
#define THREAD_STACK_SIZE 1024
20+
#define THREAD_PRIORITY 10
21+
#define THREAD_TIMESLICE 5
22+
23+
#define SWITCH_COUNT 1000 /* Number of context switches */
24+
25+
#ifdef USING_HWTIME_AS_TIME_REF
26+
static rt_device_t hw_dev = RT_NULL;
27+
28+
static rt_size_t get_timer_us(rt_hwtimerval_t *timeout_s)
29+
{
30+
if (hw_dev)
31+
return rt_device_read(hw_dev, 0, timeout_s, sizeof(rt_hwtimerval_t));
32+
return 0;
33+
}
34+
#endif
35+
36+
static void thread1_entry(void *parameter)
37+
{
38+
while (1)
39+
{
40+
rt_sem_take(sem1, RT_WAITING_FOREVER);
41+
rt_sem_release(sem2);
42+
}
43+
}
44+
45+
static void thread2_entry(void *parameter)
46+
{
47+
rt_uint32_t total_time = 0;
48+
rt_uint32_t sem_op_time = 0;
49+
rt_uint32_t i;
50+
#ifdef USING_HWTIME_AS_TIME_REF
51+
rt_hwtimerval_t start_time, end_time;
52+
rt_uint16_t ret;
53+
/* Getting Signal Time */
54+
ret = get_timer_us(&start_time);
55+
for (i = 0; i < SWITCH_COUNT; i++)
56+
{
57+
rt_sem_take(sem2, RT_WAITING_FOREVER);
58+
rt_sem_release(sem2);
59+
}
60+
ret +=get_timer_us(&end_time);
61+
sem_op_time = (end_time.sec - start_time.sec) * 1000000u + (end_time.usec - start_time.usec);
62+
63+
ret += get_timer_us(&start_time);
64+
for (i = 0; i < SWITCH_COUNT; i++)
65+
{
66+
rt_sem_take(sem2, RT_WAITING_FOREVER);
67+
rt_sem_release(sem1);
68+
}
69+
ret +=get_timer_us(&end_time);
70+
total_time = (end_time.sec - start_time.sec) * 1000000u + (end_time.usec - start_time.usec);
71+
#else
72+
rt_uint32_t start_time, end_time;
73+
/* Getting Signal Time */
74+
start_time = rt_tick_get();
75+
for (i = 0; i < SWITCH_COUNT; i++)
76+
{
77+
rt_sem_take(sem2, RT_WAITING_FOREVER);
78+
rt_sem_release(sem2);
79+
}
80+
end_time = rt_tick_get();
81+
sem_op_time = (end_time - start_time) / RT_TICK_PER_SECOND;
82+
sem_op_time += ((end_time - start_time) % RT_TICK_PER_SECOND) * (1000000u / RT_TICK_PER_SECOND);
83+
84+
start_time = rt_tick_get();
85+
for (i = 0; i < SWITCH_COUNT; i++)
86+
{
87+
rt_sem_take(sem2, RT_WAITING_FOREVER);
88+
rt_sem_release(sem1);
89+
}
90+
end_time = rt_tick_get();
91+
total_time = (end_time - start_time) / RT_TICK_PER_SECOND;
92+
total_time += ((end_time - start_time) % RT_TICK_PER_SECOND) * (1000000u / RT_TICK_PER_SECOND);
93+
#endif
94+
95+
rt_uint32_t single_switch_time = total_time / SWITCH_COUNT; /* Total single switching time */
96+
rt_uint32_t single_sem_op_time = sem_op_time / SWITCH_COUNT; /* Single semaphore operation time */
97+
rt_uint32_t context_switch_time = single_switch_time - single_sem_op_time; /* Context switching time */
98+
99+
LOG_I("Total time for %d switches: %d us", SWITCH_COUNT, total_time);
100+
LOG_I("Single switch time (including semaphore): %d us", single_switch_time);
101+
LOG_I("Semaphore operation time: %d us", single_sem_op_time);
102+
LOG_I("Pure context switch time: %d us", context_switch_time);
103+
}
104+
105+
void context_switch_test(void)
106+
{
107+
thread1 = rt_thread_create("thread1", thread1_entry, RT_NULL, THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE);
108+
if (thread1 != RT_NULL)
109+
{
110+
rt_thread_startup(thread1);
111+
}
112+
113+
thread2 = rt_thread_create("thread2", thread2_entry, RT_NULL, THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE);
114+
if (thread2 != RT_NULL)
115+
{
116+
rt_thread_startup(thread2);
117+
}
118+
}
119+
120+
static rt_err_t utest_tc_init(void)
121+
{
122+
int ret = RT_EOK;
123+
#ifdef USING_HWTIME_AS_TIME_REF
124+
rt_hwtimerval_t timeout_s;
125+
126+
hw_dev = rt_device_find(UTEST_HWTIMER_DEV_NAME);
127+
if (hw_dev == RT_NULL)
128+
{
129+
ret = RT_ERROR;
130+
LOG_E("hwtimer sample run failed! can't find %s device!", UTEST_HWTIMER_DEV_NAME);
131+
return ret;
132+
}
133+
134+
ret = rt_device_open(hw_dev, RT_DEVICE_OFLAG_RDWR);
135+
if (ret != RT_EOK)
136+
{
137+
LOG_E("open %s device failed!", UTEST_HWTIMER_DEV_NAME);
138+
return ret;
139+
}
140+
141+
timeout_s.sec = 5; /* s */
142+
timeout_s.usec = 0; /* us */
143+
if (rt_device_write(hw_dev, 0, &timeout_s, sizeof(rt_hwtimerval_t)) != sizeof(rt_hwtimerval_t))
144+
{
145+
ret = RT_ERROR;
146+
LOG_E("set timeout value failed");
147+
return ret;
148+
}
149+
#endif
150+
sem1 = rt_sem_create("sem1", 1, RT_IPC_FLAG_FIFO);
151+
sem2 = rt_sem_create("sem2", 0, RT_IPC_FLAG_FIFO);
152+
if (sem1 == RT_NULL || sem2 == RT_NULL)
153+
{
154+
ret = RT_ERROR;
155+
LOG_E("Semaphore create failed!");
156+
return ret;
157+
}
158+
return ret;
159+
}
160+
161+
static rt_err_t utest_tc_cleanup(void)
162+
{
163+
if (thread1) rt_thread_delete(thread1);
164+
if(sem1) rt_sem_delete(sem1);
165+
if(sem2) rt_sem_delete(sem2);
166+
#ifdef USING_HWTIME_AS_TIME_REF
167+
if(hw_dev) rt_device_close(hw_dev);
168+
#endif
169+
return RT_EOK;
170+
}
171+
172+
static void testcase(void)
173+
{
174+
UTEST_UNIT_RUN(context_switch_test);
175+
}
176+
177+
UTEST_TC_EXPORT(testcase, "testcase.pref.context", utest_tc_init, utest_tc_cleanup, 10);

0 commit comments

Comments
 (0)