forked from Imagelibrary/rtems
* libcsupport/src/__times.c, libmisc/cpuuse/cpuusagereport.c, libmisc/cpuuse/cpuusagereset.c, posix/src/clockgettime.c, posix/src/pthread.c, posix/src/timersettime.c, rtems/include/rtems/rtems/ratemon.h, rtems/src/clockgetsecondssinceepoch.c, rtems/src/clockgetuptime.c, rtems/src/ratemongetstatus.c, rtems/src/ratemonperiod.c, rtems/src/ratemonreportstatistics.c, rtems/src/taskwakewhen.c, rtems/src/timerfirewhen.c, rtems/src/timerserver.c, rtems/src/timerserverfirewhen.c, score/Makefile.am, score/preinstall.am, score/include/rtems/score/thread.h, score/include/rtems/score/tod.h, score/src/coretod.c, score/src/coretodget.c, score/src/coretodgetuptime.c, score/src/coretodset.c, score/src/coretodtickle.c, score/src/threaddispatch.c, score/src/threadinitialize.c: Add SuperCore handler Timestamp to provide an opaque class for the representation and manipulation of uptime, time of day, and the difference between two timestamps. By using SuperCore Timestamp, it is clear which methods and APIs really have to be struct timespec and which can be in an optimized native format. * score/include/rtems/score/timestamp.h, score/src/coretodgetuptimetimespec.c: New files.
180 lines
4.9 KiB
C
180 lines
4.9 KiB
C
/*
|
|
* CPU Usage Reporter
|
|
*
|
|
* COPYRIGHT (c) 1989-2007
|
|
* 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 <assert.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <ctype.h>
|
|
#include <inttypes.h>
|
|
|
|
#include <rtems/cpuuse.h>
|
|
#include <rtems/bspIo.h>
|
|
|
|
#if defined(RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS)
|
|
#include <rtems/score/timestamp.h>
|
|
#endif
|
|
|
|
#ifdef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS
|
|
extern Timestamp_Control CPU_usage_Uptime_at_last_reset;
|
|
#else
|
|
extern uint32_t CPU_usage_Ticks_at_last_reset;
|
|
#endif
|
|
|
|
/*PAGE
|
|
*
|
|
* rtems_cpu_usage_report
|
|
*/
|
|
|
|
void rtems_cpu_usage_report_with_plugin(
|
|
void *context,
|
|
rtems_printk_plugin_t print
|
|
)
|
|
{
|
|
uint32_t i;
|
|
uint32_t api_index;
|
|
Thread_Control *the_thread;
|
|
Objects_Information *information;
|
|
char name[13];
|
|
uint32_t ival, fval;
|
|
#ifdef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS
|
|
Timestamp_Control uptime, total, ran;
|
|
#else
|
|
uint32_t total_units = 0;
|
|
#endif
|
|
|
|
if ( !print )
|
|
return;
|
|
|
|
/*
|
|
* 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 );
|
|
_Timestamp_Subtract( &CPU_usage_Uptime_at_last_reset, &uptime, &total );
|
|
#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->cpu_time_used;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
(*print)( context, "CPU Usage by thread\n"
|
|
#if defined(RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS)
|
|
" ID NAME SECONDS PERCENT\n"
|
|
#else
|
|
" ID NAME TICKS PERCENT\n"
|
|
#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 ];
|
|
|
|
if ( !the_thread )
|
|
continue;
|
|
|
|
rtems_object_get_name( the_thread->Object.id, sizeof(name), name );
|
|
|
|
(*print)(
|
|
context,
|
|
"0x%08" PRIx32 " %-12s ",
|
|
the_thread->Object.id,
|
|
name
|
|
);
|
|
|
|
#ifdef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS
|
|
/*
|
|
* If this is the currently executing thread, account for time
|
|
* since the last context switch.
|
|
*/
|
|
ran = the_thread->cpu_time_used;
|
|
if ( _Thread_Executing->Object.id == the_thread->Object.id ) {
|
|
Timestamp_Control used;
|
|
_Timestamp_Subtract(
|
|
&_Thread_Time_of_last_context_switch, &uptime, &used
|
|
);
|
|
_Timestamp_Add_to( &ran, &used );
|
|
};
|
|
_Timestamp_Divide( &ran, &total, &ival, &fval );
|
|
|
|
/*
|
|
* Print the information
|
|
*/
|
|
|
|
(*print)( context,
|
|
"%3" PRId32 ".%06" PRId32 " %3" PRId32 ".%03" PRId32 "\n",
|
|
_Timestamp_Get_seconds( &ran ),
|
|
_Timestamp_Get_nanoseconds( &ran ) /
|
|
TOD_NANOSECONDS_PER_MICROSECOND,
|
|
ival, fval
|
|
);
|
|
#else
|
|
ival = (total_units) ?
|
|
the_thread->cpu_time_used * 10000 / total_units : 0;
|
|
fval = ival % 100;
|
|
ival /= 100;
|
|
(*print)( context,
|
|
"%8" PRId32 " %3" PRId32 ".%02" PRId32"\n",
|
|
the_thread->cpu_time_used,
|
|
ival,
|
|
fval
|
|
);
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS
|
|
(*print)( context, "Time since last CPU Usage reset %" PRId32
|
|
".%06" PRId32 " seconds\n",
|
|
_Timestamp_Get_seconds( &total ),
|
|
_Timestamp_Get_nanoseconds( &total ) / TOD_NANOSECONDS_PER_MICROSECOND
|
|
);
|
|
#else
|
|
(*print)( context,
|
|
"Ticks since last reset = %" PRId32 "\n",
|
|
_Watchdog_Ticks_since_boot - CPU_usage_Ticks_at_last_reset
|
|
);
|
|
(*print)( context, "Total Units = %" PRId32 "\n", total_units );
|
|
#endif
|
|
}
|
|
|
|
void rtems_cpu_usage_report( void )
|
|
{
|
|
rtems_cpu_usage_report_with_plugin( NULL, printk_plugin );
|
|
}
|