1313#include <rtdevice.h>
1414#include <utest.h>
1515#include <utest_assert.h>
16+ #include <perf_tc.h>
17+
18+ typedef struct rt_perf_array
19+ {
20+ rt_uint32_t count ;
21+ rt_uint32_t * raw_times ;
22+ rt_uint32_t * local_times ;
23+ rt_uint32_t * net_times ;
24+ } rt_perf_array_t ;
1625
1726static 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
27+ static rt_sem_t complete_sem = RT_NULL ;
28+
29+ void rt_perf_array_destroy (rt_perf_array_t * arr )
30+ {
31+ if (arr )
32+ {
33+ if (arr -> raw_times ) rt_free (arr -> raw_times );
34+ if (arr -> local_times ) rt_free (arr -> local_times );
35+ if (arr -> net_times ) rt_free (arr -> net_times );
36+ rt_free (arr );
37+ }
38+ }
2239
23- #define SWITCH_COUNT 1000 /* Number of context switches */
40+ rt_perf_array_t * rt_perf_array_create (rt_uint32_t count )
41+ {
42+ rt_perf_array_t * arr = rt_calloc (1 , sizeof (rt_perf_array_t ));
43+ if (!arr )
44+ return RT_NULL ;
45+
46+ arr -> count = count ;
47+ arr -> raw_times = rt_calloc (count , sizeof (rt_uint32_t ));
48+ arr -> local_times = rt_calloc (count , sizeof (rt_uint32_t ));
49+ arr -> net_times = rt_calloc (count , sizeof (rt_uint32_t ));
2450
25- #ifdef USING_HWTIME_AS_TIME_REF
26- static rt_device_t hw_dev = RT_NULL ;
51+ if (!arr -> raw_times || !arr -> local_times || !arr -> net_times )
52+ {
53+ rt_perf_array_destroy (arr );
54+ return RT_NULL ;
55+ }
2756
28- static rt_size_t get_timer_us (rt_hwtimerval_t * timeout_s )
57+ return arr ;
58+ }
59+
60+ void rt_perf_array_compute (rt_perf_array_t * arr , rt_perf_t * perf )
2961{
30- if (hw_dev )
31- return rt_device_read (hw_dev , 0 , timeout_s , sizeof (rt_hwtimerval_t ));
32- return 0 ;
62+ rt_uint32_t i ;
63+ rt_uint32_t tot_time = 0 ;
64+ rt_uint32_t max_time = 0 ;
65+ rt_uint32_t min_time = 0xFFFFFFFF ;
66+
67+ for (i = 0 ; i < arr -> count ; i ++ )
68+ {
69+ rt_uint32_t net = (arr -> raw_times [i ] > arr -> local_times [i ]) ?
70+ (arr -> raw_times [i ] - arr -> local_times [i ]) : 0 ;
71+ arr -> net_times [i ] = net ;
72+
73+ tot_time += net ;
74+ if (net > max_time ) max_time = net ;
75+ if (net < min_time ) min_time = net ;
76+ }
77+
78+ perf -> count = arr -> count ;
79+ perf -> tot_time = tot_time ;
80+ perf -> max_time = max_time ;
81+ perf -> min_time = min_time ;
3382}
34- #endif
3583
36- static void thread1_entry (void * parameter )
84+ static void perf_thread_event1 (void * parameter )
3785{
3886 while (1 )
3987 {
@@ -42,136 +90,83 @@ static void thread1_entry(void *parameter)
4290 }
4391}
4492
45- static void thread2_entry (void * parameter )
93+ static void perf_thread_event2 (void * parameter )
4694{
47- rt_uint32_t total_time = 0 ;
48- rt_uint32_t sem_op_time = 0 ;
95+ rt_perf_t * perf = ( rt_perf_t * ) parameter ;
96+ rt_perf_t * perf_local = ( rt_perf_t * ) rt_calloc ( 1 , sizeof ( rt_perf_t )) ;
4997 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 );
6298
63- ret += get_timer_us ( & start_time );
64- for ( i = 0 ; i < SWITCH_COUNT ; i ++ )
99+ rt_perf_array_t * perf_arr = rt_perf_array_create ( UTEST_SYS_PERF_TC_COUNT );
100+ if (! perf_arr )
65101 {
66- rt_sem_take ( sem2 , RT_WAITING_FOREVER );
67- rt_sem_release ( sem1 ) ;
102+ LOG_E ( "Failed to allocate performance arrays" );
103+ return ;
68104 }
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 ++ )
105+
106+ for (i = 0 ; i < UTEST_SYS_PERF_TC_COUNT ; i ++ )
76107 {
108+ rt_perf_start (perf_local );
77109 rt_sem_take (sem2 , RT_WAITING_FOREVER );
78110 rt_sem_release (sem2 );
111+ rt_perf_stop (perf_local );
112+ perf_arr -> local_times [i ] = perf_local -> real_time ;
79113 }
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 );
83114
84- start_time = rt_tick_get ();
85- for (i = 0 ; i < SWITCH_COUNT ; i ++ )
115+ for (i = 0 ; i < UTEST_SYS_PERF_TC_COUNT ; i ++ )
86116 {
87- rt_sem_take (sem2 , RT_WAITING_FOREVER );
88- rt_sem_release (sem1 );
117+ rt_perf_start (perf );
118+ rt_sem_take (sem2 , RT_WAITING_FOREVER );
119+ rt_sem_release (sem1 );
120+ rt_perf_stop (perf );
121+ perf_arr -> raw_times [i ] = perf -> real_time ;
89122 }
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 */
98123
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 );
124+ rt_perf_array_compute ( perf_arr , perf );
125+ rt_perf_array_destroy ( perf_arr );
126+ rt_free ( perf_local );
127+ rt_sem_release ( complete_sem );
103128}
104129
105- void context_switch_test (void )
130+ rt_err_t context_switch_test (rt_perf_t * perf )
106131{
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- }
132+ rt_thread_t thread1 = RT_NULL ;
133+ rt_thread_t thread2 = RT_NULL ;
112134
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- }
135+ # if __STDC_VERSION__ >= 199901L
136+ rt_strcpy (perf -> name ,__func__ );
137+ #else
138+ rt_strcpy (perf -> name ,"context_switch_test" );
139+ #endif
119140
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 ;
141+ sem1 = rt_sem_create ("sem1" , 1 , RT_IPC_FLAG_FIFO );
142+ sem2 = rt_sem_create ("sem2" , 0 , RT_IPC_FLAG_FIFO );
143+ complete_sem = rt_sem_create ("complete_sem" , 0 , RT_IPC_FLAG_FIFO );
125144
126- hw_dev = rt_device_find (UTEST_HWTIMER_DEV_NAME );
127- if (hw_dev == RT_NULL )
145+ thread1 = rt_thread_create ("perf_thread_event1" , perf_thread_event1 , perf ,
146+ THREAD_STACK_SIZE , THREAD_PRIORITY , THREAD_TIMESLICE );
147+ if (thread1 == RT_NULL )
128148 {
129- ret = RT_ERROR ;
130- LOG_E ("hwtimer sample run failed! can't find %s device!" , UTEST_HWTIMER_DEV_NAME );
131- return ret ;
149+ LOG_E ("perf_thread_event1 create failed." );
150+ return - RT_ERROR ;
132151 }
133152
134- ret = rt_device_open (hw_dev , RT_DEVICE_OFLAG_RDWR );
135- if (ret != RT_EOK )
153+ thread2 = rt_thread_create ("perf_thread_event2" , perf_thread_event2 , perf ,
154+ THREAD_STACK_SIZE , THREAD_PRIORITY + 1 , THREAD_TIMESLICE );
155+ if (thread2 == RT_NULL )
136156 {
137- LOG_E ("open %s device failed!" , UTEST_HWTIMER_DEV_NAME );
138- return ret ;
157+ LOG_E ("perf_thread_event2 create failed." );
158+ return - RT_ERROR ;
139159 }
140160
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- }
161+ rt_thread_startup (thread1 );
162+ rt_thread_startup (thread2 );
160163
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- }
164+ rt_sem_take (complete_sem , RT_WAITING_FOREVER );
165+ rt_thread_delete (thread1 );
166+ rt_sem_delete (complete_sem );
167+ rt_sem_delete (sem1 );
168+ rt_sem_delete (sem2 );
171169
172- static void testcase (void )
173- {
174- UTEST_UNIT_RUN (context_switch_test );
170+ return RT_EOK ;
175171}
176172
177- UTEST_TC_EXPORT (testcase , "testcase.pref.context" , utest_tc_init , utest_tc_cleanup , 10 );
0 commit comments