📄 tm_basic.cxx
字号:
//==========================================================================//// tm_basic.cxx//// Basic timing test / scaffolding////==========================================================================//####COPYRIGHTBEGIN####//// -------------------------------------------// The contents of this file are subject to the Cygnus eCos Public License// Version 1.0 (the "License"); you may not use this file except in// compliance with the License. You may obtain a copy of the License at// http://sourceware.cygnus.com/ecos// // Software distributed under the License is distributed on an "AS IS"// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the// License for the specific language governing rights and limitations under// the License.// // The Original Code is eCos - Embedded Cygnus Operating System, released// September 30, 1998.// // The Initial Developer of the Original Code is Cygnus. Portions created// by Cygnus are Copyright (C) 1998,1999 Cygnus Solutions. All Rights Reserved.// -------------------------------------------////####COPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s): gthomas// Contributors: gthomas// Date: 1998-10-19// Description: Very simple kernel timing test//####DESCRIPTIONEND#####include <pkgconf/kernel.h>#include <cyg/kernel/sched.hxx>#include <cyg/kernel/thread.hxx>#include <cyg/kernel/thread.inl>#include <cyg/kernel/mutex.hxx>#include <cyg/kernel/sema.hxx>#include <cyg/kernel/sched.inl>#include <cyg/kernel/clock.hxx>#include <cyg/kernel/clock.inl>#include <cyg/kernel/kapi.h>#include <cyg/infra/testcase.h>// Define this to see the statistics with the first sample datum removed.// This can expose the effects of caches on the speed of operations.#undef STATS_WITHOUT_FIRST_SAMPLE#if defined(CYGFUN_KERNEL_API_C) && \ defined(CYGSEM_KERNEL_SCHED_MLQUEUE) && \ defined(CYGVAR_KERNEL_COUNTERS_CLOCK) && \ !defined(CYGPKG_HAL_I386_LINUX) && \ (CYGNUM_KERNEL_SCHED_PRIORITIES > 12)#define NTHREADS 1#include "testaux.hxx"// Structure used to keep track of timestypedef struct fun_times { cyg_uint32 start; cyg_uint32 end;} fun_times;#define NSAMPLES 32#define NTEST_THREADS 24#define NTHREAD_SWITCHES 128#define NMUTEXES 32#define NMBOXES 32#define NSEMAPHORES 32#define NSCHEDS 128#define NCOUNTERS 32#define NALARMS 32#define NSAMPLES_SIM 2#define NTEST_THREADS_SIM 2#define NTHREAD_SWITCHES_SIM 4#define NMUTEXES_SIM 2#define NMBOXES_SIM 2#define NSEMAPHORES_SIM 2#define NSCHEDS_SIM 4#define NCOUNTERS_SIM 2#define NALARMS_SIM 2static int nsamples;static int ntest_threads;static int nthread_switches;static int nmutexes;static int nmboxes;static int nsemaphores;static int nscheds;static int ncounters;static int nalarms;#define STACK_SIZE CYGNUM_HAL_STACK_SIZE_MINIMUMstatic char stacks[NTEST_THREADS][STACK_SIZE];static cyg_thread test_threads[NTEST_THREADS];static cyg_handle_t threads[NTEST_THREADS];static int overhead;static cyg_sem_t synchro;static fun_times thread_ft[NTEST_THREADS];static fun_times test2_ft[NTHREAD_SWITCHES];static cyg_mutex_t test_mutexes[NMUTEXES];static fun_times mutex_ft[NMUTEXES];static cyg_thread mutex_test_thread;static cyg_handle_t mutex_test_thread_handle;static cyg_mbox test_mboxes[NMBOXES];static cyg_handle_t test_mbox_handles[NMBOXES];static fun_times mbox_ft[NMBOXES];static cyg_thread mbox_test_thread;static cyg_handle_t mbox_test_thread_handle;static cyg_sem_t test_semaphores[NSEMAPHORES];static fun_times semaphore_ft[NSEMAPHORES];static cyg_thread semaphore_test_thread;static cyg_handle_t semaphore_test_thread_handle;static fun_times sched_ft[NSCHEDS];static cyg_counter test_counters[NCOUNTERS];static cyg_handle_t counters[NCOUNTERS];static fun_times counter_ft[NCOUNTERS];static cyg_alarm test_alarms[NALARMS];static cyg_handle_t alarms[NALARMS];static fun_times alarm_ft[NALARMS];static long rtc_resolution[] = CYGNUM_KERNEL_COUNTERS_RTC_RESOLUTION;static long ns_per_system_clock;#ifdef HAL_CLOCK_LATENCY// Data kept by kernel real time clock measuring clock interrupt latencyextern cyg_tick_count total_clock_latency, total_clock_interrupts;extern cyg_int32 min_clock_latency, max_clock_latency;extern bool measure_clock_latency;#endifexternC void diag_printf(const char *, ...);void run_sched_tests(void);void run_thread_tests(void);void run_thread_switch_test(void);void run_mutex_tests(void);void run_mutex_circuit_test(void);void run_mbox_tests(void);void run_mbox_circuit_test(void);void run_semaphore_tests(void);void run_semaphore_circuit_test(void);void run_counter_tests(void);void run_alarm_tests(void);// Wait until a clock tick [real time clock] has passed. This should keep it// from happening again during a measurement, thus minimizing any fluctuationsvoidwait_for_tick(void){ cyg_tick_count_t tv0, tv1; tv0 = cyg_current_time(); while (true) { tv1 = cyg_current_time(); if (tv1 != tv0) break; }}// Display a number of ticks as microseconds// Note: for improved calculation significance, values are kept in ticks*1000voidshow_ticks_in_us(cyg_uint32 ticks){ long long ns; ns = (ns_per_system_clock * (long long)ticks) / CYGNUM_KERNEL_COUNTERS_RTC_PERIOD; ns += 5; // for rounding to .01us diag_printf("%5d.%02d", (int)(ns/1000), (int)((ns%1000)/10));}//// If the kernel is instrumented to measure clock interrupt latency, these// measurements can be drastically perturbed by printing via "diag_printf()"// since that code may run with interrupts disabled for long periods.//// In order to get accurate/reasonable latency figures _for the kernel // primitive functions beint tested_, the kernel's latency measurements// are suspended while the printing actually takes place.//// The measurements are reenabled after the printing, thus allowing for// fair measurements of the kernel primitives, which are not distorted// by the printing mechanisms.#ifdef HAL_CLOCK_LATENCYvoiddisable_clock_latency_measurement(void){ wait_for_tick(); measure_clock_latency = false;}voidenable_clock_latency_measurement(void){ wait_for_tick(); measure_clock_latency = true;}// Ensure that the measurements are reasonable (no startup anomalies)voidreset_clock_latency_measurement(void){ disable_clock_latency_measurement(); total_clock_latency = 0; total_clock_interrupts = 0; min_clock_latency = 0x7FFFFFFF; max_clock_latency = 0; enable_clock_latency_measurement();}#else#define disable_clock_latency_measurement()#define enable_clock_latency_measurement()#define reset_clock_latency_measurement()#endifvoidshow_times_hdr(void){ disable_clock_latency_measurement(); diag_printf("\n"); diag_printf(" Confidence\n"); diag_printf(" Ave Min Max Var Ave Min Function\n"); diag_printf(" ====== ====== ====== ====== ========== ========\n"); enable_clock_latency_measurement();}voidshow_times_detail(fun_times ft[], int nsamples, char *title, bool ignore_first){ int i, delta, min, max, con_ave, con_min, ave_dev; int start_sample, total_samples; cyg_int32 total, ave; if (ignore_first) { start_sample = 1; total_samples = nsamples-1; } else { start_sample = 0; total_samples = nsamples; } total = 0; min = 0x7FFFFFFF; max = 0; for (i = start_sample; i < nsamples; i++) { if (ft[i].end < ft[i].start) { // Clock wrapped around (timer tick) delta = (ft[i].end+CYGNUM_KERNEL_COUNTERS_RTC_PERIOD) - ft[i].start; } else { delta = ft[i].end - ft[i].start; } delta -= overhead; if (delta < 0) delta = 0; delta *= 1000; total += delta; if (delta < min) min = delta; if (delta > max) max = delta; } ave = total / total_samples; total = 0; ave_dev = 0; for (i = start_sample; i < nsamples; i++) { if (ft[i].end < ft[i].start) { // Clock wrapped around (timer tick) delta = (ft[i].end+CYGNUM_KERNEL_COUNTERS_RTC_PERIOD) - ft[i].start; } else { delta = ft[i].end - ft[i].start; } delta -= overhead; if (delta < 0) delta = 0; delta *= 1000; delta = delta - ave; if (delta < 0) delta = -delta; ave_dev += delta; } ave_dev /= total_samples; con_ave = 0; con_min = 0; for (i = start_sample; i < nsamples; i++) { if (ft[i].end < ft[i].start) { // Clock wrapped around (timer tick) delta = (ft[i].end+CYGNUM_KERNEL_COUNTERS_RTC_PERIOD) - ft[i].start; } else { delta = ft[i].end - ft[i].start; } delta -= overhead; if (delta < 0) delta = 0; delta *= 1000; if ((delta <= (ave+ave_dev)) && (delta >= (ave-ave_dev))) con_ave++; if ((delta <= (min+ave_dev)) && (delta >= (min-ave_dev))) con_min++; } con_ave = (con_ave * 100) / total_samples; con_min = (con_min * 100) / total_samples; show_ticks_in_us(ave); show_ticks_in_us(min); show_ticks_in_us(max); show_ticks_in_us(ave_dev); disable_clock_latency_measurement(); diag_printf(" %3d%% %3d%%", con_ave, con_min); diag_printf(" %s\n", title); enable_clock_latency_measurement();}voidshow_times(fun_times ft[], int nsamples, char *title){ show_times_detail(ft, nsamples, title, false);#ifdef STATS_WITHOUT_FIRST_SAMPLE show_times_detail(ft, nsamples, "", true);#endif}voidshow_test_parameters(void){ disable_clock_latency_measurement(); diag_printf("\nTesting parameters:\n"); diag_printf(" Clock samples: %3d\n", nsamples); diag_printf(" Threads: %3d\n", ntest_threads); diag_printf(" Thread switches: %3d\n", nthread_switches); diag_printf(" Mutexes: %3d\n", nmutexes); diag_printf(" Mailboxes: %3d\n", nmboxes); diag_printf(" Semaphores: %3d\n", nsemaphores); diag_printf(" Scheduler operations: %3d\n", nscheds); diag_printf(" Counters: %3d\n", ncounters); diag_printf(" Alarms: %3d\n", nalarms); diag_printf("\n"); enable_clock_latency_measurement();}voidend_of_test_group(void){ disable_clock_latency_measurement(); diag_printf("\n"); enable_clock_latency_measurement();}// Compute a name for a threadchar *thread_name(char *basename, int indx) { return "<<NULL>>"; // Not currently used}// test0 - null test, never executedvoidtest0(cyg_uint32 indx){ diag_printf("test0.%d executed?\n", indx); cyg_thread_exit();}// test1 - empty test, simply exit. Last thread signals parent.voidtest1(cyg_uint32 indx){ if (indx == (cyg_uint32)(ntest_threads-1)) { cyg_semaphore_post(&synchro); // Signal that last thread is dying } cyg_thread_exit();}// test2 - measure thread switch timesvoidtest2(cyg_uint32 indx){ int i; for (i = 0; i < nthread_switches; i++) { if (indx == 0) { HAL_CLOCK_READ(&test2_ft[i].start); } else { HAL_CLOCK_READ(&test2_ft[i].end); } cyg_thread_yield(); } if (indx == 1) { cyg_semaphore_post(&synchro); } cyg_thread_exit();}// Full-circuit mutex unlock/lock testvoidmutex_test(cyg_uint32 indx){ int i;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -