1 /***************************************************************************
2  * Copyright (c) 2024 Microsoft Corporation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the MIT License which is available at
6  * https://opensource.org/licenses/MIT.
7  *
8  * SPDX-License-Identifier: MIT
9  **************************************************************************/
10 
11 /**************************************************************************/
12 /**************************************************************************/
13 /**                                                                       */
14 /** Thread-Metric Component                                               */
15 /**                                                                       */
16 /**   Cooperative Scheduling Test                                         */
17 /**                                                                       */
18 /**************************************************************************/
19 /**************************************************************************/
20 
21 /**************************************************************************/
22 /*                                                                        */
23 /*  FUNCTION                                               RELEASE        */
24 /*                                                                        */
25 /*    tm_cooperative_scheduling_test                      PORTABLE C      */
26 /*                                                           6.1.7        */
27 /*  AUTHOR                                                                */
28 /*                                                                        */
29 /*    William E. Lamie, Microsoft Corporation                             */
30 /*                                                                        */
31 /*  DESCRIPTION                                                           */
32 /*                                                                        */
33 /*    This file defines the cooperative scheduling test.                  */
34 /*                                                                        */
35 /*  RELEASE HISTORY                                                       */
36 /*                                                                        */
37 /*    DATE              NAME                      DESCRIPTION             */
38 /*                                                                        */
39 /*  10-15-2021     William E. Lamie         Initial Version 6.1.7         */
40 /*                                                                        */
41 /**************************************************************************/
42 #include "tm_api.h"
43 
44 /* Define the counters used in the demo application...  */
45 
46 unsigned long tm_cooperative_thread_0_counter;
47 unsigned long tm_cooperative_thread_1_counter;
48 unsigned long tm_cooperative_thread_2_counter;
49 unsigned long tm_cooperative_thread_3_counter;
50 unsigned long tm_cooperative_thread_4_counter;
51 
52 /* Define the test thread prototypes.  */
53 
54 void tm_cooperative_thread_0_entry(void *p1, void *p2, void *p3);
55 void tm_cooperative_thread_1_entry(void *p1, void *p2, void *p3);
56 void tm_cooperative_thread_2_entry(void *p1, void *p2, void *p3);
57 void tm_cooperative_thread_3_entry(void *p1, void *p2, void *p3);
58 void tm_cooperative_thread_4_entry(void *p1, void *p2, void *p3);
59 
60 /* Define the reporting function prototype.  */
61 
62 void tm_cooperative_thread_report(void);
63 
64 /* Define the initialization prototype.  */
65 
66 void tm_cooperative_scheduling_initialize(void);
67 
68 /* Define main entry point.  */
69 
main(void)70 int main(void)
71 {
72 
73 	/* Initialize the test.  */
74 	tm_initialize(tm_cooperative_scheduling_initialize);
75 
76 	return 0;
77 }
78 
79 /* Define the cooperative scheduling test initialization.  */
80 
tm_cooperative_scheduling_initialize(void)81 void tm_cooperative_scheduling_initialize(void)
82 {
83 	int prio = CONFIG_MAIN_THREAD_PRIORITY;
84 
85 	/* Create all 5 threads at the same priority as the main thread.  */
86 	tm_thread_create(0, prio, tm_cooperative_thread_0_entry);
87 	tm_thread_create(1, prio, tm_cooperative_thread_1_entry);
88 	tm_thread_create(2, prio, tm_cooperative_thread_2_entry);
89 	tm_thread_create(3, prio, tm_cooperative_thread_3_entry);
90 	tm_thread_create(4, prio, tm_cooperative_thread_4_entry);
91 
92 	/* Resume all 5 threads.  */
93 	tm_thread_resume(0);
94 	tm_thread_resume(1);
95 	tm_thread_resume(2);
96 	tm_thread_resume(3);
97 	tm_thread_resume(4);
98 
99 	tm_cooperative_thread_report();
100 }
101 
102 /* Define the first cooperative thread.  */
tm_cooperative_thread_0_entry(void * p1,void * p2,void * p3)103 void tm_cooperative_thread_0_entry(void *p1, void *p2, void *p3)
104 {
105 	(void)p1;
106 	(void)p2;
107 	(void)p3;
108 
109 	while (1) {
110 
111 		/* Relinquish to all other threads at same priority.  */
112 		tm_thread_relinquish();
113 
114 		/* Increment this thread's counter.  */
115 		tm_cooperative_thread_0_counter++;
116 	}
117 }
118 
119 /* Define the second cooperative thread.  */
tm_cooperative_thread_1_entry(void * p1,void * p2,void * p3)120 void tm_cooperative_thread_1_entry(void *p1, void *p2, void *p3)
121 {
122 	(void)p1;
123 	(void)p2;
124 	(void)p3;
125 
126 	while (1) {
127 
128 		/* Relinquish to all other threads at same priority.  */
129 		tm_thread_relinquish();
130 
131 		/* Increment this thread's counter.  */
132 		tm_cooperative_thread_1_counter++;
133 	}
134 }
135 
136 /* Define the third cooperative thread.  */
tm_cooperative_thread_2_entry(void * p1,void * p2,void * p3)137 void tm_cooperative_thread_2_entry(void *p1, void *p2, void *p3)
138 {
139 	(void)p1;
140 	(void)p2;
141 	(void)p3;
142 
143 	while (1) {
144 
145 		/* Relinquish to all other threads at same priority.  */
146 		tm_thread_relinquish();
147 
148 		/* Increment this thread's counter.  */
149 		tm_cooperative_thread_2_counter++;
150 	}
151 }
152 
153 /* Define the fourth cooperative thread.  */
tm_cooperative_thread_3_entry(void * p1,void * p2,void * p3)154 void tm_cooperative_thread_3_entry(void *p1, void *p2, void *p3)
155 {
156 	(void)p1;
157 	(void)p2;
158 	(void)p3;
159 
160 	while (1) {
161 
162 		/* Relinquish to all other threads at same priority.  */
163 		tm_thread_relinquish();
164 
165 		/* Increment this thread's counter.  */
166 		tm_cooperative_thread_3_counter++;
167 	}
168 }
169 
170 /* Define the fifth cooperative thread.  */
tm_cooperative_thread_4_entry(void * p1,void * p2,void * p3)171 void tm_cooperative_thread_4_entry(void *p1, void *p2, void *p3)
172 {
173 	(void)p1;
174 	(void)p2;
175 	(void)p3;
176 
177 	while (1) {
178 
179 		/* Relinquish to all other threads at same priority.  */
180 		tm_thread_relinquish();
181 
182 		/* Increment this thread's counter.  */
183 		tm_cooperative_thread_4_counter++;
184 	}
185 }
186 
187 /* Define the cooperative test reporting function.  */
tm_cooperative_thread_report(void)188 void tm_cooperative_thread_report(void)
189 {
190 
191 	unsigned long total;
192 	unsigned long relative_time;
193 	unsigned long last_total;
194 	unsigned long average;
195 
196 	/* Initialize the last total.  */
197 	last_total = 0;
198 
199 	/* Initialize the relative time.  */
200 	relative_time = 0;
201 
202 	while (1) {
203 
204 		/* Sleep to allow the test to run.  */
205 		tm_thread_sleep(TM_TEST_DURATION);
206 
207 		/* Increment the relative time.  */
208 		relative_time = relative_time + TM_TEST_DURATION;
209 
210 		/* Print results to the stdio window.  */
211 		printf("**** Thread-Metric Cooperative Scheduling Test **** Relative Time: %lu\n",
212 		       relative_time);
213 
214 		/* Calculate the total of all the counters.  */
215 		total = tm_cooperative_thread_0_counter + tm_cooperative_thread_1_counter +
216 			tm_cooperative_thread_2_counter + tm_cooperative_thread_3_counter +
217 			tm_cooperative_thread_4_counter;
218 
219 		/* Calculate the average of all the counters.  */
220 		average = total / 5;
221 
222 		/* WCC - integrity check */
223 		printf("tm_cooperative_thread_0_counter: %lu\n", tm_cooperative_thread_0_counter);
224 		printf("tm_cooperative_thread_1_counter: %lu\n", tm_cooperative_thread_1_counter);
225 		printf("tm_cooperative_thread_2_counter: %lu\n", tm_cooperative_thread_2_counter);
226 		printf("tm_cooperative_thread_3_counter: %lu\n", tm_cooperative_thread_3_counter);
227 		printf("tm_cooperative_thread_4_counter: %lu\n", tm_cooperative_thread_4_counter);
228 
229 		/* See if there are any errors.  */
230 		if ((tm_cooperative_thread_0_counter < (average - 1)) ||
231 		    (tm_cooperative_thread_0_counter > (average + 1)) ||
232 		    (tm_cooperative_thread_1_counter < (average - 1)) ||
233 		    (tm_cooperative_thread_1_counter > (average + 1)) ||
234 		    (tm_cooperative_thread_2_counter < (average - 1)) ||
235 		    (tm_cooperative_thread_2_counter > (average + 1)) ||
236 		    (tm_cooperative_thread_3_counter < (average - 1)) ||
237 		    (tm_cooperative_thread_3_counter > (average + 1)) ||
238 		    (tm_cooperative_thread_4_counter < (average - 1)) ||
239 		    (tm_cooperative_thread_4_counter > (average + 1))) {
240 
241 			printf("ERROR: Invalid counter value(s). Cooperative counters should not "
242 			       "be more that 1 different than the average!\n");
243 		}
244 
245 		/* Show the time period total.  */
246 		printf("Time Period Total:  %lu\n\n", total - last_total);
247 
248 		/* Save the last total.  */
249 		last_total = total;
250 	}
251 }
252