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 
84 	/* Create all 5 threads at priority 3.  */
85 	tm_thread_create(0, 3, tm_cooperative_thread_0_entry);
86 	tm_thread_create(1, 3, tm_cooperative_thread_1_entry);
87 	tm_thread_create(2, 3, tm_cooperative_thread_2_entry);
88 	tm_thread_create(3, 3, tm_cooperative_thread_3_entry);
89 	tm_thread_create(4, 3, tm_cooperative_thread_4_entry);
90 
91 	/* Resume all 5 threads.  */
92 	tm_thread_resume(0);
93 	tm_thread_resume(1);
94 	tm_thread_resume(2);
95 	tm_thread_resume(3);
96 	tm_thread_resume(4);
97 
98 	tm_cooperative_thread_report();
99 }
100 
101 /* Define the first cooperative thread.  */
tm_cooperative_thread_0_entry(void * p1,void * p2,void * p3)102 void tm_cooperative_thread_0_entry(void *p1, void *p2, void *p3)
103 {
104 	(void)p1;
105 	(void)p2;
106 	(void)p3;
107 
108 	while (1) {
109 
110 		/* Relinquish to all other threads at same priority.  */
111 		tm_thread_relinquish();
112 
113 		/* Increment this thread's counter.  */
114 		tm_cooperative_thread_0_counter++;
115 	}
116 }
117 
118 /* Define the second cooperative thread.  */
tm_cooperative_thread_1_entry(void * p1,void * p2,void * p3)119 void tm_cooperative_thread_1_entry(void *p1, void *p2, void *p3)
120 {
121 	(void)p1;
122 	(void)p2;
123 	(void)p3;
124 
125 	while (1) {
126 
127 		/* Relinquish to all other threads at same priority.  */
128 		tm_thread_relinquish();
129 
130 		/* Increment this thread's counter.  */
131 		tm_cooperative_thread_1_counter++;
132 	}
133 }
134 
135 /* Define the third cooperative thread.  */
tm_cooperative_thread_2_entry(void * p1,void * p2,void * p3)136 void tm_cooperative_thread_2_entry(void *p1, void *p2, void *p3)
137 {
138 	(void)p1;
139 	(void)p2;
140 	(void)p3;
141 
142 	while (1) {
143 
144 		/* Relinquish to all other threads at same priority.  */
145 		tm_thread_relinquish();
146 
147 		/* Increment this thread's counter.  */
148 		tm_cooperative_thread_2_counter++;
149 	}
150 }
151 
152 /* Define the fourth cooperative thread.  */
tm_cooperative_thread_3_entry(void * p1,void * p2,void * p3)153 void tm_cooperative_thread_3_entry(void *p1, void *p2, void *p3)
154 {
155 	(void)p1;
156 	(void)p2;
157 	(void)p3;
158 
159 	while (1) {
160 
161 		/* Relinquish to all other threads at same priority.  */
162 		tm_thread_relinquish();
163 
164 		/* Increment this thread's counter.  */
165 		tm_cooperative_thread_3_counter++;
166 	}
167 }
168 
169 /* Define the fifth cooperative thread.  */
tm_cooperative_thread_4_entry(void * p1,void * p2,void * p3)170 void tm_cooperative_thread_4_entry(void *p1, void *p2, void *p3)
171 {
172 	(void)p1;
173 	(void)p2;
174 	(void)p3;
175 
176 	while (1) {
177 
178 		/* Relinquish to all other threads at same priority.  */
179 		tm_thread_relinquish();
180 
181 		/* Increment this thread's counter.  */
182 		tm_cooperative_thread_4_counter++;
183 	}
184 }
185 
186 /* Define the cooperative test reporting function.  */
tm_cooperative_thread_report(void)187 void tm_cooperative_thread_report(void)
188 {
189 
190 	unsigned long total;
191 	unsigned long relative_time;
192 	unsigned long last_total;
193 	unsigned long average;
194 
195 	/* Initialize the last total.  */
196 	last_total = 0;
197 
198 	/* Initialize the relative time.  */
199 	relative_time = 0;
200 
201 	while (1) {
202 
203 		/* Sleep to allow the test to run.  */
204 		tm_thread_sleep(TM_TEST_DURATION);
205 
206 		/* Increment the relative time.  */
207 		relative_time = relative_time + TM_TEST_DURATION;
208 
209 		/* Print results to the stdio window.  */
210 		printf("**** Thread-Metric Cooperative Scheduling Test **** Relative Time: %lu\n",
211 		       relative_time);
212 
213 		/* Calculate the total of all the counters.  */
214 		total = tm_cooperative_thread_0_counter + tm_cooperative_thread_1_counter +
215 			tm_cooperative_thread_2_counter + tm_cooperative_thread_3_counter +
216 			tm_cooperative_thread_4_counter;
217 
218 		/* Calculate the average of all the counters.  */
219 		average = total / 5;
220 
221 		/* WCC - integrity check */
222 		printf("tm_cooperative_thread_0_counter: %lu\n", tm_cooperative_thread_0_counter);
223 		printf("tm_cooperative_thread_1_counter: %lu\n", tm_cooperative_thread_1_counter);
224 		printf("tm_cooperative_thread_2_counter: %lu\n", tm_cooperative_thread_2_counter);
225 		printf("tm_cooperative_thread_3_counter: %lu\n", tm_cooperative_thread_3_counter);
226 		printf("tm_cooperative_thread_4_counter: %lu\n", tm_cooperative_thread_4_counter);
227 
228 		/* See if there are any errors.  */
229 		if ((tm_cooperative_thread_0_counter < (average - 1)) ||
230 		    (tm_cooperative_thread_0_counter > (average + 1)) ||
231 		    (tm_cooperative_thread_1_counter < (average - 1)) ||
232 		    (tm_cooperative_thread_1_counter > (average + 1)) ||
233 		    (tm_cooperative_thread_2_counter < (average - 1)) ||
234 		    (tm_cooperative_thread_2_counter > (average + 1)) ||
235 		    (tm_cooperative_thread_3_counter < (average - 1)) ||
236 		    (tm_cooperative_thread_3_counter > (average + 1)) ||
237 		    (tm_cooperative_thread_4_counter < (average - 1)) ||
238 		    (tm_cooperative_thread_4_counter > (average + 1))) {
239 
240 			printf("ERROR: Invalid counter value(s). Cooperative counters should not "
241 			       "be more that 1 different than the average!\n");
242 		}
243 
244 		/* Show the time period total.  */
245 		printf("Time Period Total:  %lu\n\n", total - last_total);
246 
247 		/* Save the last total.  */
248 		last_total = total;
249 	}
250 }
251