diff options
Diffstat (limited to 'cpukit/rtems/src')
-rw-r--r-- | cpukit/rtems/src/ratemongetstatus.c | 55 | ||||
-rw-r--r-- | cpukit/rtems/src/ratemonperiod.c | 154 | ||||
-rw-r--r-- | cpukit/rtems/src/ratemonreportstatistics.c | 129 | ||||
-rw-r--r-- | cpukit/rtems/src/ratemonresetall.c | 4 | ||||
-rw-r--r-- | cpukit/rtems/src/ratemontimeout.c | 7 |
5 files changed, 288 insertions, 61 deletions
diff --git a/cpukit/rtems/src/ratemongetstatus.c b/cpukit/rtems/src/ratemongetstatus.c index d059e1ae3b..d46b133e73 100644 --- a/cpukit/rtems/src/ratemongetstatus.c +++ b/cpukit/rtems/src/ratemongetstatus.c @@ -23,6 +23,11 @@ #include <rtems/rtems/ratemon.h> #include <rtems/score/thread.h> +#if defined(RTEMS_ENABLE_NANOSECOND_RATE_MONOTONIC_STATISTICS) || \ + defined(RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS) + #include <rtems/score/timespec.h> +#endif + /*PAGE * * rtems_rate_monotonic_get_status @@ -64,15 +69,51 @@ rtems_status_code rtems_rate_monotonic_get_status( status->state = the_period->state; if ( status->state == RATE_MONOTONIC_INACTIVE ) { - status->ticks_since_last_period = 0; - status->ticks_executed_since_last_period = 0; + #ifdef RTEMS_ENABLE_NANOSECOND_RATE_MONOTONIC_STATISTICS + status->since_last_period.tv_sec = 0; + status->since_last_period.tv_nsec = 0; + #else + status->ticks_since_last_period = 0; + #endif + #ifdef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS + status->executed_since_last_period.tv_sec = 0; + status->executed_since_last_period.tv_nsec = 0; + #else + status->ticks_executed_since_last_period = 0; + #endif } else { - status->ticks_since_last_period = - _Watchdog_Ticks_since_boot - the_period->time_at_period; + /* + * Both nanoseconds granularity options have to know the uptime. + * This lets them share one single invocation of _TOD_Get_uptime(). + */ + #if defined(RTEMS_ENABLE_NANOSECOND_RATE_MONOTONIC_STATISTICS) || \ + defined(RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS) + struct timespec uptime; + _TOD_Get_uptime( &uptime ); + #endif + + #ifdef RTEMS_ENABLE_NANOSECOND_RATE_MONOTONIC_STATISTICS + _Timespec_Subtract( + &the_period->time_at_period, + &uptime, + &status->since_last_period + ); + #else + status->ticks_since_last_period = + _Watchdog_Ticks_since_boot - the_period->time_at_period; + #endif - status->ticks_executed_since_last_period = - the_period->owner->ticks_executed - - the_period->owner_ticks_executed_at_period; + #ifdef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS + _Timespec_Subtract( + &_Thread_Time_of_last_context_switch, + &uptime, + &status->executed_since_last_period + ); + #else + status->ticks_executed_since_last_period = + the_period->owner->ticks_executed - + the_period->owner_ticks_executed_at_period; + #endif } _Thread_Enable_dispatch(); diff --git a/cpukit/rtems/src/ratemonperiod.c b/cpukit/rtems/src/ratemonperiod.c index 83ae0e040d..872930e035 100644 --- a/cpukit/rtems/src/ratemonperiod.c +++ b/cpukit/rtems/src/ratemonperiod.c @@ -22,13 +22,37 @@ #include <rtems/score/object.h> #include <rtems/rtems/ratemon.h> #include <rtems/score/thread.h> +#if defined(RTEMS_ENABLE_NANOSECOND_RATE_MONOTONIC_STATISTICS) || \ + defined(RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS) + #include <rtems/score/timespec.h> + extern struct timespec _Thread_Time_of_last_context_switch; +#endif void _Rate_monotonic_Update_statistics( Rate_monotonic_Control *the_period ) { - uint32_t ticks_since_last_period; - uint32_t ticks_executed_since_last_period; + rtems_rate_monotonic_period_statistics *stats; + #ifdef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS + struct timespec executed; + #else + uint32_t ticks_executed_since_last_period; + #endif + #ifdef RTEMS_ENABLE_NANOSECOND_RATE_MONOTONIC_STATISTICS + struct timespec period_start; + struct timespec since_last_period; + #else + uint32_t ticks_since_last_period; + #endif + #if defined(RTEMS_ENABLE_NANOSECOND_RATE_MONOTONIC_STATISTICS) || \ + defined(RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS) + struct timespec uptime; + + /* + * Obtain the current time since boot + */ + _TOD_Get_uptime( &uptime ); + #endif /* * Assume we are only called in states where it is appropriate @@ -40,41 +64,92 @@ void _Rate_monotonic_Update_statistics( * Grab basic information */ - ticks_since_last_period = - _Watchdog_Ticks_since_boot - the_period->time_at_period; - - ticks_executed_since_last_period = the_period->owner->ticks_executed - - the_period->owner_ticks_executed_at_period; + #ifdef RTEMS_ENABLE_NANOSECOND_RATE_MONOTONIC_STATISTICS + period_start = the_period->time_at_period; + the_period->time_at_period = uptime; + _Timespec_Subtract( &period_start, &uptime, &since_last_period ); + #else + ticks_since_last_period = + _Watchdog_Ticks_since_boot - the_period->time_at_period; + the_period->time_at_period = _Watchdog_Ticks_since_boot; + #endif + + #ifdef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS + { + struct timespec ran; + + /* executed = current cpu usage - value at start of period */ + _Timespec_Subtract( + &the_period->owner_executed_at_period, + &_Thread_Executing->cpu_time_used, + &executed + ); + + /* How much time time since last context switch */ + _Timespec_Subtract(&_Thread_Time_of_last_context_switch, &uptime, &ran); + + /* executed += ran */ + _Timespec_Add_to( &executed, &ran ); + } + #else + ticks_executed_since_last_period = the_period->owner->ticks_executed - + the_period->owner_ticks_executed_at_period; + #endif /* * Now update the statistics */ - the_period->Statistics.count++; + stats = &the_period->Statistics; + stats->count++; + if ( the_period->state == RATE_MONOTONIC_EXPIRED ) - the_period->Statistics.missed_count++; - the_period->Statistics.total_cpu_time += ticks_executed_since_last_period; - the_period->Statistics.total_wall_time += ticks_since_last_period; + stats->missed_count++; /* * Update CPU time */ - if ( ticks_executed_since_last_period < the_period->Statistics.min_cpu_time ) - the_period->Statistics.min_cpu_time = ticks_executed_since_last_period; + #ifdef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS + _Timespec_Add_to( &stats->total_cpu_time, &executed ); + + if ( _Timespec_Less_than( &executed, &stats->min_cpu_time ) ) + stats->min_cpu_time = executed; + + if ( _Timespec_Greater_than( &executed, &stats->max_cpu_time ) ) + stats->max_cpu_time = executed; + + #else + stats->total_cpu_time += ticks_executed_since_last_period; - if ( ticks_executed_since_last_period > the_period->Statistics.max_cpu_time ) - the_period->Statistics.max_cpu_time = ticks_executed_since_last_period; + if ( ticks_executed_since_last_period < stats->min_cpu_time ) + stats->min_cpu_time = ticks_executed_since_last_period; + + if ( ticks_executed_since_last_period > stats->max_cpu_time ) + stats->max_cpu_time = ticks_executed_since_last_period; + #endif /* * Update Wall time */ - if ( ticks_since_last_period < the_period->Statistics.min_wall_time ) - the_period->Statistics.min_wall_time = ticks_since_last_period; + #ifndef RTEMS_ENABLE_NANOSECOND_RATE_MONOTONIC_STATISTICS + stats->total_wall_time += ticks_since_last_period; + + if ( ticks_since_last_period < stats->min_wall_time ) + stats->min_wall_time = ticks_since_last_period; + + if ( ticks_since_last_period > stats->max_wall_time ) + stats->max_wall_time = ticks_since_last_period; + #else + _Timespec_Add_to( &stats->total_wall_time, &since_last_period ); - if ( ticks_since_last_period > the_period->Statistics.max_wall_time ) - the_period->Statistics.max_wall_time = ticks_since_last_period; + if ( _Timespec_Less_than( &since_last_period, &stats->min_wall_time ) ) + stats->min_wall_time = since_last_period; + + if ( _Timespec_Greater_than( &since_last_period, &stats->max_wall_time ) ) + stats->max_wall_time = since_last_period; + #endif } @@ -146,6 +221,40 @@ rtems_status_code rtems_rate_monotonic_period( _ISR_Enable( level ); + #ifdef RTEMS_ENABLE_NANOSECOND_RATE_MONOTONIC_STATISTICS + /* + * Since the statistics didn't update the starting time, + * we do it here. + */ + _TOD_Get_uptime( &the_period->time_at_period ); + #else + the_period->time_at_period = _Watchdog_Ticks_since_boot; + #endif + + #ifdef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS + { + struct timespec ran, uptime; + + _TOD_Get_uptime( &uptime ); + + the_period->owner_executed_at_period = + _Thread_Executing->cpu_time_used; + + /* How much time time since last context switch */ + _Timespec_Subtract( + &_Thread_Time_of_last_context_switch, + &uptime, + &ran + ); + + /* thread had executed before the last context switch also */ + _Timespec_Add_to( &the_period->owner_executed_at_period, &ran ); + } + #else + the_period->owner_ticks_executed_at_period = + _Thread_Executing->ticks_executed; + #endif + the_period->state = RATE_MONOTONIC_ACTIVE; _Watchdog_Initialize( &the_period->Timer, @@ -154,10 +263,6 @@ rtems_status_code rtems_rate_monotonic_period( NULL ); - the_period->owner_ticks_executed_at_period = - _Thread_Executing->ticks_executed; - - the_period->time_at_period = _Watchdog_Ticks_since_boot; the_period->next_length = length; _Watchdog_Insert_ticks( &the_period->Timer, length ); @@ -216,9 +321,6 @@ rtems_status_code rtems_rate_monotonic_period( _ISR_Enable( level ); the_period->state = RATE_MONOTONIC_ACTIVE; - the_period->owner_ticks_executed_at_period = - _Thread_Executing->ticks_executed; - the_period->time_at_period = _Watchdog_Ticks_since_boot; the_period->next_length = length; _Watchdog_Insert_ticks( &the_period->Timer, length ); diff --git a/cpukit/rtems/src/ratemonreportstatistics.c b/cpukit/rtems/src/ratemonreportstatistics.c index 352bd1d946..35f3c6d30b 100644 --- a/cpukit/rtems/src/ratemonreportstatistics.c +++ b/cpukit/rtems/src/ratemonreportstatistics.c @@ -22,6 +22,15 @@ #include <rtems/bspIo.h> +#if defined(RTEMS_ENABLE_NANOSECOND_RATE_MONOTONIC_STATISTICS) || \ + defined(RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS) + #include <rtems/score/timespec.h> + + /* We print to 1/10's of milliseconds */ + #define NANOSECONDS_DIVIDER 100000 + #define PERCENT_FMT "%04" PRId32 +#endif + /* * This directive allows a thread to print the statistics information * on ALL period instances which have non-zero counts using printk. @@ -30,19 +39,36 @@ * inside and outside of RTEMS. It is presented as part of the Manager * but actually uses other services of the Manager. */ -void rtems_rate_montonic_report_statistics( void ) +void rtems_rate_monotonic_report_statistics( void ) { rtems_status_code status; rtems_id id; rtems_rate_monotonic_period_statistics the_stats; rtems_rate_monotonic_period_status the_status; char name[5]; - uint32_t ival_cpu, fval_cpu; - uint32_t ival_wall, fval_wall; - printk( - "Period information by period\n" - " ID OWNER PERIODS MISSED CPU TIME WALL TIME\n" + printk( "Period information by period\n" ); +/* +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. + printk("\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789\ +\n"); +*/ + printk( " ID OWNER COUNT MISSED CPU TIME " + #ifdef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS + " " + #endif + #ifdef RTEMS_ENABLE_NANOSECOND_RATE_MONOTONIC_STATISTICS + " " + #endif + " WALL TIME\n" ); /* @@ -64,27 +90,92 @@ void rtems_rate_montonic_report_statistics( void ) if ( the_stats.count == 0 ) continue; - ival_cpu = the_stats.total_cpu_time * 100 / the_stats.count; - name[ 0 ] = '\0'; if ( the_status.owner ) { rtems_object_get_name( the_status.owner, sizeof(name), name ); } - fval_cpu = ival_cpu % 100; - ival_cpu /= 100; - ival_wall = the_stats.total_wall_time * 100 / the_stats.count; - fval_wall = ival_wall % 100; - ival_wall /= 100; + /* + * Print part of report line that is not dependent on granularity + */ + printk( - "0x%08" PRIx32 " %4s %6" PRId32 " %3" PRId32 " " - "%" PRId32 "/%" PRId32 "/%" PRId32 ".%02" PRId32 " " - "%" PRId32 "/%" PRId32 "/%" PRId32 ".%02" PRId32 "\n", + "0x%08" PRIx32 " %4s %5" PRId32 " %6" PRId32 " ", id, name, - the_stats.count, the_stats.missed_count, - the_stats.min_cpu_time, the_stats.max_cpu_time, ival_cpu, fval_cpu, - the_stats.min_wall_time, the_stats.max_wall_time, ival_wall, fval_wall + the_stats.count, the_stats.missed_count ); + + /* + * print CPU Usage part of statistics + */ + { + #ifdef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS + struct timespec cpu_average; + + _Timespec_Divide_by_integer( + &the_stats.total_cpu_time, + the_stats.count, + &cpu_average + ); + printk( + "%" PRId32 "." PERCENT_FMT "/" /* min cpu time */ + "%" PRId32 "." PERCENT_FMT "/" /* max cpu time */ + "%" PRId32 "." PERCENT_FMT " ", /* avg cpu time */ + the_stats.min_cpu_time.tv_sec, + the_stats.min_cpu_time.tv_nsec / NANOSECONDS_DIVIDER, + the_stats.max_cpu_time.tv_sec, + the_stats.max_cpu_time.tv_nsec / NANOSECONDS_DIVIDER, + cpu_average.tv_sec, + cpu_average.tv_nsec / 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; + + printk( + "%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 + */ + { + #ifdef RTEMS_ENABLE_NANOSECOND_RATE_MONOTONIC_STATISTICS + struct timespec wall_average; + _Timespec_Divide_by_integer( + &the_stats.total_wall_time, + the_stats.count, + &wall_average + ); + printk( + "%" PRId32 "." PERCENT_FMT "/" /* min wall time */ + "%" PRId32 "." PERCENT_FMT "/" /* max wall time */ + "%" PRId32 "." PERCENT_FMT "\n", /* avg wall time */ + the_stats.min_wall_time.tv_sec, + the_stats.min_wall_time.tv_nsec / NANOSECONDS_DIVIDER, + the_stats.max_wall_time.tv_sec, + the_stats.max_wall_time.tv_nsec / NANOSECONDS_DIVIDER, + wall_average.tv_sec, + wall_average.tv_nsec / 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; + printk( + "%3" PRId32 "/%4" PRId32 "/%3" PRId32 ".%02" PRId32 "\n", + the_stats.min_wall_time, the_stats.max_wall_time, ival_wall, fval_wall + ); + #endif + } } } diff --git a/cpukit/rtems/src/ratemonresetall.c b/cpukit/rtems/src/ratemonresetall.c index 8b91ddd3e5..104b9b7604 100644 --- a/cpukit/rtems/src/ratemonresetall.c +++ b/cpukit/rtems/src/ratemonresetall.c @@ -23,9 +23,9 @@ #include <rtems/score/thread.h> /* - * rtems_rate_montonic_reset_all_statistics + * rtems_rate_monotonic_reset_all_statistics */ -void rtems_rate_montonic_reset_all_statistics( void ) +void rtems_rate_monotonic_reset_all_statistics( void ) { Objects_Id id; rtems_status_code status; diff --git a/cpukit/rtems/src/ratemontimeout.c b/cpukit/rtems/src/ratemontimeout.c index 3649d574d5..f861774f98 100644 --- a/cpukit/rtems/src/ratemontimeout.c +++ b/cpukit/rtems/src/ratemontimeout.c @@ -63,18 +63,11 @@ void _Rate_monotonic_Timeout( if ( _States_Is_waiting_for_period( the_thread->current_state ) && the_thread->Wait.id == the_period->Object.id ) { _Thread_Unblock( the_thread ); - the_period->owner_ticks_executed_at_period = - the_thread->ticks_executed; - - the_period->time_at_period = _Watchdog_Ticks_since_boot; _Watchdog_Insert_ticks( &the_period->Timer, the_period->next_length ); } else if ( the_period->state == RATE_MONOTONIC_OWNER_IS_BLOCKING ) { the_period->state = RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING; - the_period->owner_ticks_executed_at_period = - the_thread->ticks_executed; - the_period->time_at_period = _Watchdog_Ticks_since_boot; _Watchdog_Insert_ticks( &the_period->Timer, the_period->next_length ); } else the_period->state = RATE_MONOTONIC_EXPIRED; |