|
0
|
1 //========================================================================== |
|
|
2 // |
|
|
3 // tm_basic.cxx |
|
|
4 // |
|
|
5 // Basic timing test / scaffolding |
|
|
6 // |
|
|
7 //========================================================================== |
|
|
8 //####COPYRIGHTBEGIN#### |
|
|
9 // |
|
|
10 // ------------------------------------------- |
|
|
11 // The contents of this file are subject to the Cygnus eCos Public License |
|
|
12 // Version 1.0 (the "License"); you may not use this file except in |
|
|
13 // compliance with the License. You may obtain a copy of the License at |
|
|
14 // http://sourceware.cygnus.com/ecos |
|
|
15 // |
|
|
16 // Software distributed under the License is distributed on an "AS IS" |
|
|
17 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the |
|
|
18 // License for the specific language governing rights and limitations under |
|
|
19 // the License. |
|
|
20 // |
|
|
21 // The Original Code is eCos - Embedded Cygnus Operating System, released |
|
|
22 // September 30, 1998. |
|
|
23 // |
|
|
24 // The Initial Developer of the Original Code is Cygnus. Portions created |
|
2
|
25 // by Cygnus are Copyright (C) 1998,1999 Cygnus Solutions. All Rights Reserved. |
|
0
|
26 // ------------------------------------------- |
|
|
27 // |
|
|
28 //####COPYRIGHTEND#### |
|
|
29 //========================================================================== |
|
|
30 //#####DESCRIPTIONBEGIN#### |
|
|
31 // |
|
|
32 // Author(s): gthomas |
|
|
33 // Contributors: gthomas |
|
|
34 // Date: 1998-10-19 |
|
2
|
35 // Description: Very simple kernel timing test |
|
0
|
36 //####DESCRIPTIONEND#### |
|
|
37 |
|
|
38 #include <pkgconf/kernel.h> |
|
|
39 |
|
|
40 #include <cyg/kernel/sched.hxx> |
|
|
41 #include <cyg/kernel/thread.hxx> |
|
|
42 #include <cyg/kernel/thread.inl> |
|
|
43 #include <cyg/kernel/mutex.hxx> |
|
|
44 #include <cyg/kernel/sema.hxx> |
|
|
45 #include <cyg/kernel/sched.inl> |
|
|
46 #include <cyg/kernel/clock.hxx> |
|
|
47 #include <cyg/kernel/clock.inl> |
|
|
48 #include <cyg/kernel/kapi.h> |
|
|
49 |
|
|
50 #include <cyg/infra/testcase.h> |
|
2
|
51 |
|
|
52 // Define this to see the statistics with the first sample datum removed. |
|
|
53 // This can expose the effects of caches on the speed of operations. |
|
|
54 #undef STATS_WITHOUT_FIRST_SAMPLE |
|
|
55 |
|
|
56 #if defined(CYGFUN_KERNEL_API_C) && \ |
|
|
57 defined(CYGSEM_KERNEL_SCHED_MLQUEUE) && \ |
|
|
58 defined(CYGVAR_KERNEL_COUNTERS_CLOCK) && \ |
|
|
59 !defined(CYGPKG_HAL_I386_LINUX) && \ |
|
|
60 (CYGNUM_KERNEL_SCHED_PRIORITIES > 12) |
|
|
61 |
|
0
|
62 #define NTHREADS 1 |
|
|
63 #include "testaux.hxx" |
|
|
64 |
|
|
65 // Structure used to keep track of times |
|
|
66 typedef struct fun_times { |
|
|
67 cyg_uint32 start; |
|
|
68 cyg_uint32 end; |
|
|
69 } fun_times; |
|
|
70 |
|
2
|
71 #define NSAMPLES 32 |
|
|
72 #define NTEST_THREADS 24 |
|
0
|
73 #define NTHREAD_SWITCHES 128 |
|
|
74 #define NMUTEXES 32 |
|
|
75 #define NMBOXES 32 |
|
|
76 #define NSEMAPHORES 32 |
|
|
77 #define NSCHEDS 128 |
|
|
78 #define NCOUNTERS 32 |
|
|
79 #define NALARMS 32 |
|
|
80 |
|
2
|
81 #define NSAMPLES_SIM 2 |
|
|
82 #define NTEST_THREADS_SIM 2 |
|
|
83 #define NTHREAD_SWITCHES_SIM 4 |
|
|
84 #define NMUTEXES_SIM 2 |
|
|
85 #define NMBOXES_SIM 2 |
|
|
86 #define NSEMAPHORES_SIM 2 |
|
|
87 #define NSCHEDS_SIM 4 |
|
|
88 #define NCOUNTERS_SIM 2 |
|
|
89 #define NALARMS_SIM 2 |
|
|
90 |
|
|
91 static int nsamples; |
|
|
92 static int ntest_threads; |
|
|
93 static int nthread_switches; |
|
|
94 static int nmutexes; |
|
|
95 static int nmboxes; |
|
|
96 static int nsemaphores; |
|
|
97 static int nscheds; |
|
|
98 static int ncounters; |
|
|
99 static int nalarms; |
|
|
100 |
|
|
101 #define STACK_SIZE CYGNUM_HAL_STACK_SIZE_MINIMUM |
|
|
102 |
|
0
|
103 static char stacks[NTEST_THREADS][STACK_SIZE]; |
|
|
104 static cyg_thread test_threads[NTEST_THREADS]; |
|
|
105 static cyg_handle_t threads[NTEST_THREADS]; |
|
|
106 static int overhead; |
|
|
107 static cyg_sem_t synchro; |
|
|
108 static fun_times thread_ft[NTEST_THREADS]; |
|
|
109 |
|
|
110 static fun_times test2_ft[NTHREAD_SWITCHES]; |
|
|
111 |
|
|
112 static cyg_mutex_t test_mutexes[NMUTEXES]; |
|
|
113 static fun_times mutex_ft[NMUTEXES]; |
|
|
114 static cyg_thread mutex_test_thread; |
|
|
115 static cyg_handle_t mutex_test_thread_handle; |
|
|
116 |
|
|
117 static cyg_mbox test_mboxes[NMBOXES]; |
|
|
118 static cyg_handle_t test_mbox_handles[NMBOXES]; |
|
|
119 static fun_times mbox_ft[NMBOXES]; |
|
|
120 static cyg_thread mbox_test_thread; |
|
|
121 static cyg_handle_t mbox_test_thread_handle; |
|
|
122 |
|
|
123 static cyg_sem_t test_semaphores[NSEMAPHORES]; |
|
|
124 static fun_times semaphore_ft[NSEMAPHORES]; |
|
|
125 static cyg_thread semaphore_test_thread; |
|
|
126 static cyg_handle_t semaphore_test_thread_handle; |
|
|
127 |
|
|
128 static fun_times sched_ft[NSCHEDS]; |
|
|
129 |
|
|
130 static cyg_counter test_counters[NCOUNTERS]; |
|
|
131 static cyg_handle_t counters[NCOUNTERS]; |
|
|
132 static fun_times counter_ft[NCOUNTERS]; |
|
|
133 |
|
|
134 static cyg_alarm test_alarms[NALARMS]; |
|
|
135 static cyg_handle_t alarms[NALARMS]; |
|
|
136 static fun_times alarm_ft[NALARMS]; |
|
|
137 |
|
2
|
138 static long rtc_resolution[] = CYGNUM_KERNEL_COUNTERS_RTC_RESOLUTION; |
|
|
139 static long ns_per_system_clock; |
|
|
140 |
|
|
141 #ifdef HAL_CLOCK_LATENCY |
|
|
142 // Data kept by kernel real time clock measuring clock interrupt latency |
|
|
143 extern cyg_tick_count total_clock_latency, total_clock_interrupts; |
|
|
144 extern cyg_int32 min_clock_latency, max_clock_latency; |
|
|
145 extern bool measure_clock_latency; |
|
|
146 #endif |
|
|
147 |
|
0
|
148 externC void diag_printf(const char *, ...); |
|
|
149 |
|
|
150 void run_sched_tests(void); |
|
|
151 void run_thread_tests(void); |
|
|
152 void run_thread_switch_test(void); |
|
|
153 void run_mutex_tests(void); |
|
|
154 void run_mutex_circuit_test(void); |
|
|
155 void run_mbox_tests(void); |
|
|
156 void run_mbox_circuit_test(void); |
|
|
157 void run_semaphore_tests(void); |
|
|
158 void run_semaphore_circuit_test(void); |
|
|
159 void run_counter_tests(void); |
|
|
160 void run_alarm_tests(void); |
|
|
161 |
|
|
162 // Wait until a clock tick [real time clock] has passed. This should keep it |
|
|
163 // from happening again during a measurement, thus minimizing any fluctuations |
|
|
164 void |
|
|
165 wait_for_tick(void) |
|
|
166 { |
|
2
|
167 cyg_tick_count_t tv0, tv1; |
|
|
168 tv0 = cyg_current_time(); |
|
0
|
169 while (true) { |
|
2
|
170 tv1 = cyg_current_time(); |
|
|
171 if (tv1 != tv0) break; |
|
|
172 } |
|
|
173 } |
|
|
174 |
|
|
175 // Display a number of ticks as microseconds |
|
|
176 // Note: for improved calculation significance, values are kept in ticks*1000 |
|
|
177 void |
|
|
178 show_ticks_in_us(cyg_uint32 ticks) |
|
|
179 { |
|
|
180 long long ns; |
|
|
181 ns = (ns_per_system_clock * (long long)ticks) / CYGNUM_KERNEL_COUNTERS_RTC_PERIOD; |
|
|
182 ns += 5; // for rounding to .01us |
|
|
183 diag_printf("%5d.%02d", (int)(ns/1000), (int)((ns%1000)/10)); |
|
|
184 } |
|
|
185 |
|
|
186 // |
|
|
187 // If the kernel is instrumented to measure clock interrupt latency, these |
|
|
188 // measurements can be drastically perturbed by printing via "diag_printf()" |
|
|
189 // since that code may run with interrupts disabled for long periods. |
|
|
190 // |
|
|
191 // In order to get accurate/reasonable latency figures _for the kernel |
|
|
192 // primitive functions beint tested_, the kernel's latency measurements |
|
|
193 // are suspended while the printing actually takes place. |
|
|
194 // |
|
|
195 // The measurements are reenabled after the printing, thus allowing for |
|
|
196 // fair measurements of the kernel primitives, which are not distorted |
|
|
197 // by the printing mechanisms. |
|
|
198 |
|
|
199 #ifdef HAL_CLOCK_LATENCY |
|
|
200 void |
|
|
201 disable_clock_latency_measurement(void) |
|
|
202 { |
|
|
203 wait_for_tick(); |
|
|
204 measure_clock_latency = false; |
|
|
205 } |
|
|
206 |
|
|
207 void |
|
|
208 enable_clock_latency_measurement(void) |
|
|
209 { |
|
|
210 wait_for_tick(); |
|
|
211 measure_clock_latency = true; |
|
|
212 } |
|
|
213 |
|
|
214 // Ensure that the measurements are reasonable (no startup anomalies) |
|
|
215 void |
|
|
216 reset_clock_latency_measurement(void) |
|
|
217 { |
|
|
218 disable_clock_latency_measurement(); |
|
|
219 total_clock_latency = 0; |
|
|
220 total_clock_interrupts = 0; |
|
|
221 min_clock_latency = 0x7FFFFFFF; |
|
|
222 max_clock_latency = 0; |
|
|
223 enable_clock_latency_measurement(); |
|
|
224 } |
|
|
225 #else |
|
|
226 #define disable_clock_latency_measurement() |
|
|
227 #define enable_clock_latency_measurement() |
|
|
228 #define reset_clock_latency_measurement() |
|
|
229 #endif |
|
|
230 |
|
|
231 void |
|
|
232 show_times_hdr(void) |
|
|
233 { |
|
|
234 disable_clock_latency_measurement(); |
|
|
235 diag_printf("\n"); |
|
|
236 diag_printf(" Confidence\n"); |
|
|
237 diag_printf(" Ave Min Max Var Ave Min Function\n"); |
|
|
238 diag_printf(" ====== ====== ====== ====== ========== ========\n"); |
|
|
239 enable_clock_latency_measurement(); |
|
|
240 } |
|
|
241 |
|
|
242 void |
|
|
243 show_times_detail(fun_times ft[], int nsamples, char *title, bool ignore_first) |
|
|
244 { |
|
|
245 int i, delta, min, max, con_ave, con_min, ave_dev; |
|
|
246 int start_sample, total_samples; |
|
|
247 cyg_int32 total, ave; |
|
|
248 |
|
|
249 if (ignore_first) { |
|
|
250 start_sample = 1; |
|
|
251 total_samples = nsamples-1; |
|
|
252 } else { |
|
|
253 start_sample = 0; |
|
|
254 total_samples = nsamples; |
|
0
|
255 } |
|
2
|
256 total = 0; |
|
|
257 min = 0x7FFFFFFF; |
|
|
258 max = 0; |
|
|
259 for (i = start_sample; i < nsamples; i++) { |
|
|
260 if (ft[i].end < ft[i].start) { |
|
|
261 // Clock wrapped around (timer tick) |
|
|
262 delta = (ft[i].end+CYGNUM_KERNEL_COUNTERS_RTC_PERIOD) - ft[i].start; |
|
|
263 } else { |
|
|
264 delta = ft[i].end - ft[i].start; |
|
|
265 } |
|
|
266 delta -= overhead; |
|
|
267 if (delta < 0) delta = 0; |
|
|
268 delta *= 1000; |
|
|
269 total += delta; |
|
|
270 if (delta < min) min = delta; |
|
|
271 if (delta > max) max = delta; |
|
|
272 } |
|
|
273 ave = total / total_samples; |
|
|
274 total = 0; |
|
|
275 ave_dev = 0; |
|
|
276 for (i = start_sample; i < nsamples; i++) { |
|
|
277 if (ft[i].end < ft[i].start) { |
|
|
278 // Clock wrapped around (timer tick) |
|
|
279 delta = (ft[i].end+CYGNUM_KERNEL_COUNTERS_RTC_PERIOD) - ft[i].start; |
|
|
280 } else { |
|
|
281 delta = ft[i].end - ft[i].start; |
|
|
282 } |
|
|
283 delta -= overhead; |
|
|
284 if (delta < 0) delta = 0; |
|
|
285 delta *= 1000; |
|
|
286 delta = delta - ave; |
|
|
287 if (delta < 0) delta = -delta; |
|
|
288 ave_dev += delta; |
|
|
289 } |
|
|
290 ave_dev /= total_samples; |
|
|
291 con_ave = 0; |
|
|
292 con_min = 0; |
|
|
293 for (i = start_sample; i < nsamples; i++) { |
|
|
294 if (ft[i].end < ft[i].start) { |
|
|
295 // Clock wrapped around (timer tick) |
|
|
296 delta = (ft[i].end+CYGNUM_KERNEL_COUNTERS_RTC_PERIOD) - ft[i].start; |
|
|
297 } else { |
|
|
298 delta = ft[i].end - ft[i].start; |
|
|
299 } |
|
|
300 delta -= overhead; |
|
|
301 if (delta < 0) delta = 0; |
|
|
302 delta *= 1000; |
|
|
303 if ((delta <= (ave+ave_dev)) && (delta >= (ave-ave_dev))) con_ave++; |
|
|
304 if ((delta <= (min+ave_dev)) && (delta >= (min-ave_dev))) con_min++; |
|
|
305 } |
|
|
306 con_ave = (con_ave * 100) / total_samples; |
|
|
307 con_min = (con_min * 100) / total_samples; |
|
|
308 show_ticks_in_us(ave); |
|
|
309 show_ticks_in_us(min); |
|
|
310 show_ticks_in_us(max); |
|
|
311 show_ticks_in_us(ave_dev); |
|
|
312 disable_clock_latency_measurement(); |
|
|
313 diag_printf(" %3d%% %3d%%", con_ave, con_min); |
|
|
314 diag_printf(" %s\n", title); |
|
|
315 enable_clock_latency_measurement(); |
|
|
316 } |
|
|
317 |
|
|
318 void |
|
|
319 show_times(fun_times ft[], int nsamples, char *title) |
|
|
320 { |
|
|
321 show_times_detail(ft, nsamples, title, false); |
|
|
322 #ifdef STATS_WITHOUT_FIRST_SAMPLE |
|
|
323 show_times_detail(ft, nsamples, "", true); |
|
|
324 #endif |
|
|
325 } |
|
|
326 |
|
|
327 void |
|
|
328 show_test_parameters(void) |
|
|
329 { |
|
|
330 disable_clock_latency_measurement(); |
|
|
331 diag_printf("\nTesting parameters:\n"); |
|
|
332 diag_printf(" Clock samples: %3d\n", nsamples); |
|
|
333 diag_printf(" Threads: %3d\n", ntest_threads); |
|
|
334 diag_printf(" Thread switches: %3d\n", nthread_switches); |
|
|
335 diag_printf(" Mutexes: %3d\n", nmutexes); |
|
|
336 diag_printf(" Mailboxes: %3d\n", nmboxes); |
|
|
337 diag_printf(" Semaphores: %3d\n", nsemaphores); |
|
|
338 diag_printf(" Scheduler operations: %3d\n", nscheds); |
|
|
339 diag_printf(" Counters: %3d\n", ncounters); |
|
|
340 diag_printf(" Alarms: %3d\n", nalarms); |
|
|
341 diag_printf("\n"); |
|
|
342 enable_clock_latency_measurement(); |
|
|
343 } |
|
|
344 |
|
|
345 void |
|
|
346 end_of_test_group(void) |
|
|
347 { |
|
|
348 disable_clock_latency_measurement(); |
|
|
349 diag_printf("\n"); |
|
|
350 enable_clock_latency_measurement(); |
|
0
|
351 } |
|
|
352 |
|
|
353 // Compute a name for a thread |
|
|
354 char * |
|
|
355 thread_name(char *basename, int indx) { |
|
|
356 return "<<NULL>>"; // Not currently used |
|
|
357 } |
|
|
358 |
|
|
359 // test0 - null test, never executed |
|
|
360 void |
|
|
361 test0(cyg_uint32 indx) |
|
|
362 { |
|
|
363 diag_printf("test0.%d executed?\n", indx); |
|
|
364 cyg_thread_exit(); |
|
|
365 } |
|
|
366 |
|
|
367 // test1 - empty test, simply exit. Last thread signals parent. |
|
|
368 void |
|
|
369 test1(cyg_uint32 indx) |
|
|
370 { |
|
2
|
371 if (indx == (cyg_uint32)(ntest_threads-1)) { |
|
0
|
372 cyg_semaphore_post(&synchro); // Signal that last thread is dying |
|
|
373 } |
|
|
374 cyg_thread_exit(); |
|
|
375 } |
|
|
376 |
|
|
377 // test2 - measure thread switch times |
|
|
378 void |
|
|
379 test2(cyg_uint32 indx) |
|
|
380 { |
|
|
381 int i; |
|
2
|
382 for (i = 0; i < nthread_switches; i++) { |
|
0
|
383 if (indx == 0) { |
|
|
384 HAL_CLOCK_READ(&test2_ft[i].start); |
|
|
385 } else { |
|
|
386 HAL_CLOCK_READ(&test2_ft[i].end); |
|
|
387 } |
|
|
388 cyg_thread_yield(); |
|
|
389 } |
|
|
390 if (indx == 1) { |
|
|
391 cyg_semaphore_post(&synchro); |
|
|
392 } |
|
|
393 cyg_thread_exit(); |
|
|
394 } |
|
|
395 |
|
|
396 // Full-circuit mutex unlock/lock test |
|
|
397 void |
|
|
398 mutex_test(cyg_uint32 indx) |
|
|
399 { |
|
|
400 int i; |
|
|
401 cyg_mutex_lock(&test_mutexes[0]); |
|
2
|
402 for (i = 0; i < nmutexes; i++) { |
|
0
|
403 cyg_semaphore_wait(&synchro); |
|
|
404 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
|
405 HAL_CLOCK_READ(&mutex_ft[i].start); |
|
|
406 cyg_mutex_unlock(&test_mutexes[0]); |
|
|
407 cyg_mutex_lock(&test_mutexes[0]); |
|
|
408 cyg_semaphore_post(&synchro); |
|
|
409 } |
|
|
410 cyg_thread_exit(); |
|
|
411 } |
|
|
412 |
|
|
413 // Full-circuit mbox put/get test |
|
|
414 void |
|
|
415 mbox_test(cyg_uint32 indx) |
|
|
416 { |
|
|
417 void *item; |
|
|
418 do { |
|
|
419 item = cyg_mbox_get(test_mbox_handles[0]); |
|
|
420 HAL_CLOCK_READ(&mbox_ft[(int)item].end); |
|
|
421 cyg_semaphore_post(&synchro); |
|
2
|
422 } while ((int)item != (nmboxes-1)); |
|
0
|
423 cyg_thread_exit(); |
|
|
424 } |
|
|
425 |
|
|
426 // Full-circuit semaphore post/wait test |
|
|
427 void |
|
|
428 semaphore_test(cyg_uint32 indx) |
|
|
429 { |
|
|
430 int i; |
|
2
|
431 for (i = 0; i < nsemaphores; i++) { |
|
0
|
432 cyg_semaphore_wait(&test_semaphores[0]); |
|
|
433 HAL_CLOCK_READ(&semaphore_ft[i].end); |
|
|
434 cyg_semaphore_post(&synchro); |
|
|
435 } |
|
|
436 cyg_thread_exit(); |
|
|
437 } |
|
|
438 |
|
2
|
439 // |
|
|
440 // This set of tests is used to measure kernel primitives that deal with threads |
|
|
441 // |
|
0
|
442 void |
|
|
443 run_thread_tests(void) |
|
|
444 { |
|
|
445 int i; |
|
|
446 cyg_priority_t prio; |
|
|
447 |
|
|
448 // Set my priority higher than any I plan to create |
|
|
449 cyg_thread_set_priority(cyg_thread_self(), 2); |
|
|
450 |
|
|
451 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
452 for (i = 0; i < ntest_threads; i++) { |
|
0
|
453 HAL_CLOCK_READ(&thread_ft[i].start); |
|
|
454 cyg_thread_create(10, // Priority - just a number |
|
|
455 test0, // entry |
|
|
456 i, // index |
|
|
457 thread_name("thread", i), // Name |
|
|
458 &stacks[i][0], // Stack |
|
|
459 STACK_SIZE, // Size |
|
|
460 &threads[i], // Handle |
|
|
461 &test_threads[i] // Thread data structure |
|
|
462 ); |
|
|
463 HAL_CLOCK_READ(&thread_ft[i].end); |
|
|
464 } |
|
2
|
465 show_times(thread_ft, ntest_threads, "Create thread"); |
|
0
|
466 |
|
|
467 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
468 for (i = 0; i < ntest_threads; i++) { |
|
0
|
469 HAL_CLOCK_READ(&thread_ft[i].start); |
|
|
470 cyg_thread_yield(); |
|
|
471 HAL_CLOCK_READ(&thread_ft[i].end); |
|
|
472 } |
|
2
|
473 show_times(thread_ft, ntest_threads, "Yield thread [all suspended]"); |
|
0
|
474 |
|
|
475 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
476 for (i = 0; i < ntest_threads; i++) { |
|
0
|
477 HAL_CLOCK_READ(&thread_ft[i].start); |
|
|
478 cyg_thread_suspend(threads[i]); |
|
|
479 HAL_CLOCK_READ(&thread_ft[i].end); |
|
|
480 } |
|
2
|
481 show_times(thread_ft, ntest_threads, "Suspend [suspended] thread"); |
|
0
|
482 |
|
|
483 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
484 for (i = 0; i < ntest_threads; i++) { |
|
0
|
485 HAL_CLOCK_READ(&thread_ft[i].start); |
|
|
486 cyg_thread_resume(threads[i]); |
|
|
487 HAL_CLOCK_READ(&thread_ft[i].end); |
|
|
488 } |
|
2
|
489 show_times(thread_ft, ntest_threads, "Resume thread"); |
|
0
|
490 |
|
|
491 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
492 for (i = 0; i < ntest_threads; i++) { |
|
0
|
493 HAL_CLOCK_READ(&thread_ft[i].start); |
|
|
494 cyg_thread_set_priority(threads[i], 11); |
|
|
495 HAL_CLOCK_READ(&thread_ft[i].end); |
|
|
496 } |
|
2
|
497 show_times(thread_ft, ntest_threads, "Set priority"); |
|
0
|
498 |
|
|
499 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
500 for (i = 0; i < ntest_threads; i++) { |
|
0
|
501 HAL_CLOCK_READ(&thread_ft[i].start); |
|
|
502 prio = cyg_thread_get_priority(threads[i]); |
|
|
503 HAL_CLOCK_READ(&thread_ft[i].end); |
|
|
504 } |
|
2
|
505 show_times(thread_ft, ntest_threads, "Get priority"); |
|
0
|
506 |
|
|
507 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
508 for (i = 0; i < ntest_threads; i++) { |
|
0
|
509 HAL_CLOCK_READ(&thread_ft[i].start); |
|
|
510 cyg_thread_kill(threads[i]); |
|
|
511 HAL_CLOCK_READ(&thread_ft[i].end); |
|
|
512 } |
|
2
|
513 show_times(thread_ft, ntest_threads, "Kill [suspended] thread"); |
|
0
|
514 |
|
|
515 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
516 for (i = 0; i < ntest_threads; i++) { |
|
0
|
517 HAL_CLOCK_READ(&thread_ft[i].start); |
|
|
518 cyg_thread_yield(); |
|
|
519 HAL_CLOCK_READ(&thread_ft[i].end); |
|
|
520 } |
|
2
|
521 show_times(thread_ft, ntest_threads, "Yield [no other] thread"); |
|
0
|
522 |
|
|
523 // Set my priority higher than any I plan to create |
|
|
524 cyg_thread_set_priority(cyg_thread_self(), 2); |
|
|
525 |
|
|
526 // Recreate the test set |
|
2
|
527 for (i = 0; i < ntest_threads; i++) { |
|
0
|
528 cyg_thread_create(10, // Priority - just a number |
|
|
529 test0, // entry |
|
|
530 i, // index |
|
|
531 thread_name("thread", i), // Name |
|
|
532 &stacks[i][0], // Stack |
|
|
533 STACK_SIZE, // Size |
|
|
534 &threads[i], // Handle |
|
|
535 &test_threads[i] // Thread data structure |
|
|
536 ); |
|
|
537 } |
|
|
538 |
|
|
539 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
540 for (i = 0; i < ntest_threads; i++) { |
|
|
541 HAL_CLOCK_READ(&thread_ft[i].start); |
|
|
542 cyg_thread_resume(threads[i]); |
|
|
543 HAL_CLOCK_READ(&thread_ft[i].end); |
|
|
544 } |
|
|
545 show_times(thread_ft, ntest_threads, "Resume [suspended low prio] thread"); |
|
|
546 |
|
|
547 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
|
548 for (i = 0; i < ntest_threads; i++) { |
|
0
|
549 HAL_CLOCK_READ(&thread_ft[i].start); |
|
|
550 cyg_thread_resume(threads[i]); |
|
|
551 HAL_CLOCK_READ(&thread_ft[i].end); |
|
|
552 } |
|
2
|
553 show_times(thread_ft, ntest_threads, "Resume [runnable low prio] thread"); |
|
0
|
554 |
|
|
555 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
556 for (i = 0; i < ntest_threads; i++) { |
|
0
|
557 HAL_CLOCK_READ(&thread_ft[i].start); |
|
2
|
558 cyg_thread_suspend(threads[i]); |
|
0
|
559 HAL_CLOCK_READ(&thread_ft[i].end); |
|
|
560 } |
|
2
|
561 show_times(thread_ft, ntest_threads, "Suspend [runnable] thread"); |
|
|
562 |
|
0
|
563 |
|
|
564 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
565 for (i = 0; i < ntest_threads; i++) { |
|
|
566 HAL_CLOCK_READ(&thread_ft[i].start); |
|
|
567 cyg_thread_yield(); |
|
|
568 HAL_CLOCK_READ(&thread_ft[i].end); |
|
|
569 } |
|
|
570 show_times(thread_ft, ntest_threads, "Yield [only low prio] thread"); |
|
|
571 |
|
|
572 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
|
573 for (i = 0; i < ntest_threads; i++) { |
|
0
|
574 HAL_CLOCK_READ(&thread_ft[i].start); |
|
|
575 cyg_thread_suspend(threads[i]); |
|
|
576 HAL_CLOCK_READ(&thread_ft[i].end); |
|
|
577 } |
|
2
|
578 show_times(thread_ft, ntest_threads, "Suspend [runnable->not runnable]"); |
|
|
579 for (i = 0; i < ntest_threads; i++) { |
|
0
|
580 cyg_thread_resume(threads[i]); |
|
|
581 } |
|
|
582 |
|
|
583 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
584 for (i = 0; i < ntest_threads; i++) { |
|
0
|
585 HAL_CLOCK_READ(&thread_ft[i].start); |
|
|
586 cyg_thread_kill(threads[i]); |
|
|
587 HAL_CLOCK_READ(&thread_ft[i].end); |
|
|
588 } |
|
2
|
589 show_times(thread_ft, ntest_threads, "Kill [runnable] thread"); |
|
|
590 |
|
|
591 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
|
592 for (i = 0; i < ntest_threads; i++) { |
|
|
593 HAL_CLOCK_READ(&thread_ft[i].start); |
|
|
594 cyg_thread_delete(threads[i]); |
|
|
595 HAL_CLOCK_READ(&thread_ft[i].end); |
|
|
596 } |
|
|
597 show_times(thread_ft, ntest_threads, "Destroy [dead] thread"); |
|
|
598 |
|
|
599 // Recreate the test set |
|
|
600 for (i = 0; i < ntest_threads; i++) { |
|
|
601 cyg_thread_create(10, // Priority - just a number |
|
|
602 test0, // entry |
|
|
603 i, // index |
|
|
604 thread_name("thread", i), // Name |
|
|
605 &stacks[i][0], // Stack |
|
|
606 STACK_SIZE, // Size |
|
|
607 &threads[i], // Handle |
|
|
608 &test_threads[i] // Thread data structure |
|
|
609 ); |
|
|
610 cyg_thread_resume(threads[i]); |
|
|
611 } |
|
|
612 |
|
|
613 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
|
614 for (i = 0; i < ntest_threads; i++) { |
|
|
615 HAL_CLOCK_READ(&thread_ft[i].start); |
|
|
616 cyg_thread_delete(threads[i]); |
|
|
617 HAL_CLOCK_READ(&thread_ft[i].end); |
|
|
618 } |
|
|
619 show_times(thread_ft, ntest_threads, "Destroy [runnable] thread"); |
|
|
620 |
|
0
|
621 // Set my priority lower than any I plan to create |
|
|
622 cyg_thread_set_priority(cyg_thread_self(), 3); |
|
|
623 |
|
|
624 // Set up the end-of-threads synchronizer |
|
|
625 cyg_semaphore_init(&synchro, 0); |
|
|
626 |
|
|
627 // Recreate the test set |
|
2
|
628 for (i = 0; i < ntest_threads; i++) { |
|
0
|
629 cyg_thread_create(2, // Priority - just a number |
|
|
630 test1, // entry |
|
|
631 i, // index |
|
|
632 thread_name("thread", i), // Name |
|
|
633 &stacks[i][0], // Stack |
|
|
634 STACK_SIZE, // Size |
|
|
635 &threads[i], // Handle |
|
|
636 &test_threads[i] // Thread data structure |
|
|
637 ); |
|
|
638 } |
|
|
639 |
|
|
640 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
641 for (i = 0; i < ntest_threads; i++) { |
|
0
|
642 HAL_CLOCK_READ(&thread_ft[i].start); |
|
|
643 cyg_thread_resume(threads[i]); |
|
|
644 HAL_CLOCK_READ(&thread_ft[i].end); |
|
|
645 } |
|
2
|
646 show_times(thread_ft, ntest_threads, "Resume [high priority] thread"); |
|
0
|
647 cyg_semaphore_wait(&synchro); // Wait for all threads to finish |
|
|
648 // Make sure they are all dead |
|
2
|
649 for (i = 0; i < ntest_threads; i++) { |
|
|
650 cyg_thread_delete(threads[i]); |
|
0
|
651 } |
|
|
652 |
|
|
653 run_thread_switch_test(); |
|
2
|
654 end_of_test_group(); |
|
0
|
655 } |
|
|
656 |
|
|
657 void |
|
|
658 run_thread_switch_test(void) |
|
|
659 { |
|
|
660 int i; |
|
|
661 |
|
|
662 // Set up for thread context switch |
|
|
663 for (i = 0; i < 2; i++) { |
|
|
664 cyg_thread_create(10, // Priority - just a number |
|
|
665 test2, // entry |
|
|
666 i, // index |
|
|
667 thread_name("thread", i), // Name |
|
|
668 &stacks[i][0], // Stack |
|
|
669 STACK_SIZE, // Size |
|
|
670 &threads[i], // Handle |
|
|
671 &test_threads[i] // Thread data structure |
|
|
672 ); |
|
|
673 cyg_thread_resume(threads[i]); |
|
|
674 } |
|
|
675 // Set up the end-of-threads synchronizer |
|
|
676 cyg_semaphore_init(&synchro, 0); |
|
|
677 cyg_semaphore_wait(&synchro); |
|
|
678 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
679 show_times(test2_ft, nthread_switches, "Thread switch"); |
|
0
|
680 // Clean up |
|
|
681 for (i = 0; i < 2; i++) { |
|
2
|
682 cyg_thread_delete(threads[i]); |
|
0
|
683 } |
|
|
684 } |
|
|
685 |
|
|
686 void |
|
|
687 run_mutex_tests(void) |
|
|
688 { |
|
|
689 int i; |
|
|
690 |
|
|
691 // Mutex primitives |
|
|
692 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
693 for (i = 0; i < nmutexes; i++) { |
|
0
|
694 HAL_CLOCK_READ(&mutex_ft[i].start); |
|
|
695 cyg_mutex_init(&test_mutexes[i]); |
|
|
696 HAL_CLOCK_READ(&mutex_ft[i].end); |
|
|
697 } |
|
2
|
698 show_times(mutex_ft, nmutexes, "Init mutex"); |
|
0
|
699 |
|
|
700 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
701 for (i = 0; i < nmutexes; i++) { |
|
0
|
702 HAL_CLOCK_READ(&mutex_ft[i].start); |
|
|
703 cyg_mutex_lock(&test_mutexes[i]); |
|
|
704 HAL_CLOCK_READ(&mutex_ft[i].end); |
|
|
705 } |
|
2
|
706 show_times(mutex_ft, nmutexes, "Lock [unlocked] mutex"); |
|
0
|
707 |
|
|
708 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
709 for (i = 0; i < nmutexes; i++) { |
|
0
|
710 HAL_CLOCK_READ(&mutex_ft[i].start); |
|
|
711 cyg_mutex_unlock(&test_mutexes[i]); |
|
|
712 HAL_CLOCK_READ(&mutex_ft[i].end); |
|
|
713 } |
|
2
|
714 show_times(mutex_ft, nmutexes, "Unlock [locked] mutex"); |
|
0
|
715 |
|
|
716 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
717 for (i = 0; i < nmutexes; i++) { |
|
0
|
718 HAL_CLOCK_READ(&mutex_ft[i].start); |
|
|
719 cyg_mutex_trylock(&test_mutexes[i]); |
|
|
720 HAL_CLOCK_READ(&mutex_ft[i].end); |
|
|
721 } |
|
2
|
722 show_times(mutex_ft, nmutexes, "Trylock [unlocked] mutex"); |
|
0
|
723 |
|
|
724 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
725 for (i = 0; i < nmutexes; i++) { |
|
0
|
726 HAL_CLOCK_READ(&mutex_ft[i].start); |
|
|
727 cyg_mutex_trylock(&test_mutexes[i]); |
|
|
728 HAL_CLOCK_READ(&mutex_ft[i].end); |
|
|
729 } |
|
2
|
730 show_times(mutex_ft, nmutexes, "Trylock [locked] mutex"); |
|
0
|
731 |
|
|
732 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
733 for (i = 0; i < nmutexes; i++) { |
|
0
|
734 HAL_CLOCK_READ(&mutex_ft[i].start); |
|
|
735 cyg_mutex_destroy(&test_mutexes[i]); |
|
|
736 HAL_CLOCK_READ(&mutex_ft[i].end); |
|
|
737 } |
|
2
|
738 show_times(mutex_ft, nmutexes, "Destroy mutex"); |
|
0
|
739 run_mutex_circuit_test(); |
|
2
|
740 end_of_test_group(); |
|
0
|
741 } |
|
|
742 |
|
|
743 void |
|
|
744 run_mutex_circuit_test(void) |
|
|
745 { |
|
|
746 int i; |
|
|
747 // Set my priority lower than any I plan to create |
|
|
748 cyg_thread_set_priority(cyg_thread_self(), 4); |
|
|
749 // Set up for full mutex unlock/lock test |
|
|
750 cyg_mutex_init(&test_mutexes[0]); |
|
|
751 cyg_semaphore_init(&synchro, 0); |
|
|
752 cyg_thread_create(3, // Priority - just a number |
|
|
753 mutex_test, // entry |
|
|
754 0, // index |
|
|
755 thread_name("thread", 0), // Name |
|
|
756 &stacks[0][0], // Stack |
|
|
757 STACK_SIZE, // Size |
|
|
758 &mutex_test_thread_handle, // Handle |
|
|
759 &mutex_test_thread // Thread data structure |
|
|
760 ); |
|
|
761 cyg_thread_resume(mutex_test_thread_handle); |
|
|
762 // Need to raise priority so that this thread will block on the "lock" |
|
|
763 cyg_thread_set_priority(cyg_thread_self(), 2); |
|
2
|
764 for (i = 0; i < nmutexes; i++) { |
|
0
|
765 cyg_semaphore_post(&synchro); |
|
|
766 cyg_mutex_lock(&test_mutexes[0]); |
|
|
767 HAL_CLOCK_READ(&mutex_ft[i].end); |
|
|
768 cyg_mutex_unlock(&test_mutexes[0]); |
|
|
769 cyg_semaphore_wait(&synchro); |
|
|
770 } |
|
2
|
771 cyg_thread_delete(mutex_test_thread_handle); |
|
|
772 show_times(mutex_ft, nmutexes, "Unlock/Lock mutex"); |
|
0
|
773 } |
|
|
774 |
|
|
775 void |
|
|
776 run_mbox_tests(void) |
|
|
777 { |
|
|
778 int i, cnt; |
|
|
779 void *item; |
|
|
780 // Mailbox primitives |
|
|
781 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
782 for (i = 0; i < nmboxes; i++) { |
|
0
|
783 HAL_CLOCK_READ(&mbox_ft[i].start); |
|
|
784 cyg_mbox_create(&test_mbox_handles[i], &test_mboxes[i]); |
|
|
785 HAL_CLOCK_READ(&mbox_ft[i].end); |
|
|
786 } |
|
2
|
787 show_times(mbox_ft, nmboxes, "Create mbox"); |
|
0
|
788 |
|
|
789 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
790 for (i = 0; i < nmboxes; i++) { |
|
0
|
791 HAL_CLOCK_READ(&mbox_ft[i].start); |
|
|
792 cnt = cyg_mbox_peek(test_mbox_handles[i]); |
|
|
793 HAL_CLOCK_READ(&mbox_ft[i].end); |
|
|
794 } |
|
2
|
795 show_times(mbox_ft, nmboxes, "Peek [empty] mbox"); |
|
0
|
796 |
|
2
|
797 #ifdef CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT |
|
0
|
798 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
799 for (i = 0; i < nmboxes; i++) { |
|
0
|
800 HAL_CLOCK_READ(&mbox_ft[i].start); |
|
|
801 cyg_mbox_put(test_mbox_handles[i], (void *)i); |
|
|
802 HAL_CLOCK_READ(&mbox_ft[i].end); |
|
|
803 } |
|
2
|
804 show_times(mbox_ft, nmboxes, "Put [first] mbox"); |
|
0
|
805 |
|
|
806 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
807 for (i = 0; i < nmboxes; i++) { |
|
0
|
808 HAL_CLOCK_READ(&mbox_ft[i].start); |
|
|
809 cnt = cyg_mbox_peek(test_mbox_handles[i]); |
|
|
810 HAL_CLOCK_READ(&mbox_ft[i].end); |
|
|
811 } |
|
2
|
812 show_times(mbox_ft, nmboxes, "Peek [1 msg] mbox"); |
|
0
|
813 |
|
|
814 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
815 for (i = 0; i < nmboxes; i++) { |
|
|
816 HAL_CLOCK_READ(&mbox_ft[i].start); |
|
|
817 cyg_mbox_put(test_mbox_handles[i], (void *)i); |
|
|
818 HAL_CLOCK_READ(&mbox_ft[i].end); |
|
|
819 } |
|
|
820 show_times(mbox_ft, nmboxes, "Put [second] mbox"); |
|
|
821 |
|
|
822 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
|
823 for (i = 0; i < nmboxes; i++) { |
|
|
824 HAL_CLOCK_READ(&mbox_ft[i].start); |
|
|
825 cnt = cyg_mbox_peek(test_mbox_handles[i]); |
|
|
826 HAL_CLOCK_READ(&mbox_ft[i].end); |
|
|
827 } |
|
|
828 show_times(mbox_ft, nmboxes, "Peek [2 msgs] mbox"); |
|
|
829 |
|
|
830 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
|
831 for (i = 0; i < nmboxes; i++) { |
|
0
|
832 HAL_CLOCK_READ(&mbox_ft[i].start); |
|
|
833 item = cyg_mbox_get(test_mbox_handles[i]); |
|
|
834 HAL_CLOCK_READ(&mbox_ft[i].end); |
|
|
835 } |
|
2
|
836 show_times(mbox_ft, nmboxes, "Get [first] mbox"); |
|
0
|
837 |
|
|
838 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
839 for (i = 0; i < nmboxes; i++) { |
|
0
|
840 HAL_CLOCK_READ(&mbox_ft[i].start); |
|
|
841 item = cyg_mbox_get(test_mbox_handles[i]); |
|
|
842 HAL_CLOCK_READ(&mbox_ft[i].end); |
|
|
843 } |
|
2
|
844 show_times(mbox_ft, nmboxes, "Get [second] mbox"); |
|
|
845 #endif // ifdef CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT |
|
0
|
846 |
|
|
847 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
848 for (i = 0; i < nmboxes; i++) { |
|
0
|
849 HAL_CLOCK_READ(&mbox_ft[i].start); |
|
|
850 cyg_mbox_tryput(test_mbox_handles[i], (void *)i); |
|
|
851 HAL_CLOCK_READ(&mbox_ft[i].end); |
|
|
852 } |
|
2
|
853 show_times(mbox_ft, nmboxes, "Tryput [first] mbox"); |
|
0
|
854 |
|
|
855 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
856 for (i = 0; i < nmboxes; i++) { |
|
0
|
857 HAL_CLOCK_READ(&mbox_ft[i].start); |
|
|
858 item = cyg_mbox_peek_item(test_mbox_handles[i]); |
|
|
859 HAL_CLOCK_READ(&mbox_ft[i].end); |
|
|
860 } |
|
2
|
861 show_times(mbox_ft, nmboxes, "Peek item [non-empty] mbox"); |
|
0
|
862 |
|
|
863 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
864 for (i = 0; i < nmboxes; i++) { |
|
0
|
865 HAL_CLOCK_READ(&mbox_ft[i].start); |
|
|
866 item = cyg_mbox_tryget(test_mbox_handles[i]); |
|
|
867 HAL_CLOCK_READ(&mbox_ft[i].end); |
|
|
868 } |
|
2
|
869 show_times(mbox_ft, nmboxes, "Tryget [non-empty] mbox"); |
|
0
|
870 |
|
|
871 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
872 for (i = 0; i < nmboxes; i++) { |
|
0
|
873 HAL_CLOCK_READ(&mbox_ft[i].start); |
|
|
874 item = cyg_mbox_peek_item(test_mbox_handles[i]); |
|
|
875 HAL_CLOCK_READ(&mbox_ft[i].end); |
|
|
876 } |
|
2
|
877 show_times(mbox_ft, nmboxes, "Peek item [empty] mbox"); |
|
0
|
878 |
|
|
879 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
880 for (i = 0; i < nmboxes; i++) { |
|
0
|
881 HAL_CLOCK_READ(&mbox_ft[i].start); |
|
|
882 item = cyg_mbox_tryget(test_mbox_handles[i]); |
|
|
883 HAL_CLOCK_READ(&mbox_ft[i].end); |
|
|
884 } |
|
2
|
885 show_times(mbox_ft, nmboxes, "Tryget [empty] mbox"); |
|
0
|
886 |
|
|
887 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
888 for (i = 0; i < nmboxes; i++) { |
|
0
|
889 HAL_CLOCK_READ(&mbox_ft[i].start); |
|
|
890 cyg_mbox_waiting_to_get(test_mbox_handles[i]); |
|
|
891 HAL_CLOCK_READ(&mbox_ft[i].end); |
|
|
892 } |
|
2
|
893 show_times(mbox_ft, nmboxes, "Waiting to get mbox"); |
|
0
|
894 |
|
|
895 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
896 for (i = 0; i < nmboxes; i++) { |
|
0
|
897 HAL_CLOCK_READ(&mbox_ft[i].start); |
|
|
898 cyg_mbox_waiting_to_put(test_mbox_handles[i]); |
|
|
899 HAL_CLOCK_READ(&mbox_ft[i].end); |
|
|
900 } |
|
2
|
901 show_times(mbox_ft, nmboxes, "Waiting to put mbox"); |
|
0
|
902 |
|
|
903 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
904 for (i = 0; i < nmboxes; i++) { |
|
0
|
905 HAL_CLOCK_READ(&mbox_ft[i].start); |
|
|
906 cyg_mbox_delete(test_mbox_handles[i]); |
|
|
907 HAL_CLOCK_READ(&mbox_ft[i].end); |
|
|
908 } |
|
2
|
909 show_times(mbox_ft, nmboxes, "Delete mbox"); |
|
0
|
910 |
|
|
911 run_mbox_circuit_test(); |
|
2
|
912 end_of_test_group(); |
|
0
|
913 } |
|
|
914 |
|
|
915 void |
|
|
916 run_mbox_circuit_test(void) |
|
|
917 { |
|
2
|
918 #ifdef CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT |
|
0
|
919 int i; |
|
|
920 // Set my priority lower than any I plan to create |
|
|
921 cyg_thread_set_priority(cyg_thread_self(), 3); |
|
|
922 // Set up for full mbox put/get test |
|
|
923 cyg_mbox_create(&test_mbox_handles[0], &test_mboxes[0]); |
|
|
924 cyg_semaphore_init(&synchro, 0); |
|
|
925 cyg_thread_create(2, // Priority - just a number |
|
|
926 mbox_test, // entry |
|
|
927 0, // index |
|
|
928 thread_name("thread", 0), // Name |
|
|
929 &stacks[0][0], // Stack |
|
|
930 STACK_SIZE, // Size |
|
|
931 &mbox_test_thread_handle, // Handle |
|
|
932 &mbox_test_thread // Thread data structure |
|
|
933 ); |
|
|
934 cyg_thread_resume(mbox_test_thread_handle); |
|
2
|
935 for (i = 0; i < nmboxes; i++) { |
|
0
|
936 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
|
937 HAL_CLOCK_READ(&mbox_ft[i].start); |
|
|
938 cyg_mbox_put(test_mbox_handles[0], (void *)i); |
|
|
939 cyg_semaphore_wait(&synchro); |
|
|
940 } |
|
2
|
941 cyg_thread_delete(mbox_test_thread_handle); |
|
|
942 show_times(mbox_ft, nmboxes, "Put/Get mbox"); |
|
|
943 #endif |
|
0
|
944 } |
|
|
945 |
|
|
946 void |
|
|
947 run_semaphore_tests(void) |
|
|
948 { |
|
|
949 int i; |
|
2
|
950 cyg_count32 sem_val; |
|
0
|
951 // Semaphore primitives |
|
|
952 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
953 for (i = 0; i < nsemaphores; i++) { |
|
0
|
954 HAL_CLOCK_READ(&semaphore_ft[i].start); |
|
|
955 cyg_semaphore_init(&test_semaphores[i], 0); |
|
|
956 HAL_CLOCK_READ(&semaphore_ft[i].end); |
|
|
957 } |
|
2
|
958 show_times(semaphore_ft, nsemaphores, "Init semaphore"); |
|
0
|
959 |
|
|
960 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
961 for (i = 0; i < nsemaphores; i++) { |
|
0
|
962 HAL_CLOCK_READ(&semaphore_ft[i].start); |
|
|
963 cyg_semaphore_post(&test_semaphores[i]); |
|
|
964 HAL_CLOCK_READ(&semaphore_ft[i].end); |
|
|
965 } |
|
2
|
966 show_times(semaphore_ft, nsemaphores, "Post [0] semaphore"); |
|
0
|
967 |
|
|
968 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
969 for (i = 0; i < nsemaphores; i++) { |
|
0
|
970 HAL_CLOCK_READ(&semaphore_ft[i].start); |
|
|
971 cyg_semaphore_wait(&test_semaphores[i]); |
|
|
972 HAL_CLOCK_READ(&semaphore_ft[i].end); |
|
|
973 } |
|
2
|
974 show_times(semaphore_ft, nsemaphores, "Wait [1] semaphore"); |
|
0
|
975 |
|
|
976 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
977 for (i = 0; i < nsemaphores; i++) { |
|
0
|
978 HAL_CLOCK_READ(&semaphore_ft[i].start); |
|
|
979 cyg_semaphore_trywait(&test_semaphores[i]); |
|
|
980 HAL_CLOCK_READ(&semaphore_ft[i].end); |
|
|
981 } |
|
2
|
982 show_times(semaphore_ft, nsemaphores, "Trywait [0] semaphore"); |
|
0
|
983 |
|
|
984 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
985 for (i = 0; i < nsemaphores; i++) { |
|
0
|
986 cyg_semaphore_post(&test_semaphores[i]); |
|
|
987 HAL_CLOCK_READ(&semaphore_ft[i].start); |
|
|
988 cyg_semaphore_trywait(&test_semaphores[i]); |
|
|
989 HAL_CLOCK_READ(&semaphore_ft[i].end); |
|
|
990 } |
|
2
|
991 show_times(semaphore_ft, nsemaphores, "Trywait [1] semaphore"); |
|
0
|
992 |
|
|
993 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
994 for (i = 0; i < nsemaphores; i++) { |
|
0
|
995 HAL_CLOCK_READ(&semaphore_ft[i].start); |
|
|
996 cyg_semaphore_peek(&test_semaphores[i], &sem_val); |
|
|
997 HAL_CLOCK_READ(&semaphore_ft[i].end); |
|
|
998 } |
|
2
|
999 show_times(semaphore_ft, nsemaphores, "Peek semaphore"); |
|
0
|
1000 |
|
|
1001 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
1002 for (i = 0; i < nsemaphores; i++) { |
|
0
|
1003 HAL_CLOCK_READ(&semaphore_ft[i].start); |
|
|
1004 cyg_semaphore_destroy(&test_semaphores[i]); |
|
|
1005 HAL_CLOCK_READ(&semaphore_ft[i].end); |
|
|
1006 } |
|
2
|
1007 show_times(semaphore_ft, nsemaphores, "Destroy semaphore"); |
|
0
|
1008 |
|
|
1009 run_semaphore_circuit_test(); |
|
2
|
1010 end_of_test_group(); |
|
0
|
1011 } |
|
|
1012 |
|
|
1013 void |
|
|
1014 run_semaphore_circuit_test(void) |
|
|
1015 { |
|
|
1016 int i; |
|
|
1017 // Set my priority lower than any I plan to create |
|
|
1018 cyg_thread_set_priority(cyg_thread_self(), 3); |
|
|
1019 // Set up for full semaphore post/wait test |
|
|
1020 cyg_semaphore_init(&test_semaphores[0], 0); |
|
|
1021 cyg_semaphore_init(&synchro, 0); |
|
|
1022 cyg_thread_create(2, // Priority - just a number |
|
|
1023 semaphore_test, // entry |
|
|
1024 0, // index |
|
|
1025 thread_name("thread", 0), // Name |
|
|
1026 &stacks[0][0], // Stack |
|
|
1027 STACK_SIZE, // Size |
|
|
1028 &semaphore_test_thread_handle, // Handle |
|
|
1029 &semaphore_test_thread // Thread data structure |
|
|
1030 ); |
|
|
1031 cyg_thread_resume(semaphore_test_thread_handle); |
|
2
|
1032 for (i = 0; i < nsemaphores; i++) { |
|
0
|
1033 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
|
1034 HAL_CLOCK_READ(&semaphore_ft[i].start); |
|
|
1035 cyg_semaphore_post(&test_semaphores[0]); |
|
|
1036 cyg_semaphore_wait(&synchro); |
|
|
1037 } |
|
2
|
1038 cyg_thread_delete(semaphore_test_thread_handle); |
|
|
1039 show_times(semaphore_ft, nsemaphores, "Post/Wait semaphore"); |
|
0
|
1040 } |
|
|
1041 |
|
|
1042 void |
|
|
1043 run_counter_tests(void) |
|
|
1044 { |
|
|
1045 int i; |
|
2
|
1046 cyg_tick_count_t val=0; |
|
0
|
1047 |
|
|
1048 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
1049 for (i = 0; i < ncounters; i++) { |
|
0
|
1050 HAL_CLOCK_READ(&counter_ft[i].start); |
|
|
1051 cyg_counter_create(&counters[i], &test_counters[i]); |
|
|
1052 HAL_CLOCK_READ(&counter_ft[i].end); |
|
|
1053 } |
|
2
|
1054 show_times(counter_ft, ncounters, "Create counter"); |
|
0
|
1055 |
|
|
1056 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
1057 for (i = 0; i < ncounters; i++) { |
|
0
|
1058 HAL_CLOCK_READ(&counter_ft[i].start); |
|
|
1059 val = cyg_counter_current_value(counters[i]); |
|
|
1060 HAL_CLOCK_READ(&counter_ft[i].end); |
|
|
1061 } |
|
2
|
1062 show_times(counter_ft, ncounters, "Get counter value"); |
|
0
|
1063 |
|
|
1064 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
1065 for (i = 0; i < ncounters; i++) { |
|
0
|
1066 HAL_CLOCK_READ(&counter_ft[i].start); |
|
|
1067 cyg_counter_set_value(counters[i], val); |
|
|
1068 HAL_CLOCK_READ(&counter_ft[i].end); |
|
|
1069 } |
|
2
|
1070 show_times(counter_ft, ncounters, "Set counter value"); |
|
0
|
1071 |
|
|
1072 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
1073 for (i = 0; i < ncounters; i++) { |
|
0
|
1074 HAL_CLOCK_READ(&counter_ft[i].start); |
|
|
1075 cyg_counter_tick(counters[i]); |
|
|
1076 HAL_CLOCK_READ(&counter_ft[i].end); |
|
|
1077 } |
|
2
|
1078 show_times(counter_ft, ncounters, "Tick counter"); |
|
0
|
1079 |
|
|
1080 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
1081 for (i = 0; i < ncounters; i++) { |
|
0
|
1082 HAL_CLOCK_READ(&counter_ft[i].start); |
|
|
1083 cyg_counter_delete(counters[i]); |
|
|
1084 HAL_CLOCK_READ(&counter_ft[i].end); |
|
|
1085 } |
|
2
|
1086 show_times(counter_ft, ncounters, "Delete counter"); |
|
|
1087 end_of_test_group(); |
|
0
|
1088 } |
|
|
1089 |
|
|
1090 // Alarm callback function |
|
|
1091 void |
|
|
1092 alarm_cb(cyg_handle_t alarm, cyg_addrword_t val) |
|
|
1093 { |
|
|
1094 // empty call back |
|
|
1095 } |
|
|
1096 |
|
|
1097 // Callback used to test determinancy |
|
|
1098 static volatile int alarm_cnt; |
|
|
1099 void |
|
|
1100 alarm_cb2(cyg_handle_t alarm, cyg_addrword_t indx) |
|
|
1101 { |
|
2
|
1102 if (alarm_cnt == nscheds) return; |
|
0
|
1103 sched_ft[alarm_cnt].start = 0; |
|
|
1104 HAL_CLOCK_READ(&sched_ft[alarm_cnt++].end); |
|
2
|
1105 if (alarm_cnt == nscheds) { |
|
0
|
1106 cyg_semaphore_post(&synchro); |
|
|
1107 } |
|
|
1108 } |
|
|
1109 |
|
|
1110 // Null thread, used to keep scheduler busy |
|
|
1111 void |
|
|
1112 alarm_test(cyg_uint32 id) |
|
|
1113 { |
|
|
1114 while (true) { |
|
|
1115 cyg_thread_yield(); |
|
|
1116 } |
|
|
1117 } |
|
|
1118 |
|
|
1119 void |
|
|
1120 run_alarm_tests(void) |
|
|
1121 { |
|
|
1122 int i; |
|
|
1123 cyg_tick_count_t init_val, step_val; |
|
|
1124 cyg_handle_t rtc_handle; |
|
|
1125 |
|
|
1126 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
1127 for (i = 0; i < ncounters; i++) { |
|
0
|
1128 cyg_counter_create(&counters[i], &test_counters[i]); |
|
|
1129 } |
|
2
|
1130 for (i = 0; i < nalarms; i++) { |
|
0
|
1131 HAL_CLOCK_READ(&alarm_ft[i].start); |
|
|
1132 cyg_alarm_create(counters[0], alarm_cb, 0, &alarms[i], &test_alarms[i]); |
|
|
1133 HAL_CLOCK_READ(&alarm_ft[i].end); |
|
|
1134 } |
|
2
|
1135 show_times(alarm_ft, nalarms, "Create alarm"); |
|
0
|
1136 |
|
|
1137 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
|
1138 init_val = 0; step_val = 0; |
|
2
|
1139 for (i = 0; i < nalarms; i++) { |
|
0
|
1140 HAL_CLOCK_READ(&alarm_ft[i].start); |
|
|
1141 cyg_alarm_initialize(alarms[i], init_val, step_val); |
|
|
1142 HAL_CLOCK_READ(&alarm_ft[i].end); |
|
|
1143 } |
|
2
|
1144 show_times(alarm_ft, nalarms, "Initialize alarm"); |
|
0
|
1145 |
|
|
1146 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
|
1147 init_val = 0; step_val = 0; |
|
2
|
1148 for (i = 0; i < nalarms; i++) { |
|
0
|
1149 HAL_CLOCK_READ(&alarm_ft[i].start); |
|
|
1150 cyg_alarm_disable(alarms[i]); |
|
|
1151 HAL_CLOCK_READ(&alarm_ft[i].end); |
|
|
1152 } |
|
2
|
1153 show_times(alarm_ft, nalarms, "Disable alarm"); |
|
0
|
1154 |
|
|
1155 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
|
1156 init_val = 0; step_val = 0; |
|
2
|
1157 for (i = 0; i < nalarms; i++) { |
|
0
|
1158 HAL_CLOCK_READ(&alarm_ft[i].start); |
|
|
1159 cyg_alarm_enable(alarms[i]); |
|
|
1160 HAL_CLOCK_READ(&alarm_ft[i].end); |
|
|
1161 } |
|
2
|
1162 show_times(alarm_ft, nalarms, "Enable alarm"); |
|
0
|
1163 |
|
|
1164 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
1165 for (i = 0; i < nalarms; i++) { |
|
0
|
1166 HAL_CLOCK_READ(&alarm_ft[i].start); |
|
|
1167 cyg_alarm_delete(alarms[i]); |
|
|
1168 HAL_CLOCK_READ(&alarm_ft[i].end); |
|
|
1169 } |
|
2
|
1170 show_times(alarm_ft, nalarms, "Delete alarm"); |
|
0
|
1171 |
|
|
1172 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
|
1173 cyg_counter_create(&counters[0], &test_counters[0]); |
|
|
1174 cyg_alarm_create(counters[0], alarm_cb, 0, &alarms[0], &test_alarms[0]); |
|
|
1175 init_val = 9999; step_val = 9999; |
|
|
1176 cyg_alarm_initialize(alarms[0], init_val, step_val); |
|
|
1177 cyg_alarm_enable(alarms[0]); |
|
2
|
1178 for (i = 0; i < ncounters; i++) { |
|
0
|
1179 HAL_CLOCK_READ(&counter_ft[i].start); |
|
|
1180 cyg_counter_tick(counters[0]); |
|
|
1181 HAL_CLOCK_READ(&counter_ft[i].end); |
|
|
1182 } |
|
2
|
1183 show_times(counter_ft, ncounters, "Tick counter [1 alarm]"); |
|
0
|
1184 |
|
|
1185 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
|
1186 cyg_counter_create(&counters[0], &test_counters[0]); |
|
2
|
1187 for (i = 0; i < nalarms; i++) { |
|
0
|
1188 cyg_alarm_create(counters[0], alarm_cb, 0, &alarms[i], &test_alarms[i]); |
|
|
1189 init_val = 9999; step_val = 9999; |
|
|
1190 cyg_alarm_initialize(alarms[i], init_val, step_val); |
|
|
1191 cyg_alarm_enable(alarms[i]); |
|
|
1192 } |
|
2
|
1193 for (i = 0; i < ncounters; i++) { |
|
0
|
1194 HAL_CLOCK_READ(&counter_ft[i].start); |
|
|
1195 cyg_counter_tick(counters[0]); |
|
|
1196 HAL_CLOCK_READ(&counter_ft[i].end); |
|
|
1197 } |
|
2
|
1198 show_times(counter_ft, ncounters, "Tick counter [many alarms]"); |
|
0
|
1199 |
|
|
1200 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
|
1201 cyg_counter_create(&counters[0], &test_counters[0]); |
|
|
1202 cyg_alarm_create(counters[0], alarm_cb, 0, &alarms[0], &test_alarms[0]); |
|
|
1203 init_val = 1; step_val = 1; |
|
|
1204 cyg_alarm_initialize(alarms[0], init_val, step_val); |
|
|
1205 cyg_alarm_enable(alarms[0]); |
|
2
|
1206 for (i = 0; i < ncounters; i++) { |
|
0
|
1207 HAL_CLOCK_READ(&counter_ft[i].start); |
|
|
1208 cyg_counter_tick(counters[0]); |
|
|
1209 HAL_CLOCK_READ(&counter_ft[i].end); |
|
|
1210 } |
|
2
|
1211 show_times(counter_ft, ncounters, "Tick & fire counter [1 alarm]"); |
|
0
|
1212 |
|
|
1213 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
|
1214 cyg_counter_create(&counters[0], &test_counters[0]); |
|
2
|
1215 for (i = 0; i < nalarms; i++) { |
|
0
|
1216 cyg_alarm_create(counters[0], alarm_cb, i, &alarms[i], &test_alarms[i]); |
|
|
1217 init_val = 1; step_val = 1; |
|
|
1218 cyg_alarm_initialize(alarms[i], init_val, step_val); |
|
|
1219 cyg_alarm_enable(alarms[i]); |
|
|
1220 } |
|
2
|
1221 for (i = 0; i < nalarms; i++) { |
|
|
1222 HAL_CLOCK_READ(&alarm_ft[i].start); |
|
0
|
1223 cyg_counter_tick(counters[0]); |
|
2
|
1224 HAL_CLOCK_READ(&alarm_ft[i].end); |
|
0
|
1225 } |
|
2
|
1226 for (i = 0; i < nalarms; i++) { |
|
0
|
1227 cyg_alarm_delete(alarms[i]); |
|
|
1228 } |
|
2
|
1229 show_times(alarm_ft, nalarms, "Tick & fire counters [>1 together]"); |
|
|
1230 |
|
|
1231 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
|
1232 cyg_counter_create(&counters[0], &test_counters[0]); |
|
|
1233 for (i = 0; i < nalarms; i++) { |
|
|
1234 cyg_alarm_create(counters[0], alarm_cb, i, &alarms[i], &test_alarms[i]); |
|
|
1235 init_val = i+1; step_val = nalarms+1; |
|
|
1236 cyg_alarm_initialize(alarms[i], init_val, step_val); |
|
|
1237 cyg_alarm_enable(alarms[i]); |
|
|
1238 } |
|
|
1239 for (i = 0; i < nalarms; i++) { |
|
|
1240 HAL_CLOCK_READ(&alarm_ft[i].start); |
|
|
1241 cyg_counter_tick(counters[0]); |
|
|
1242 HAL_CLOCK_READ(&alarm_ft[i].end); |
|
|
1243 } |
|
|
1244 for (i = 0; i < nalarms; i++) { |
|
|
1245 cyg_alarm_delete(alarms[i]); |
|
|
1246 } |
|
|
1247 show_times(alarm_ft, nalarms, "Tick & fire counters [>1 separately]"); |
|
0
|
1248 |
|
|
1249 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
|
1250 cyg_clock_to_counter(cyg_real_time_clock(), &rtc_handle); |
|
|
1251 cyg_alarm_create(rtc_handle, alarm_cb2, 0, &alarms[0], &test_alarms[0]); |
|
|
1252 init_val = 5; step_val = 5; alarm_cnt = 0; |
|
|
1253 cyg_alarm_initialize(alarms[0], init_val, step_val); |
|
|
1254 cyg_semaphore_init(&synchro, 0); |
|
|
1255 cyg_alarm_enable(alarms[0]); |
|
|
1256 cyg_semaphore_wait(&synchro); |
|
|
1257 cyg_alarm_disable(alarms[0]); |
|
|
1258 cyg_alarm_delete(alarms[0]); |
|
2
|
1259 show_times(sched_ft, nscheds, "Alarm latency [0 threads]"); |
|
0
|
1260 |
|
|
1261 // Set my priority higher than any I plan to create |
|
|
1262 cyg_thread_set_priority(cyg_thread_self(), 2); |
|
|
1263 for (i = 0; i < 2; i++) { |
|
|
1264 cyg_thread_create(10, // Priority - just a number |
|
|
1265 alarm_test, // entry |
|
|
1266 i, // index |
|
|
1267 thread_name("thread", i), // Name |
|
|
1268 &stacks[i][0], // Stack |
|
|
1269 STACK_SIZE, // Size |
|
|
1270 &threads[i], // Handle |
|
|
1271 &test_threads[i] // Thread data structure |
|
|
1272 ); |
|
|
1273 cyg_thread_resume(threads[i]); |
|
|
1274 } |
|
|
1275 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
|
1276 cyg_clock_to_counter(cyg_real_time_clock(), &rtc_handle); |
|
|
1277 cyg_alarm_create(rtc_handle, alarm_cb2, 0, &alarms[0], &test_alarms[0]); |
|
|
1278 init_val = 5; step_val = 5; alarm_cnt = 0; |
|
|
1279 cyg_alarm_initialize(alarms[0], init_val, step_val); |
|
|
1280 cyg_semaphore_init(&synchro, 0); |
|
|
1281 cyg_alarm_enable(alarms[0]); |
|
|
1282 cyg_semaphore_wait(&synchro); |
|
|
1283 cyg_alarm_disable(alarms[0]); |
|
|
1284 cyg_alarm_delete(alarms[0]); |
|
2
|
1285 show_times(sched_ft, nscheds, "Alarm latency [2 threads]"); |
|
0
|
1286 for (i = 0; i < 2; i++) { |
|
|
1287 cyg_thread_suspend(threads[i]); |
|
2
|
1288 cyg_thread_delete(threads[i]); |
|
0
|
1289 } |
|
|
1290 |
|
|
1291 // Set my priority higher than any I plan to create |
|
|
1292 cyg_thread_set_priority(cyg_thread_self(), 2); |
|
2
|
1293 for (i = 0; i < ntest_threads; i++) { |
|
0
|
1294 cyg_thread_create(10, // Priority - just a number |
|
|
1295 alarm_test, // entry |
|
|
1296 i, // index |
|
|
1297 thread_name("thread", i), // Name |
|
|
1298 &stacks[i][0], // Stack |
|
|
1299 STACK_SIZE, // Size |
|
|
1300 &threads[i], // Handle |
|
|
1301 &test_threads[i] // Thread data structure |
|
|
1302 ); |
|
|
1303 cyg_thread_resume(threads[i]); |
|
|
1304 } |
|
|
1305 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
|
1306 cyg_clock_to_counter(cyg_real_time_clock(), &rtc_handle); |
|
|
1307 cyg_alarm_create(rtc_handle, alarm_cb2, 0, &alarms[0], &test_alarms[0]); |
|
|
1308 init_val = 5; step_val = 5; alarm_cnt = 0; |
|
|
1309 cyg_alarm_initialize(alarms[0], init_val, step_val); |
|
|
1310 cyg_semaphore_init(&synchro, 0); |
|
|
1311 cyg_alarm_enable(alarms[0]); |
|
|
1312 cyg_semaphore_wait(&synchro); |
|
|
1313 cyg_alarm_disable(alarms[0]); |
|
|
1314 cyg_alarm_delete(alarms[0]); |
|
2
|
1315 show_times(sched_ft, nscheds, "Alarm latency [many threads]"); |
|
|
1316 for (i = 0; i < ntest_threads; i++) { |
|
0
|
1317 cyg_thread_suspend(threads[i]); |
|
2
|
1318 cyg_thread_delete(threads[i]); |
|
0
|
1319 } |
|
2
|
1320 end_of_test_group(); |
|
0
|
1321 } |
|
|
1322 |
|
|
1323 void |
|
|
1324 run_sched_tests(void) |
|
|
1325 { |
|
|
1326 int i; |
|
|
1327 |
|
|
1328 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
1329 for (i = 0; i < nscheds; i++) { |
|
0
|
1330 HAL_CLOCK_READ(&sched_ft[i].start); |
|
|
1331 cyg_scheduler_lock(); |
|
|
1332 HAL_CLOCK_READ(&sched_ft[i].end); |
|
|
1333 cyg_scheduler_unlock(); |
|
|
1334 } |
|
2
|
1335 show_times(sched_ft, nscheds, "Scheduler lock"); |
|
0
|
1336 |
|
|
1337 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
1338 for (i = 0; i < nscheds; i++) { |
|
0
|
1339 cyg_scheduler_lock(); |
|
|
1340 HAL_CLOCK_READ(&sched_ft[i].start); |
|
|
1341 cyg_scheduler_unlock(); |
|
|
1342 HAL_CLOCK_READ(&sched_ft[i].end); |
|
|
1343 } |
|
2
|
1344 show_times(sched_ft, nscheds, "Scheduler unlock [0 threads]"); |
|
0
|
1345 |
|
|
1346 // Set my priority higher than any I plan to create |
|
|
1347 cyg_thread_set_priority(cyg_thread_self(), 2); |
|
|
1348 for (i = 0; i < 1; i++) { |
|
|
1349 cyg_thread_create(10, // Priority - just a number |
|
|
1350 test0, // entry |
|
|
1351 i, // index |
|
|
1352 thread_name("thread", i), // Name |
|
|
1353 &stacks[i][0], // Stack |
|
|
1354 STACK_SIZE, // Size |
|
|
1355 &threads[i], // Handle |
|
|
1356 &test_threads[i] // Thread data structure |
|
|
1357 ); |
|
|
1358 } |
|
|
1359 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
1360 for (i = 0; i < nscheds; i++) { |
|
0
|
1361 cyg_scheduler_lock(); |
|
|
1362 HAL_CLOCK_READ(&sched_ft[i].start); |
|
|
1363 cyg_scheduler_unlock(); |
|
|
1364 HAL_CLOCK_READ(&sched_ft[i].end); |
|
|
1365 } |
|
2
|
1366 show_times(sched_ft, nscheds, "Scheduler unlock [1 suspended]"); |
|
0
|
1367 for (i = 0; i < 1; i++) { |
|
2
|
1368 cyg_thread_delete(threads[i]); |
|
0
|
1369 } |
|
|
1370 |
|
|
1371 // Set my priority higher than any I plan to create |
|
|
1372 cyg_thread_set_priority(cyg_thread_self(), 2); |
|
2
|
1373 for (i = 0; i < ntest_threads; i++) { |
|
0
|
1374 cyg_thread_create(10, // Priority - just a number |
|
|
1375 test0, // entry |
|
|
1376 i, // index |
|
|
1377 thread_name("thread", i), // Name |
|
|
1378 &stacks[i][0], // Stack |
|
|
1379 STACK_SIZE, // Size |
|
|
1380 &threads[i], // Handle |
|
|
1381 &test_threads[i] // Thread data structure |
|
|
1382 ); |
|
|
1383 } |
|
|
1384 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
1385 for (i = 0; i < nscheds; i++) { |
|
0
|
1386 cyg_scheduler_lock(); |
|
|
1387 HAL_CLOCK_READ(&sched_ft[i].start); |
|
|
1388 cyg_scheduler_unlock(); |
|
|
1389 HAL_CLOCK_READ(&sched_ft[i].end); |
|
|
1390 } |
|
2
|
1391 show_times(sched_ft, nscheds, "Scheduler unlock [many suspended]"); |
|
|
1392 for (i = 0; i < ntest_threads; i++) { |
|
|
1393 cyg_thread_delete(threads[i]); |
|
0
|
1394 } |
|
|
1395 |
|
|
1396 // Set my priority higher than any I plan to create |
|
|
1397 cyg_thread_set_priority(cyg_thread_self(), 2); |
|
2
|
1398 for (i = 0; i < ntest_threads; i++) { |
|
0
|
1399 cyg_thread_create(10, // Priority - just a number |
|
|
1400 test0, // entry |
|
|
1401 i, // index |
|
|
1402 thread_name("thread", i), // Name |
|
|
1403 &stacks[i][0], // Stack |
|
|
1404 STACK_SIZE, // Size |
|
|
1405 &threads[i], // Handle |
|
|
1406 &test_threads[i] // Thread data structure |
|
|
1407 ); |
|
|
1408 cyg_thread_resume(threads[i]); |
|
|
1409 } |
|
|
1410 wait_for_tick(); // Wait until the next clock tick to minimize aberations |
|
2
|
1411 for (i = 0; i < nscheds; i++) { |
|
0
|
1412 cyg_scheduler_lock(); |
|
|
1413 HAL_CLOCK_READ(&sched_ft[i].start); |
|
|
1414 cyg_scheduler_unlock(); |
|
|
1415 HAL_CLOCK_READ(&sched_ft[i].end); |
|
|
1416 } |
|
2
|
1417 show_times(sched_ft, nscheds, "Scheduler unlock [many low prio]"); |
|
|
1418 for (i = 0; i < ntest_threads; i++) { |
|
|
1419 cyg_thread_delete(threads[i]); |
|
0
|
1420 } |
|
2
|
1421 end_of_test_group(); |
|
0
|
1422 } |
|
|
1423 |
|
|
1424 void |
|
|
1425 run_all_tests(CYG_ADDRESS id) |
|
|
1426 { |
|
2
|
1427 int i, j; |
|
|
1428 cyg_uint32 tv[nsamples], tv0, tv1; |
|
|
1429 cyg_uint32 min_stack, max_stack, total_stack, actual_stack; |
|
|
1430 cyg_tick_count_t ticks, tick0, tick1; |
|
0
|
1431 #ifdef CYG_SCHEDULER_LOCK_TIMINGS |
|
|
1432 cyg_uint32 lock_ave, lock_max; |
|
|
1433 #endif |
|
|
1434 #ifdef HAL_CLOCK_LATENCY |
|
|
1435 cyg_int32 clock_ave; |
|
|
1436 #endif |
|
|
1437 |
|
2
|
1438 disable_clock_latency_measurement(); |
|
|
1439 diag_printf("\neCos Kernel Timings\n"); |
|
|
1440 diag_printf("Notes: all times are in microseconds (.000001) unless otherwise stated\n"); |
|
|
1441 #ifdef STATS_WITHOUT_FIRST_SAMPLE |
|
|
1442 diag_printf(" second line of results have first sample removed\n"); |
|
|
1443 #endif |
|
|
1444 |
|
|
1445 cyg_thread_delay(2); // Make sure the clock is actually running |
|
|
1446 |
|
|
1447 ns_per_system_clock = 1000000/rtc_resolution[1]; |
|
|
1448 |
|
|
1449 for (i = 0; i < nsamples; i++) { |
|
0
|
1450 HAL_CLOCK_READ(&tv[i]); |
|
|
1451 } |
|
|
1452 tv0 = 0; |
|
2
|
1453 for (i = 1; i < nsamples; i++) { |
|
|
1454 tv0 += tv[i] - tv[i-1]; |
|
0
|
1455 } |
|
2
|
1456 end_of_test_group(); |
|
0
|
1457 |
|
2
|
1458 overhead = tv0 / (nsamples-1); |
|
|
1459 diag_printf("Reading the hardware clock takes %d 'ticks' overhead\n", overhead); |
|
|
1460 diag_printf("... this value will be factored out of all other measurements\n"); |
|
0
|
1461 |
|
|
1462 // Try and measure how long the clock interrupt handling takes |
|
2
|
1463 for (i = 0; i < nsamples; i++) { |
|
|
1464 tick0 = cyg_current_time(); |
|
|
1465 while (true) { |
|
|
1466 tick1 = cyg_current_time(); |
|
|
1467 if (tick0 != tick1) break; |
|
|
1468 } |
|
|
1469 HAL_CLOCK_READ(&tv[i]); |
|
0
|
1470 } |
|
2
|
1471 tv1 = 0; |
|
|
1472 for (i = 0; i < nsamples; i++) { |
|
|
1473 tv1 += tv[i] * 1000; |
|
|
1474 } |
|
|
1475 tv1 = tv1 / nsamples; |
|
0
|
1476 tv1 -= overhead; // Adjust out the cost of getting the timer value |
|
2
|
1477 diag_printf("Clock interrupt took"); |
|
|
1478 show_ticks_in_us(tv1); |
|
|
1479 diag_printf(" microseconds (%d raw clock ticks)\n", tv1/1000); |
|
|
1480 enable_clock_latency_measurement(); |
|
0
|
1481 |
|
|
1482 ticks = cyg_current_time(); |
|
|
1483 |
|
|
1484 show_test_parameters(); |
|
|
1485 show_times_hdr(); |
|
|
1486 |
|
2
|
1487 reset_clock_latency_measurement(); |
|
|
1488 |
|
0
|
1489 run_thread_tests(); |
|
|
1490 run_sched_tests(); |
|
|
1491 run_mutex_tests(); |
|
|
1492 run_mbox_tests(); |
|
|
1493 run_semaphore_tests(); |
|
|
1494 run_counter_tests(); |
|
|
1495 run_alarm_tests(); |
|
|
1496 |
|
|
1497 #ifdef CYG_SCHEDULER_LOCK_TIMINGS |
|
|
1498 Cyg_Scheduler::get_lock_times(&lock_ave, &lock_max); |
|
2
|
1499 diag_printf("\nMax lock:"); |
|
|
1500 show_ticks_in_us(lock_max); |
|
|
1501 diag_printf(", Ave lock:"); |
|
|
1502 show_ticks_in_us(lock_ave); |
|
|
1503 diag_printf("\n"); |
|
0
|
1504 #endif |
|
|
1505 |
|
|
1506 #ifdef HAL_CLOCK_LATENCY |
|
2
|
1507 // Display latency figures in same format as all other numbers |
|
|
1508 disable_clock_latency_measurement(); |
|
|
1509 clock_ave = (total_clock_latency*1000) / total_clock_interrupts; |
|
|
1510 show_ticks_in_us(clock_ave); |
|
|
1511 show_ticks_in_us(min_clock_latency*1000); |
|
|
1512 show_ticks_in_us(max_clock_latency*1000); |
|
|
1513 show_ticks_in_us(0); |
|
|
1514 diag_printf(" Clock/interrupt latency\n\n"); |
|
|
1515 enable_clock_latency_measurement(); |
|
0
|
1516 #endif |
|
|
1517 |
|
2
|
1518 disable_clock_latency_measurement(); |
|
|
1519 min_stack = STACK_SIZE; |
|
|
1520 max_stack = 0; |
|
|
1521 total_stack = 0; |
|
|
1522 for (i = 0; i < NTEST_THREADS; i++) { |
|
|
1523 for (j = 0; j < STACK_SIZE; j++) { |
|
|
1524 if (stacks[i][j]) break; |
|
|
1525 } |
|
|
1526 actual_stack = STACK_SIZE-j; |
|
|
1527 if (actual_stack < min_stack) min_stack = actual_stack; |
|
|
1528 if (actual_stack > max_stack) max_stack = actual_stack; |
|
|
1529 total_stack += actual_stack; |
|
|
1530 } |
|
|
1531 for (j = 0; j < STACKSIZE; j++) { |
|
|
1532 if (stack[j]) break; |
|
|
1533 } |
|
|
1534 diag_printf("%5d %5d %5d (main stack: %5d) Thread stack used (%d total)\n", |
|
|
1535 total_stack/NTEST_THREADS, min_stack, max_stack, |
|
|
1536 STACKSIZE - j, STACK_SIZE); |
|
|
1537 enable_clock_latency_measurement(); |
|
|
1538 |
|
0
|
1539 ticks = cyg_current_time(); |
|
2
|
1540 diag_printf("\nTiming complete - %d ms total\n\n", (int)((ticks*ns_per_system_clock)/1000)); |
|
0
|
1541 |
|
|
1542 CYG_TEST_PASS_FINISH("Basic timing OK"); |
|
|
1543 } |
|
|
1544 |
|
|
1545 void tm_basic_main( void ) |
|
|
1546 { |
|
|
1547 CYG_TEST_INIT(); |
|
|
1548 |
|
2
|
1549 if (cyg_test_is_simulator) { |
|
|
1550 nsamples = NSAMPLES_SIM; |
|
|
1551 ntest_threads = NTEST_THREADS_SIM; |
|
|
1552 nthread_switches = NTHREAD_SWITCHES_SIM; |
|
|
1553 nmutexes = NMUTEXES_SIM; |
|
|
1554 nmboxes = NMBOXES_SIM; |
|
|
1555 nsemaphores = NSEMAPHORES_SIM; |
|
|
1556 nscheds = NSCHEDS_SIM; |
|
|
1557 ncounters = NCOUNTERS_SIM; |
|
|
1558 nalarms = NALARMS_SIM; |
|
|
1559 } else { |
|
|
1560 nsamples = NSAMPLES; |
|
|
1561 ntest_threads = NTEST_THREADS; |
|
|
1562 nthread_switches = NTHREAD_SWITCHES; |
|
|
1563 nmutexes = NMUTEXES; |
|
|
1564 nmboxes = NMBOXES; |
|
|
1565 nsemaphores = NSEMAPHORES; |
|
|
1566 nscheds = NSCHEDS; |
|
|
1567 ncounters = NCOUNTERS; |
|
|
1568 nalarms = NALARMS; |
|
|
1569 } |
|
|
1570 |
|
0
|
1571 new_thread(run_all_tests, 0); |
|
|
1572 |
|
|
1573 Cyg_Scheduler::scheduler.start(); |
|
|
1574 } |
|
|
1575 |
|
|
1576 externC void |
|
|
1577 cyg_start( void ) |
|
|
1578 { |
|
|
1579 tm_basic_main(); |
|
|
1580 } |
|
2
|
1581 |
|
|
1582 #else // CYGFUN_KERNEL_API_C |
|
|
1583 |
|
|
1584 externC void |
|
|
1585 cyg_start( void ) |
|
|
1586 { |
|
|
1587 CYG_TEST_INIT(); |
|
|
1588 CYG_TEST_PASS_FINISH("Timing tests require:\n" |
|
|
1589 "CYGFUN_KERNEL_API_C && \n" |
|
|
1590 "CYGSEM_KERNEL_SCHED_MLQUEUE &&\n" |
|
|
1591 "CYGVAR_KERNEL_COUNTERS_CLOCK &&\n" |
|
|
1592 "!CYGPKG_HAL_I386_LINUX &&\n" |
|
|
1593 "(CYGNUM_KERNEL_SCHED_PRIORITIES > 12)\n"); |
|
|
1594 } |
|
|
1595 #endif // CYGFUN_KERNEL_API_C, etc. |
|
|
1596 |
|
0
|
1597 // EOF tm_basic.cxx |