Mercurial > ecos-v2_0-branch
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 |
