summaryrefslogtreecommitdiffstats
path: root/cpukit/rtems/src
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>2007-05-17 22:46:45 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>2007-05-17 22:46:45 +0000
commitc3330a88ee5d674b09dded32ef1ccba26a9c3034 (patch)
treef7f247449fc18bc299ef695c3503f9b7790db97a /cpukit/rtems/src
parentAdd .rh clause to extra_arg. (diff)
downloadrtems-c3330a88ee5d674b09dded32ef1ccba26a9c3034.tar.bz2
2007-05-17 Joel Sherrill <joel.sherrill@oarcorp.com>
* ChangeLog, configure.ac, libcsupport/src/__times.c, libmisc/cpuuse/cpuuse.c, libmisc/stackchk/check.c, rtems/include/rtems/rtems/ratemon.h, rtems/src/ratemongetstatus.c, rtems/src/ratemonperiod.c, rtems/src/ratemonreportstatistics.c, rtems/src/ratemonresetall.c, rtems/src/ratemontimeout.c, score/Makefile.am, score/include/rtems/score/thread.h, score/include/rtems/score/timespec.h, score/src/threaddispatch.c, score/src/threadinitialize.c, score/src/threadtickletimeslice.c, score/src/timespecdivide.c: Add nanoseconds granularity to the rate monotonic period statistics and CPU usage statistics. This capability is enabled by default although may be conditionally disabled by the user. It could be too much overhead on small targets but it does not appear to be bad in early testing. Its impact on code size has not been evaluated either. It is possible that both forms of statistics gathering could be disabled with further tweaking of the conditional compilation. * score/src/timespecdividebyinteger.c: New file.
Diffstat (limited to 'cpukit/rtems/src')
-rw-r--r--cpukit/rtems/src/ratemongetstatus.c55
-rw-r--r--cpukit/rtems/src/ratemonperiod.c154
-rw-r--r--cpukit/rtems/src/ratemonreportstatistics.c129
-rw-r--r--cpukit/rtems/src/ratemonresetall.c4
-rw-r--r--cpukit/rtems/src/ratemontimeout.c7
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;