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