📄 tm_basic.cxx
字号:
//==========================================================================//// tm_basic.cxx//// Basic timing test / scaffolding////==========================================================================//####COPYRIGHTBEGIN####// // ------------------------------------------- // The contents of this file are subject to the Red Hat eCos Public License // Version 1.1 (the "License"); you may not use this file except in // compliance with the License. You may obtain a copy of the License at // http://www.redhat.com/ // // 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 Configurable Operating System, // released September 30, 1998. // // The Initial Developer of the Original Code is Red Hat. // Portions created by Red Hat are // Copyright (C) 1998, 1999, 2000 Red Hat, Inc. // 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 <pkgconf/hal.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>#include <cyg/kernel/test/stackmon.h>#include CYGHWR_MEMORY_LAYOUT_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) && \ !defined(CYGDBG_INFRA_DIAG_USE_DEVICE) && \ (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 STACK_SIZE CYGNUM_HAL_STACK_SIZE_MINIMUM#ifdef CYGMEM_REGION_ram_SIZE#define CYG_THREAD_OVERHEAD (STACK_SIZE+sizeof(cyg_thread)+(sizeof(fun_times)*2))#define NTEST_THREADS ((CYGMEM_REGION_ram_SIZE/16)/CYG_THREAD_OVERHEAD)#define CYG_MUTEX_OVERHEAD (sizeof(cyg_mutex_t)+sizeof(fun_times))#define NMUTEXES ((CYGMEM_REGION_ram_SIZE/16)/CYG_MUTEX_OVERHEAD)#define CYG_MBOX_OVERHEAD (sizeof(cyg_mbox)+sizeof(fun_times))#define NMBOXES ((CYGMEM_REGION_ram_SIZE/24)/CYG_MBOX_OVERHEAD)#define CYG_SEMAPHORE_OVERHEAD (sizeof(cyg_sem_t)+sizeof(fun_times))#define NSEMAPHORES ((CYGMEM_REGION_ram_SIZE/16)/CYG_SEMAPHORE_OVERHEAD)#define CYG_COUNTER_OVERHEAD (sizeof(cyg_counter)+sizeof(fun_times))#define NCOUNTERS ((CYGMEM_REGION_ram_SIZE/24)/CYG_COUNTER_OVERHEAD)#define CYG_ALARM_OVERHEAD (sizeof(cyg_alarm)+sizeof(fun_times))#define NALARMS ((CYGMEM_REGION_ram_SIZE/16)/CYG_ALARM_OVERHEAD)#else// Defaults#define NTEST_THREADS 16#define NMUTEXES 32#define NMBOXES 32#define NSEMAPHORES 32#define NCOUNTERS 32#define NALARMS 32#endif#define NSAMPLES 32#define NTHREAD_SWITCHES 128#define NSCHEDS 128#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;static 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;#if defined(CYGVAR_KERNEL_COUNTERS_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;#endif#if defined(CYGVAR_KERNEL_COUNTERS_CLOCK_DSR_LATENCY)extern cyg_tick_count total_clock_dsr_latency, total_clock_dsr_calls;extern cyg_int32 min_clock_dsr_latency, max_clock_dsr_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);#ifndef max#define max(n,m) (m > n ? n : m)#endif// 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.#if defined(CYGVAR_KERNEL_COUNTERS_CLOCK_LATENCY) && defined(HAL_CLOCK_LATENCY)voiddisable_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;#if defined(CYGVAR_KERNEL_COUNTERS_CLOCK_DSR_LATENCY) total_clock_dsr_latency = 0; total_clock_dsr_calls = 0; min_clock_dsr_latency = 0x7FFFFFFF; max_clock_dsr_latency = 0;#endif 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -