diff options
Diffstat (limited to 'cpukit/rtems/src/ratemonreportstatistics.c')
-rw-r--r-- | cpukit/rtems/src/ratemonreportstatistics.c | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/cpukit/rtems/src/ratemonreportstatistics.c b/cpukit/rtems/src/ratemonreportstatistics.c new file mode 100644 index 0000000000..fe65151d04 --- /dev/null +++ b/cpukit/rtems/src/ratemonreportstatistics.c @@ -0,0 +1,209 @@ +/* + * Rate Monotonic Manager -- Report Statistics for All Periods + * + * COPYRIGHT (c) 1989-2010. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems.h> +#include <stdlib.h> +#include <ctype.h> +#include <inttypes.h> + +#include <rtems/bspIo.h> +#include <rtems/score/timespec.h> + +#ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__ + /* We print to 1/10's of milliseconds */ + #define NANOSECONDS_DIVIDER 1000 + #define PERCENT_FMT "%04" PRId32 + #define NANOSECONDS_FMT "%06" PRId32 +#endif + +/* + * This directive allows a thread to print the statistics information + * on ALL period instances which have non-zero counts using printk. + * + * The implementation of this directive straddles the fence between + * inside and outside of RTEMS. It is presented as part of the Manager + * but actually uses other services of the Manager. + */ +void rtems_rate_monotonic_report_statistics_with_plugin( + void *context, + rtems_printk_plugin_t print +) +{ + rtems_status_code status; + rtems_id id; + rtems_rate_monotonic_period_statistics the_stats; + rtems_rate_monotonic_period_status the_status; + char name[5]; + + if ( !print ) + return; + + (*print)( context, "Period information by period\n" ); + #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__ + (*print)( context, "--- CPU times are in seconds ---\n" ); + (*print)( context, "--- Wall times are in seconds ---\n" ); + #endif +/* +Layout by columns -- in memory of Hollerith :) + +1234567890123456789012345678901234567890123456789012345678901234567890123456789\ + ID OWNER COUNT MISSED X +ididididid NNNN ccccc mmmmmm X + + Uncomment the following if you are tinkering with the formatting. + Be sure to test the various cases. + (*print)( context,"\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789\ +\n"); +*/ + (*print)( context, " ID OWNER COUNT MISSED " + #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__ + " " + #endif + "CPU TIME " + #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__ + " " + #endif + " WALL TIME\n" + ); + (*print)( context, " " + #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__ + " " + #endif + "MIN/MAX/AVG " + #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__ + " " + #endif + " MIN/MAX/AVG\n" + ); + + /* + * Cycle through all possible ids and try to report on each one. If it + * is a period that is inactive, we just get an error back. No big deal. + */ + for ( id=_Rate_monotonic_Information.minimum_id ; + id <= _Rate_monotonic_Information.maximum_id ; + id++ ) { + status = rtems_rate_monotonic_get_statistics( id, &the_stats ); + if ( status != RTEMS_SUCCESSFUL ) + continue; + + /* If the above passed, so should this but check it anyway */ + #if defined(RTEMS_DEBUG) + status = rtems_rate_monotonic_get_status( id, &the_status ); + if ( status != RTEMS_SUCCESSFUL ) + continue; + #else + (void) rtems_rate_monotonic_get_status( id, &the_status ); + #endif + + rtems_object_get_name( the_status.owner, sizeof(name), name ); + + /* + * Print part of report line that is not dependent on granularity + */ + (*print)( context, + "0x%08" PRIx32 " %4s %5" PRId32 " %6" PRId32 " ", + id, name, + the_stats.count, the_stats.missed_count + ); + + /* + * If the count is zero, don't print statistics + */ + if (the_stats.count == 0) { + (*print)( context, "\n" ); + continue; + } + + /* + * print CPU Usage part of statistics + */ + { + #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__ + struct timespec cpu_average; + struct timespec *min_cpu = &the_stats.min_cpu_time; + struct timespec *max_cpu = &the_stats.max_cpu_time; + struct timespec *total_cpu = &the_stats.total_cpu_time; + + _Timespec_Divide_by_integer( total_cpu, the_stats.count, &cpu_average ); + (*print)( context, + "%" PRId32 "." NANOSECONDS_FMT "/" /* min cpu time */ + "%" PRId32 "." NANOSECONDS_FMT "/" /* max cpu time */ + "%" PRId32 "." NANOSECONDS_FMT " ", /* avg cpu time */ + _Timespec_Get_seconds( min_cpu ), + _Timespec_Get_nanoseconds( min_cpu ) / NANOSECONDS_DIVIDER, + _Timespec_Get_seconds( max_cpu ), + _Timespec_Get_nanoseconds( max_cpu ) / NANOSECONDS_DIVIDER, + _Timespec_Get_seconds( &cpu_average ), + _Timespec_Get_nanoseconds( &cpu_average ) / NANOSECONDS_DIVIDER + ); + #else + uint32_t ival_cpu, fval_cpu; + + ival_cpu = the_stats.total_cpu_time * 100 / the_stats.count; + fval_cpu = ival_cpu % 100; + ival_cpu /= 100; + + (*print)( context, + "%3" PRId32 "/%4" PRId32 "/%3" PRId32 ".%02" PRId32 " ", + the_stats.min_cpu_time, the_stats.max_cpu_time, ival_cpu, fval_cpu + ); + #endif + } + + /* + * print wall time part of statistics + */ + { + #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__ + struct timespec wall_average; + struct timespec *min_wall = &the_stats.min_wall_time; + struct timespec *max_wall = &the_stats.max_wall_time; + struct timespec *total_wall = &the_stats.total_wall_time; + + _Timespec_Divide_by_integer(total_wall, the_stats.count, &wall_average); + (*print)( context, + "%" PRId32 "." NANOSECONDS_FMT "/" /* min wall time */ + "%" PRId32 "." NANOSECONDS_FMT "/" /* max wall time */ + "%" PRId32 "." NANOSECONDS_FMT "\n", /* avg wall time */ + _Timespec_Get_seconds( min_wall ), + _Timespec_Get_nanoseconds( min_wall ) / NANOSECONDS_DIVIDER, + _Timespec_Get_seconds( max_wall ), + _Timespec_Get_nanoseconds( max_wall ) / NANOSECONDS_DIVIDER, + _Timespec_Get_seconds( &wall_average ), + _Timespec_Get_nanoseconds( &wall_average ) / NANOSECONDS_DIVIDER + ); + #else + uint32_t ival_wall, fval_wall; + + ival_wall = the_stats.total_wall_time * 100 / the_stats.count; + fval_wall = ival_wall % 100; + ival_wall /= 100; + (*print)( context, + "%3" PRId32 "/%4" PRId32 "/%3" PRId32 ".%02" PRId32 "\n", + the_stats.min_wall_time, the_stats.max_wall_time, ival_wall, fval_wall + ); + #endif + } + } +} + +void rtems_rate_monotonic_report_statistics( void ) +{ + rtems_rate_monotonic_report_statistics_with_plugin( NULL, printk_plugin ); +} |