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.
This commit is contained in:
Joel Sherrill
2007-05-17 22:46:45 +00:00
parent e57739da09
commit c3330a88ee
19 changed files with 696 additions and 191 deletions

View File

@@ -26,7 +26,18 @@
#include <rtems/cpuuse.h>
#include <rtems/bspIo.h>
uint32_t CPU_usage_Ticks_at_last_reset;
#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
#ifndef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS
uint32_t CPU_usage_Ticks_at_last_reset;
#endif
/*PAGE
*
@@ -41,27 +52,38 @@ void rtems_cpu_usage_report( void )
Objects_Information *information;
char name[5];
uint32_t ival, fval;
uint32_t total_units = 0;
#ifdef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS
struct timespec uptime;
#else
uint32_t total_units = 0;
#endif
for ( api_index = 1 ;
api_index <= OBJECTS_APIS_LAST ;
api_index++ ) {
if ( !_Objects_Information_table[ api_index ] )
continue;
information = _Objects_Information_table[ api_index ][ 1 ];
if ( information ) {
for ( i=1 ; i <= information->maximum ; i++ ) {
the_thread = (Thread_Control *)information->local_table[ i ];
/*
* When not using nanosecond CPU usage resolution, we have to count
* the number of "ticks" we gave credit for to give the user a rough
* guideline as to what each number means proportionally.
*/
#ifdef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS
_TOD_Get_uptime( &uptime );
#else
for ( api_index = 1 ; api_index <= OBJECTS_APIS_LAST ; api_index++ ) {
if ( !_Objects_Information_table[ api_index ] )
continue;
information = _Objects_Information_table[ api_index ][ 1 ];
if ( information ) {
for ( i=1 ; i <= information->maximum ; i++ ) {
the_thread = (Thread_Control *)information->local_table[ i ];
if ( the_thread )
total_units += the_thread->ticks_executed;
if ( the_thread )
total_units += the_thread->ticks_executed;
}
}
}
}
#endif
printk( "CPU Usage by thread\n"
" ID NAME TICKS PERCENT\n"
);
" ID NAME TICKS PERCENT\n"
);
for ( api_index = 1 ;
api_index <= OBJECTS_APIS_LAST ;
@@ -77,36 +99,61 @@ void rtems_cpu_usage_report( void )
continue;
rtems_object_get_name( the_thread->Object.id, sizeof(name), name );
printk( "0x%08" PRIx32 " %4s ", the_thread->Object.id, name );
ival = total_units ?
the_thread->ticks_executed * 10000 / total_units : 0;
fval = ival % 100;
ival /= 100;
printk(
"0x%08" PRIx32 " %4s %8" PRId32 " %3" PRId32
".%02" PRId32"\n",
the_thread->Object.id,
name,
the_thread->ticks_executed,
ival,
fval
);
#ifdef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS
_Timespec_Divide( &the_thread->cpu_time_used, &uptime, &ival, &fval );
printk(
"%" PRId32 ".%06d" /* cpu time used */
" %3" PRId32 ".%02" PRId32 "\n", /* percentage */
the_thread->cpu_time_used.tv_sec,
the_thread->cpu_time_used.tv_nsec /
TOD_NANOSECONDS_PER_MICROSECOND,
ival,
fval
);
#else
ival = (total_units) ?
the_thread->ticks_executed * 10000 / total_units : 0;
fval = ival % 100;
ival /= 100;
printk(
"%8" PRId32 " %3" PRId32 ".%02" PRId32"\n",
the_thread->ticks_executed,
ival,
fval
);
#endif
}
}
}
printk(
"\nTicks since last reset = %" PRId32 "\n",
_Watchdog_Ticks_since_boot - CPU_usage_Ticks_at_last_reset
);
printk( "\nTotal Units = %" PRId32 "\n", total_units );
#ifdef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS
printk( "Uptime %d.%06d seconds\n\n",
uptime.tv_sec,
uptime.tv_nsec / TOD_NANOSECONDS_PER_MICROSECOND
);
#else
printk(
"Ticks since last reset = %" PRId32 "\n",
_Watchdog_Ticks_since_boot - CPU_usage_Ticks_at_last_reset
);
printk( "Total Units = %" PRId32 "\n\n", total_units );
#endif
}
static void CPU_usage_Per_thread_handler(
Thread_Control *the_thread
)
{
the_thread->ticks_executed = 0;
#ifdef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS
the_thread->cpu_time_used.tv_sec = 0;
the_thread->cpu_time_used.tv_nsec = 0;
#else
the_thread->ticks_executed = 0;
#endif
}
/*
@@ -114,7 +161,9 @@ static void CPU_usage_Per_thread_handler(
*/
void rtems_cpu_usage_reset( void )
{
CPU_usage_Ticks_at_last_reset = _Watchdog_Ticks_since_boot;
#ifndef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS
CPU_usage_Ticks_at_last_reset = _Watchdog_Ticks_since_boot;
#endif
rtems_iterate_over_all_threads(CPU_usage_Per_thread_handler);
}