comparison packages/compat/posix/current/tests/tm_basic.cxx @ 115:6ed91473a1cd ecos-sw-2000-08-21

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