1 /**************************************************************************/
2 /* */
3 /* Copyright (c) Microsoft Corporation. All rights reserved. */
4 /* */
5 /* This software is licensed under the Microsoft Software License */
6 /* Terms for Microsoft Azure RTOS. Full text of the license can be */
7 /* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
8 /* and in the root directory of this software. */
9 /* */
10 /**************************************************************************/
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** Thread-Metric Component */
16 /** */
17 /** Preemptive Scheduling Test */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22 /**************************************************************************/
23 /* */
24 /* FUNCTION RELEASE */
25 /* */
26 /* tm_preemptive_scheduling_test PORTABLE C */
27 /* 6.1.7 */
28 /* AUTHOR */
29 /* */
30 /* William E. Lamie, Microsoft Corporation */
31 /* */
32 /* DESCRIPTION */
33 /* */
34 /* This file defines the preemptive scheduling test. */
35 /* */
36 /* RELEASE HISTORY */
37 /* */
38 /* DATE NAME DESCRIPTION */
39 /* */
40 /* 10-15-2021 William E. Lamie Initial Version 6.1.7 */
41 /* */
42 /**************************************************************************/
43 #include "tm_api.h"
44
45
46 /* Define the counters used in the demo application... */
47
48 unsigned long tm_preemptive_thread_0_counter;
49 unsigned long tm_preemptive_thread_1_counter;
50 unsigned long tm_preemptive_thread_2_counter;
51 unsigned long tm_preemptive_thread_3_counter;
52 unsigned long tm_preemptive_thread_4_counter;
53
54
55 /* Define the test thread prototypes. */
56
57 void tm_preemptive_thread_0_entry(void);
58 void tm_preemptive_thread_1_entry(void);
59 void tm_preemptive_thread_2_entry(void);
60 void tm_preemptive_thread_3_entry(void);
61 void tm_preemptive_thread_4_entry(void);
62
63
64 /* Define the reporting thread prototype. */
65
66 void tm_preemptive_thread_report(void);
67
68
69 /* Define the initialization prototype. */
70
71 void tm_preemptive_scheduling_initialize(void);
72
73
74 /* Define main entry point. */
75
tm_main()76 void tm_main()
77 {
78
79 /* Initialize the test. */
80 tm_initialize(tm_preemptive_scheduling_initialize);
81 }
82
83
84 /* Define the preemptive scheduling test initialization. */
85
tm_preemptive_scheduling_initialize(void)86 void tm_preemptive_scheduling_initialize(void)
87 {
88
89 /* Create thread 0 at priority 10. */
90 tm_thread_create(0, 10, tm_preemptive_thread_0_entry);
91
92 /* Create thread 1 at priority 9. */
93 tm_thread_create(1, 9, tm_preemptive_thread_1_entry);
94
95 /* Create thread 2 at priority 8. */
96 tm_thread_create(2, 8, tm_preemptive_thread_2_entry);
97
98 /* Create thread 3 at priority 7. */
99 tm_thread_create(3, 7, tm_preemptive_thread_3_entry);
100
101 /* Create thread 4 at priority 6. */
102 tm_thread_create(4, 6, tm_preemptive_thread_4_entry);
103
104 /* Resume just thread 0. */
105 tm_thread_resume(0);
106
107 /* Create the reporting thread. It will preempt the other
108 threads and print out the test results. */
109 tm_thread_create(5, 2, tm_preemptive_thread_report);
110 tm_thread_resume(5);
111 }
112
113
114 /* Define the first preemptive thread. */
tm_preemptive_thread_0_entry(void)115 void tm_preemptive_thread_0_entry(void)
116 {
117
118 while(1)
119 {
120
121 /* Resume thread 1. */
122 tm_thread_resume(1);
123
124 /* We won't get back here until threads 1, 2, 3, and 4 all execute and
125 self-suspend. */
126
127 /* Increment this thread's counter. */
128 tm_preemptive_thread_0_counter++;
129 }
130 }
131
132 /* Define the second preemptive thread. */
tm_preemptive_thread_1_entry(void)133 void tm_preemptive_thread_1_entry(void)
134 {
135
136 while(1)
137 {
138
139 /* Resume thread 2. */
140 tm_thread_resume(2);
141
142 /* We won't get back here until threads 2, 3, and 4 all execute and
143 self-suspend. */
144
145 /* Increment this thread's counter. */
146 tm_preemptive_thread_1_counter++;
147
148 /* Suspend self! */
149 tm_thread_suspend(1);
150 }
151 }
152
153 /* Define the third preemptive thread. */
tm_preemptive_thread_2_entry(void)154 void tm_preemptive_thread_2_entry(void)
155 {
156
157 while(1)
158 {
159
160 /* Resume thread 3. */
161 tm_thread_resume(3);
162
163 /* We won't get back here until threads 3 and 4 execute and
164 self-suspend. */
165
166 /* Increment this thread's counter. */
167 tm_preemptive_thread_2_counter++;
168
169 /* Suspend self! */
170 tm_thread_suspend(2);
171 }
172 }
173
174
175 /* Define the fourth preemptive thread. */
tm_preemptive_thread_3_entry(void)176 void tm_preemptive_thread_3_entry(void)
177 {
178
179 while(1)
180 {
181
182 /* Resume thread 4. */
183 tm_thread_resume(4);
184
185 /* We won't get back here until thread 4 executes and
186 self-suspends. */
187
188 /* Increment this thread's counter. */
189 tm_preemptive_thread_3_counter++;
190
191 /* Suspend self! */
192 tm_thread_suspend(3);
193 }
194 }
195
196
197 /* Define the fifth preemptive thread. */
tm_preemptive_thread_4_entry(void)198 void tm_preemptive_thread_4_entry(void)
199 {
200
201 while(1)
202 {
203
204 /* Increment this thread's counter. */
205 tm_preemptive_thread_4_counter++;
206
207 /* Self suspend thread 4. */
208 tm_thread_suspend(4);
209 }
210 }
211
212
213 /* Define the preemptive test reporting thread. */
tm_preemptive_thread_report(void)214 void tm_preemptive_thread_report(void)
215 {
216
217 unsigned long total;
218 unsigned long relative_time;
219 unsigned long last_total;
220 unsigned long average;
221
222
223 /* Initialize the last total. */
224 last_total = 0;
225
226 /* Initialize the relative time. */
227 relative_time = 0;
228
229 while(1)
230 {
231
232 /* Sleep to allow the test to run. */
233 tm_thread_sleep(TM_TEST_DURATION);
234
235 /* Increment the relative time. */
236 relative_time = relative_time + TM_TEST_DURATION;
237
238 /* Print results to the stdio window. */
239 printf("**** Thread-Metric Preemptive Scheduling Test **** Relative Time: %lu\n", relative_time);
240
241 /* Calculate the total of all the counters. */
242 total = tm_preemptive_thread_0_counter + tm_preemptive_thread_1_counter + tm_preemptive_thread_2_counter
243 + tm_preemptive_thread_3_counter + tm_preemptive_thread_4_counter;
244
245 /* Calculate the average of all the counters. */
246 average = total/5;
247
248 /* See if there are any errors. */
249 if ((tm_preemptive_thread_0_counter < (average - 1)) ||
250 (tm_preemptive_thread_0_counter > (average + 1)) ||
251 (tm_preemptive_thread_1_counter < (average - 1)) ||
252 (tm_preemptive_thread_1_counter > (average + 1)) ||
253 (tm_preemptive_thread_2_counter < (average - 1)) ||
254 (tm_preemptive_thread_2_counter > (average + 1)) ||
255 (tm_preemptive_thread_3_counter < (average - 1)) ||
256 (tm_preemptive_thread_3_counter > (average + 1)) ||
257 (tm_preemptive_thread_4_counter < (average - 1)) ||
258 (tm_preemptive_thread_4_counter > (average + 1)))
259 {
260
261 printf("ERROR: Invalid counter value(s). Preemptive counters should not be more that 1 different than the average!\n");
262 }
263
264 /* Show the time period total. */
265 printf("Time Period Total: %lu\n\n", total - last_total);
266
267 /* Save the last total. */
268 last_total = total;
269 }
270 }
271