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 #include <perf_tc.h>
17 
18 static rt_sem_t sem1, sem2;
19 static rt_sem_t complete_sem = RT_NULL;
20 
local_modify_time(rt_perf_t * perf)21 static void local_modify_time(rt_perf_t *perf)
22 {
23     if(perf)
24         perf->real_time = perf->real_time - perf->tmp_time;
25 }
26 
perf_thread_event1(void * parameter)27 static void perf_thread_event1(void *parameter)
28 {
29     while (1)
30     {
31         rt_sem_take(sem1, RT_WAITING_FOREVER);
32         rt_sem_release(sem2);
33     }
34 }
35 
perf_thread_event2(void * parameter)36 static void perf_thread_event2(void *parameter)
37 {
38     rt_perf_t *perf = (rt_perf_t *)parameter;
39 
40     for (rt_uint32_t i = 0; i < UTEST_SYS_PERF_TC_COUNT; i++)
41     {
42         perf->tmp_time = 0;
43         rt_perf_start(perf);
44         rt_sem_take(sem2, RT_WAITING_FOREVER);
45         rt_sem_release(sem2);
46         rt_perf_stop(perf);
47 
48         rt_mutex_take(perf->lock,RT_WAITING_FOREVER);
49         perf->count -= 1;
50         perf->tmp_time = perf->real_time;
51         rt_mutex_release(perf->lock);
52 
53         rt_perf_start(perf);
54         rt_sem_take(sem2, RT_WAITING_FOREVER);
55         rt_sem_release(sem1);
56         rt_perf_stop(perf);
57     }
58     rt_sem_release(complete_sem);
59 }
60 
context_switch_test(rt_perf_t * perf)61 rt_err_t context_switch_test(rt_perf_t *perf)
62 {
63     rt_thread_t thread1 = RT_NULL;
64     rt_thread_t thread2 = RT_NULL;
65 
66 # if __STDC_VERSION__ >= 199901L
67     rt_strcpy(perf->name,__func__);
68 #else
69     rt_strcpy(perf->name,"context_switch_test");
70 #endif
71 
72     perf->local_modify = local_modify_time;
73     sem1 = rt_sem_create("sem1", 1, RT_IPC_FLAG_FIFO);
74     sem2 = rt_sem_create("sem2", 0, RT_IPC_FLAG_FIFO);
75     complete_sem = rt_sem_create("complete_sem", 0, RT_IPC_FLAG_FIFO);
76 
77     thread1 = rt_thread_create("perf_thread_event1", perf_thread_event1, perf,
78                                 THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE);
79     if (thread1 == RT_NULL)
80     {
81         LOG_E("perf_thread_event1 create failed.");
82         return -RT_ERROR;
83     }
84 
85     thread2 = rt_thread_create("perf_thread_event2", perf_thread_event2, perf,
86                                 THREAD_STACK_SIZE, THREAD_PRIORITY + 1, THREAD_TIMESLICE);
87     if (thread2 == RT_NULL)
88     {
89         LOG_E("perf_thread_event2 create failed.");
90         return -RT_ERROR;
91     }
92 
93     rt_thread_startup(thread1);
94     rt_thread_startup(thread2);
95 
96     rt_sem_take(complete_sem, RT_WAITING_FOREVER);
97 
98     rt_perf_dump(perf);
99     rt_thread_delete(thread1);
100     rt_sem_delete(complete_sem);
101     rt_sem_delete(sem1);
102     rt_sem_delete(sem2);
103 
104     return RT_EOK;
105 }
106 
107