1 //==========================================================================
5 // Basic timing test / scaffolding
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
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.
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
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.
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.
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.
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####
45 // Contributors: gthomas
47 // Description: Very simple kernel timing test
48 //####DESCRIPTIONEND####
50 #include <pkgconf/kernel.h>
51 #include <pkgconf/hal.h>
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>
64 #include <cyg/infra/testcase.h>
65 #include <cyg/infra/diag.h>
67 #include <cyg/kernel/test/stackmon.h>
68 #include CYGHWR_MEMORY_LAYOUT_H
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
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)
81 #include "testaux.hxx"
83 // Structure used to keep track of times
84 typedef struct fun_times {
89 #define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL+4*1024)
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)
108 #define NTEST_THREADS 16
111 #define NSEMAPHORES 32
118 #define NTHREAD_SWITCHES 128
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
129 #define NCOUNTERS_SIM 2
130 #define NALARMS_SIM 2
133 static int ntest_threads;
134 static int nthread_switches;
137 static int nsemaphores;
140 static int ncounters;
143 static char stacks[NTEST_THREADS][STACK_SIZE];
144 static cyg_thread test_threads[NTEST_THREADS];
145 static cyg_handle_t threads[NTEST_THREADS];
147 static cyg_sem_t synchro;
148 static fun_times thread_ft[NTEST_THREADS];
150 static fun_times test2_ft[NTHREAD_SWITCHES];
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;
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;
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;
170 static fun_times sched_ft[NSCHEDS];
172 static cyg_counter test_counters[NCOUNTERS];
173 static cyg_handle_t counters[NCOUNTERS];
174 static fun_times counter_ft[NCOUNTERS];
176 static cyg_flag_t test_flags[NFLAGS];
177 static fun_times flag_ft[NFLAGS];
179 static cyg_alarm test_alarms[NALARMS];
180 static cyg_handle_t alarms[NALARMS];
181 static fun_times alarm_ft[NALARMS];
183 static long rtc_resolution[] = CYGNUM_KERNEL_COUNTERS_RTC_RESOLUTION;
184 static long ns_per_system_clock;
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;
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;
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);
213 #define max(n,m) (m > n ? n : m)
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
221 cyg_tick_count_t tv0, tv1;
222 tv0 = cyg_current_time();
224 tv1 = cyg_current_time();
225 if (tv1 != tv0) break;
229 // Display a number of ticks as microseconds
230 // Note: for improved calculation significance, values are kept in ticks*1000
232 show_ticks_in_us(cyg_uint32 ticks)
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));
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.
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.
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.
253 #if defined(CYGVAR_KERNEL_COUNTERS_CLOCK_LATENCY) && defined(HAL_CLOCK_LATENCY)
255 disable_clock_latency_measurement(void)
258 measure_clock_latency = false;
262 enable_clock_latency_measurement(void)
265 measure_clock_latency = true;
268 // Ensure that the measurements are reasonable (no startup anomalies)
270 reset_clock_latency_measurement(void)
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;
283 enable_clock_latency_measurement();
287 #define disable_clock_latency_measurement()
288 #define enable_clock_latency_measurement()
289 #define reset_clock_latency_measurement()
295 disable_clock_latency_measurement();
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();
304 show_times_detail(fun_times ft[], int nsamples, char *title, bool ignore_first)
306 int i, delta, min, max, con_ave, con_min, ave_dev;
307 int start_sample, total_samples;
308 cyg_int32 total, ave;
312 total_samples = nsamples-1;
315 total_samples = nsamples;
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;
325 delta = ft[i].end - ft[i].start;
328 if (delta < 0) delta = 0;
331 if (delta < min) min = delta;
332 if (delta > max) max = delta;
334 ave = total / total_samples;
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;
342 delta = ft[i].end - ft[i].start;
345 if (delta < 0) delta = 0;
348 if (delta < 0) delta = -delta;
351 ave_dev /= total_samples;
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;
359 delta = ft[i].end - ft[i].start;
362 if (delta < 0) delta = 0;
364 if ((delta <= (ave+ave_dev)) && (delta >= (ave-ave_dev))) con_ave++;
365 if ((delta <= (min+ave_dev)) && (delta >= (min-ave_dev))) con_min++;
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();
380 show_times(fun_times ft[], int nsamples, char *title)
382 show_times_detail(ft, nsamples, title, false);
383 #ifdef STATS_WITHOUT_FIRST_SAMPLE
384 show_times_detail(ft, nsamples, "", true);
389 show_test_parameters(void)
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);
404 enable_clock_latency_measurement();
408 end_of_test_group(void)
410 disable_clock_latency_measurement();
412 enable_clock_latency_measurement();
415 // Compute a name for a thread
417 thread_name(char *basename, int indx) {
418 return "<<NULL>>"; // Not currently used
421 // test0 - null test, never executed
423 test0(cyg_uint32 indx)
425 #ifndef CYGPKG_KERNEL_SMP_SUPPORT
426 // In SMP, somw of these threads will execute
427 diag_printf("test0.%d executed?\n", indx);
432 // test1 - empty test, simply exit. Last thread signals parent.
434 test1(cyg_uint32 indx)
436 if (indx == (cyg_uint32)(ntest_threads-1)) {
437 cyg_semaphore_post(&synchro); // Signal that last thread is dying
442 // test2 - measure thread switch times
444 test2(cyg_uint32 indx)
447 for (i = 0; i < nthread_switches; i++) {
449 HAL_CLOCK_READ(&test2_ft[i].start);
451 HAL_CLOCK_READ(&test2_ft[i].end);
456 cyg_semaphore_post(&synchro);
461 // Full-circuit mutex unlock/lock test
463 mutex_test(cyg_uint32 indx)
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);
478 // Full-circuit mbox put/get test
480 mbox_test(cyg_uint32 indx)
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));
491 // Full-circuit semaphore post/wait test
493 semaphore_test(cyg_uint32 indx)
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);
505 // This set of tests is used to measure kernel primitives that deal with threads
508 run_thread_tests(void)
513 // Set my priority higher than any I plan to create
514 cyg_thread_set_priority(cyg_thread_self(), 2);
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
522 thread_name("thread", i), // Name
523 &stacks[i][0], // Stack
525 &threads[i], // Handle
526 &test_threads[i] // Thread data structure
528 HAL_CLOCK_READ(&thread_ft[i].end);
530 show_times(thread_ft, ntest_threads, "Create thread");
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);
536 HAL_CLOCK_READ(&thread_ft[i].end);
538 show_times(thread_ft, ntest_threads, "Yield thread [all suspended]");
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);
546 show_times(thread_ft, ntest_threads, "Suspend [suspended] thread");
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);
554 show_times(thread_ft, ntest_threads, "Resume thread");
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);
562 show_times(thread_ft, ntest_threads, "Set priority");
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);
570 show_times(thread_ft, ntest_threads, "Get priority");
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);
578 show_times(thread_ft, ntest_threads, "Kill [suspended] thread");
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);
584 HAL_CLOCK_READ(&thread_ft[i].end);
586 show_times(thread_ft, ntest_threads, "Yield [no other] thread");
588 // Set my priority higher than any I plan to create
589 cyg_thread_set_priority(cyg_thread_self(), 2);
591 // Recreate the test set
592 for (i = 0; i < ntest_threads; i++) {
593 cyg_thread_create(10, // Priority - just a number
596 thread_name("thread", i), // Name
597 &stacks[i][0], // Stack
599 &threads[i], // Handle
600 &test_threads[i] // Thread data structure
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);
610 show_times(thread_ft, ntest_threads, "Resume [suspended low prio] thread");
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);
618 show_times(thread_ft, ntest_threads, "Resume [runnable low prio] thread");
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);
626 show_times(thread_ft, ntest_threads, "Suspend [runnable] thread");
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);
633 HAL_CLOCK_READ(&thread_ft[i].end);
635 show_times(thread_ft, ntest_threads, "Yield [only low prio] thread");
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);
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]);
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);
654 show_times(thread_ft, ntest_threads, "Kill [runnable] thread");
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);
662 show_times(thread_ft, ntest_threads, "Destroy [dead] thread");
664 // Recreate the test set
665 for (i = 0; i < ntest_threads; i++) {
666 cyg_thread_create(10, // Priority - just a number
669 thread_name("thread", i), // Name
670 &stacks[i][0], // Stack
672 &threads[i], // Handle
673 &test_threads[i] // Thread data structure
675 cyg_thread_resume(threads[i]);
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);
684 show_times(thread_ft, ntest_threads, "Destroy [runnable] thread");
686 // Set my priority lower than any I plan to create
687 cyg_thread_set_priority(cyg_thread_self(), 3);
689 // Set up the end-of-threads synchronizer
690 cyg_semaphore_init(&synchro, 0);
692 // Recreate the test set
693 for (i = 0; i < ntest_threads; i++) {
694 cyg_thread_create(2, // Priority - just a number
697 thread_name("thread", i), // Name
698 &stacks[i][0], // Stack
700 &threads[i], // Handle
701 &test_threads[i] // Thread data structure
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);
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]);
718 run_thread_switch_test();
723 run_thread_switch_test(void)
727 // Set up for thread context switch
728 for (i = 0; i < 2; i++) {
729 cyg_thread_create(10, // Priority - just a number
732 thread_name("thread", i), // Name
733 &stacks[i][0], // Stack
735 &threads[i], // Handle
736 &test_threads[i] // Thread data structure
738 cyg_thread_resume(threads[i]);
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");
746 for (i = 0; i < 2; i++) {
747 cyg_thread_delete(threads[i]);
752 run_mutex_tests(void)
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);
763 show_times(mutex_ft, nmutexes, "Init mutex");
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);
771 show_times(mutex_ft, nmutexes, "Lock [unlocked] mutex");
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);
779 show_times(mutex_ft, nmutexes, "Unlock [locked] mutex");
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);
787 show_times(mutex_ft, nmutexes, "Trylock [unlocked] mutex");
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);
795 show_times(mutex_ft, nmutexes, "Trylock [locked] mutex");
797 // Must unlock mutices before destroying them.
798 for (i = 0; i < nmutexes; i++) {
799 cyg_mutex_unlock(&test_mutexes[i]);
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);
808 show_times(mutex_ft, nmutexes, "Destroy mutex");
809 run_mutex_circuit_test();
814 run_mutex_circuit_test(void)
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
825 thread_name("thread", 0), // Name
826 &stacks[0][0], // Stack
828 &mutex_test_thread_handle, // Handle
829 &mutex_test_thread // Thread data structure
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);
841 cyg_thread_delete(mutex_test_thread_handle);
842 show_times(mutex_ft, nmutexes, "Unlock/Lock mutex");
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);
857 show_times(mbox_ft, nmboxes, "Create mbox");
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);
865 show_times(mbox_ft, nmboxes, "Peek [empty] mbox");
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);
874 show_times(mbox_ft, nmboxes, "Put [first] mbox");
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);
882 show_times(mbox_ft, nmboxes, "Peek [1 msg] mbox");
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);
890 show_times(mbox_ft, nmboxes, "Put [second] mbox");
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);
898 show_times(mbox_ft, nmboxes, "Peek [2 msgs] mbox");
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);
906 show_times(mbox_ft, nmboxes, "Get [first] mbox");
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);
914 show_times(mbox_ft, nmboxes, "Get [second] mbox");
915 #endif // ifdef CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT
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);
923 show_times(mbox_ft, nmboxes, "Tryput [first] mbox");
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);
931 show_times(mbox_ft, nmboxes, "Peek item [non-empty] mbox");
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);
939 show_times(mbox_ft, nmboxes, "Tryget [non-empty] mbox");
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);
947 show_times(mbox_ft, nmboxes, "Peek item [empty] mbox");
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);
955 show_times(mbox_ft, nmboxes, "Tryget [empty] mbox");
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);
963 show_times(mbox_ft, nmboxes, "Waiting to get mbox");
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);
971 show_times(mbox_ft, nmboxes, "Waiting to put mbox");
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);
979 show_times(mbox_ft, nmboxes, "Delete mbox");
981 run_mbox_circuit_test();
986 run_mbox_circuit_test(void)
988 #ifdef CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT
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
998 thread_name("thread", 0), // Name
999 &stacks[0][0], // Stack
1001 &mbox_test_thread_handle, // Handle
1002 &mbox_test_thread // Thread data structure
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);
1011 cyg_thread_delete(mbox_test_thread_handle);
1012 show_times(mbox_ft, nmboxes, "Put/Get mbox");
1017 run_semaphore_tests(void)
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);
1028 show_times(semaphore_ft, nsemaphores, "Init semaphore");
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);
1036 show_times(semaphore_ft, nsemaphores, "Post [0] semaphore");
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);
1044 show_times(semaphore_ft, nsemaphores, "Wait [1] semaphore");
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);
1052 show_times(semaphore_ft, nsemaphores, "Trywait [0] semaphore");
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);
1061 show_times(semaphore_ft, nsemaphores, "Trywait [1] semaphore");
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);
1069 show_times(semaphore_ft, nsemaphores, "Peek semaphore");
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);
1077 show_times(semaphore_ft, nsemaphores, "Destroy semaphore");
1079 run_semaphore_circuit_test();
1080 end_of_test_group();
1084 run_semaphore_circuit_test(void)
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
1095 thread_name("thread", 0), // Name
1096 &stacks[0][0], // Stack
1098 &semaphore_test_thread_handle, // Handle
1099 &semaphore_test_thread // Thread data structure
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);
1108 cyg_thread_delete(semaphore_test_thread_handle);
1109 show_times(semaphore_ft, nsemaphores, "Post/Wait semaphore");
1113 run_counter_tests(void)
1116 cyg_tick_count_t val=0;
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);
1124 show_times(counter_ft, ncounters, "Create counter");
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);
1132 show_times(counter_ft, ncounters, "Get counter value");
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);
1140 show_times(counter_ft, ncounters, "Set counter value");
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);
1148 show_times(counter_ft, ncounters, "Tick counter");
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);
1156 show_times(counter_ft, ncounters, "Delete counter");
1157 end_of_test_group();
1161 run_flag_tests(void)
1164 cyg_flag_value_t val;
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);
1172 show_times(flag_ft, nflags, "Init flag");
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);
1180 show_times(flag_ft, nflags, "Destroy flag");
1182 // Recreate the flags - reused in the remaining tests
1183 for (i = 0; i < nflags; i++) {
1184 cyg_flag_init(&test_flags[i]);
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);
1193 show_times(flag_ft, nflags, "Mask bits in flag");
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);
1201 show_times(flag_ft, nflags, "Set bits in flag [no waiters]");
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);
1210 show_times(flag_ft, nflags, "Wait for flag [AND]");
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);
1219 show_times(flag_ft, nflags, "Wait for flag [OR]");
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);
1228 show_times(flag_ft, nflags, "Wait for flag [AND/CLR]");
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);
1237 show_times(flag_ft, nflags, "Wait for flag [OR/CLR]");
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);
1246 show_times(flag_ft, nflags, "Peek on flag");
1248 // Destroy flags - no longer needed
1249 for (i = 0; i < nflags; i++) {
1250 cyg_flag_destroy(&test_flags[i]);
1252 end_of_test_group();
1255 // Alarm callback function
1257 alarm_cb(cyg_handle_t alarm, cyg_addrword_t val)
1262 // Callback used to test determinancy
1263 static volatile int alarm_cnt;
1265 alarm_cb2(cyg_handle_t alarm, cyg_addrword_t indx)
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);
1276 alarm_cb3(cyg_handle_t alarm, cyg_addrword_t indx)
1278 if (alarm_cnt == nscheds) {
1279 cyg_semaphore_post(&synchro);
1281 sched_ft[alarm_cnt].start = 0;
1282 cyg_thread_resume((cyg_handle_t)indx);
1286 // Null thread, used to keep scheduler busy
1288 alarm_test(cyg_uint32 id)
1295 // Thread that suspends itself at the first opportunity
1297 alarm_test2(cyg_uint32 id)
1299 cyg_handle_t me = cyg_thread_self();
1301 HAL_CLOCK_READ(&sched_ft[alarm_cnt++].end);
1302 cyg_thread_suspend(me);
1307 run_alarm_tests(void)
1310 cyg_tick_count_t init_val, step_val;
1311 cyg_handle_t rtc_handle;
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]);
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);
1322 show_times(alarm_ft, nalarms, "Create alarm");
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);
1331 show_times(alarm_ft, nalarms, "Initialize alarm");
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);
1340 show_times(alarm_ft, nalarms, "Disable alarm");
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);
1349 show_times(alarm_ft, nalarms, "Enable alarm");
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);
1357 show_times(alarm_ft, nalarms, "Delete alarm");
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);
1370 show_times(counter_ft, ncounters, "Tick counter [1 alarm]");
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]);
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);
1385 show_times(counter_ft, ncounters, "Tick counter [many alarms]");
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);
1398 show_times(counter_ft, ncounters, "Tick & fire counter [1 alarm]");
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]);
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);
1413 for (i = 0; i < nalarms; i++) {
1414 cyg_alarm_delete(alarms[i]);
1416 show_times(alarm_ft, nalarms, "Tick & fire counters [>1 together]");
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]);
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);
1431 for (i = 0; i < nalarms; i++) {
1432 cyg_alarm_delete(alarms[i]);
1434 show_times(alarm_ft, nalarms, "Tick & fire counters [>1 separately]");
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]");
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
1454 thread_name("thread", i), // Name
1455 &stacks[i][0], // Stack
1457 &threads[i], // Handle
1458 &test_threads[i] // Thread data structure
1460 cyg_thread_resume(threads[i]);
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]);
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
1484 thread_name("thread", i), // Name
1485 &stacks[i][0], // Stack
1487 &threads[i], // Handle
1488 &test_threads[i] // Thread data structure
1490 cyg_thread_resume(threads[i]);
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]);
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
1513 thread_name("thread", 0), // Name
1514 &stacks[0][0], // Stack
1516 &threads[0], // Handle
1517 &test_threads[0] // Thread data structure
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],
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]);
1534 end_of_test_group();
1538 run_sched_tests(void)
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();
1549 show_times(sched_ft, nscheds, "Scheduler lock");
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);
1558 show_times(sched_ft, nscheds, "Scheduler unlock [0 threads]");
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
1566 thread_name("thread", i), // Name
1567 &stacks[i][0], // Stack
1569 &threads[i], // Handle
1570 &test_threads[i] // Thread data structure
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);
1580 show_times(sched_ft, nscheds, "Scheduler unlock [1 suspended]");
1581 for (i = 0; i < 1; i++) {
1582 cyg_thread_delete(threads[i]);
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
1591 thread_name("thread", i), // Name
1592 &stacks[i][0], // Stack
1594 &threads[i], // Handle
1595 &test_threads[i] // Thread data structure
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);
1605 show_times(sched_ft, nscheds, "Scheduler unlock [many suspended]");
1606 for (i = 0; i < ntest_threads; i++) {
1607 cyg_thread_delete(threads[i]);
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
1616 thread_name("thread", i), // Name
1617 &stacks[i][0], // Stack
1619 &threads[i], // Handle
1620 &test_threads[i] // Thread data structure
1622 cyg_thread_resume(threads[i]);
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);
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]);
1635 end_of_test_group();
1639 _run_all_tests(CYG_ADDRESS id)
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;
1648 #if defined(CYGVAR_KERNEL_COUNTERS_CLOCK_LATENCY) && defined(HAL_CLOCK_LATENCY)
1649 cyg_int32 clock_ave;
1652 disable_clock_latency_measurement();
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();
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");
1667 cyg_thread_delay(2); // Make sure the clock is actually running
1669 ns_per_system_clock = 1000000/rtc_resolution[1];
1672 for (i = 0; i < nsamples; i++) {
1673 HAL_CLOCK_READ(&tv[i]);
1676 for (i = 1; i < nsamples; i++) {
1677 tv0 += tv[i] - tv[i-1];
1679 end_of_test_group();
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");
1685 // Try and measure how long the clock interrupt handling takes
1686 for (i = 0; i < nsamples; i++) {
1687 tick0 = cyg_current_time();
1689 tick1 = cyg_current_time();
1690 if (tick0 != tick1) break;
1692 HAL_CLOCK_READ(&tv[i]);
1695 for (i = 0; i < nsamples; i++) {
1696 tv1 += tv[i] * 1000;
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();
1705 ticks = cyg_current_time();
1707 show_test_parameters();
1710 reset_clock_latency_measurement();
1716 run_semaphore_tests();
1717 run_counter_tests();
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);
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();
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();
1753 #ifndef CYGPKG_KERNEL_SMP_SUPPORT
1754 disable_clock_latency_measurement();
1755 min_stack = STACK_SIZE;
1758 for (i = 0; i < (int)NTEST_THREADS; i++) {
1759 for (j = 0; j < STACK_SIZE; j++) {
1760 if (stacks[i][j]) break;
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;
1767 for (j = 0; j < STACKSIZE; j++) {
1768 if (((char *)stack[0])[j]) break;
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);
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" );
1779 enable_clock_latency_measurement();
1781 ticks = cyg_current_time();
1782 diag_printf("\nTiming complete - %d ms total\n\n", (int)((ticks*ns_per_system_clock)/1000));
1786 run_all_tests(CYG_ADDRESS id)
1788 #if CYGNUM_TESTS_RUN_COUNT < 0
1792 for (i = 0; i < CYGNUM_TESTS_RUN_COUNT; i++)
1795 CYG_TEST_PASS_FINISH("Basic timing OK");
1798 void tm_basic_main( void )
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;
1814 nsamples = NSAMPLES;
1815 ntest_threads = NTEST_THREADS;
1816 nthread_switches = NTHREAD_SWITCHES;
1817 nmutexes = NMUTEXES;
1819 nsemaphores = NSEMAPHORES;
1822 ncounters = NCOUNTERS;
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);
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);
1844 new_thread(run_all_tests, 0);
1846 Cyg_Scheduler::scheduler.start();
1850 #ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
1852 cyg_hal_invoke_constructors();
1858 #ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
1859 cyg_hal_invoke_constructors();
1864 #else // CYGFUN_KERNEL_API_C
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");
1878 #endif // CYGFUN_KERNEL_API_C, etc.