summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cpukit/ChangeLog24
-rw-r--r--cpukit/configure.ac12
-rw-r--r--cpukit/libcsupport/src/__times.c26
-rw-r--r--cpukit/libmisc/cpuuse/cpuuse.c129
-rw-r--r--cpukit/libmisc/stackchk/check.c56
-rw-r--r--cpukit/rtems/include/rtems/rtems/ratemon.h96
-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
-rw-r--r--cpukit/score/Makefile.am3
-rw-r--r--cpukit/score/include/rtems/score/thread.h37
-rw-r--r--cpukit/score/include/rtems/score/timespec.h23
-rw-r--r--cpukit/score/src/threaddispatch.c19
-rw-r--r--cpukit/score/src/threadinitialize.c27
-rw-r--r--cpukit/score/src/threadtickletimeslice.c11
-rw-r--r--cpukit/score/src/timespecdivide.c31
-rw-r--r--cpukit/score/src/timespecdividebyinteger.c52
19 files changed, 700 insertions, 195 deletions
diff --git a/cpukit/ChangeLog b/cpukit/ChangeLog
index 6d42ab70e8..a59e116fe1 100644
--- a/cpukit/ChangeLog
+++ b/cpukit/ChangeLog
@@ -1,3 +1,23 @@
+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.
+
2007-05-16 Joel Sherrill <joel.sherrill@oarcorp.com>
* libmisc/cpuuse/cpuuse.c: Use rtems_object_get_name and eliminate
@@ -36,8 +56,8 @@
Monotonic Statistics and Period Usage into Rate Monotonic Manager.
Added the following directives: rtems_rate_monotonic_get_statistics,
rtems_rate_monotonic_reset_statistics,
- rtems_rate_montonic_reset_all_statistics,
- rtems_rate_montonic_report_statistics, and rtems_object_get_name.
+ rtems_rate_monotonic_reset_all_statistics,
+ rtems_rate_monotonic_report_statistics, and rtems_object_get_name.
Obsoleted the rtems/rtmonuse.h file as a public interface.
* rtems/src/ratemongetstatistics.c,
rtems/src/ratemonreportstatistics.c, rtems/src/ratemonresetall.c,
diff --git a/cpukit/configure.ac b/cpukit/configure.ac
index e743c2d537..08f7b4725e 100644
--- a/cpukit/configure.ac
+++ b/cpukit/configure.ac
@@ -208,6 +208,18 @@ RTEMS_CPUOPT([SIZEOF_CPU_CONTEXT],
[$ac_cv_sizeof_CPU_CONTEXT],
[The size of a 'CPU_CONTEXT', as computed by sizeof])
+RTEMS_CPUOPT([__RTEMS_USE_TICKS_CPU_USAGE_STATISTICS__],
+ [test x"${USE_TICKS_FOR_CPU_USAGE_STATISTICS}" = x"1"],
+ [1],
+ [disable nanosecond granularity for cpu usage statistics]
+)
+
+RTEMS_CPUOPT([__RTEMS_USE_TICKS_RATE_MONOTONIC_STATISTICS__],
+ [test x"${USE_TICKS_FOR_RATE_MONOTONIC_STATISTICS}" = x"1"],
+ [1],
+ [disable nanosecond granularity for period statistics]
+)
+
RTEMS_CPUOPT([__RTEMS_MAJOR__],
[true],
[$rtems_major],
diff --git a/cpukit/libcsupport/src/__times.c b/cpukit/libcsupport/src/__times.c
index 733befe8c9..669ed5ca25 100644
--- a/cpukit/libcsupport/src/__times.c
+++ b/cpukit/libcsupport/src/__times.c
@@ -22,6 +22,9 @@
#include <sys/time.h>
#include <errno.h>
#include <assert.h>
+#ifdef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS
+ #include <rtems/score/timespec.h>
+#endif
clock_t _times(
struct tms *ptms
@@ -48,7 +51,28 @@ clock_t _times(
* this thread.
*/
- ptms->tms_utime = _Thread_Executing->ticks_executed;
+ #ifdef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS
+ {
+ struct timespec per_tick;
+ uint32_t ticks;
+ uint32_t fractional_ticks;
+
+ per_tick.tv_sec =
+ _TOD_Microseconds_per_tick / TOD_MILLISECONDS_PER_SECOND;
+ per_tick.tv_nsec =
+ (_TOD_Microseconds_per_tick % TOD_MILLISECONDS_PER_SECOND) / 1000;
+
+ _Timespec_Divide(
+ &_Thread_Executing->cpu_time_used,
+ &per_tick,
+ &ticks,
+ &fractional_ticks
+ );
+ ptms->tms_utime = ticks;
+ }
+ #else
+ ptms->tms_utime = _Thread_Executing->ticks_executed;
+ #endif
ptms->tms_stime = ticks;
ptms->tms_cutime = 0;
ptms->tms_cstime = 0;
diff --git a/cpukit/libmisc/cpuuse/cpuuse.c b/cpukit/libmisc/cpuuse/cpuuse.c
index 9e9be38db8..cf1b6f2b4d 100644
--- a/cpukit/libmisc/cpuuse/cpuuse.c
+++ b/cpukit/libmisc/cpuuse/cpuuse.c
@@ -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;
-
- 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;
+ #ifdef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS
+ struct timespec uptime;
+ #else
+ uint32_t total_units = 0;
+ #endif
+
+ /*
+ * 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;
+ }
}
}
- }
-
+ #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 );
-
- 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
- );
+
+ printk( "0x%08" PRIx32 " %4s ", the_thread->Object.id, name );
+
+ #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);
}
diff --git a/cpukit/libmisc/stackchk/check.c b/cpukit/libmisc/stackchk/check.c
index 37b91dab21..bc9dc66481 100644
--- a/cpukit/libmisc/stackchk/check.c
+++ b/cpukit/libmisc/stackchk/check.c
@@ -215,7 +215,8 @@ void Stack_check_report_blown_task(
Stack_Control *stack = &running->Start.Initial_stack;
printk(
- "BLOWN STACK!!! Offending task(%p): id=0x%08" PRIx32 "; name=0x%08" PRIx32,
+ "BLOWN STACK!!! Offending task(0x%p): "
+ "id=0x%08" PRIx32 "; name=0x%08" PRIx32,
running,
running->Object.id,
(uint32_t) running->Object.name
@@ -233,7 +234,7 @@ void Stack_check_report_blown_task(
#endif
printk(
- " stack covers range %p - %p (%d bytes)\n",
+ " stack covers range 0x%p - 0x%p (%d bytes)\n",
stack->area,
stack->area + stack->size - 1,
stack->size
@@ -325,8 +326,8 @@ void *Stack_check_find_high_water_mark(
base += length - 1;
for (ebase = s; base > ebase; base--)
- if (*base != U32_PATTERN)
- return (void *) base;
+ if (*base != U32_PATTERN)
+ return (void *) base;
#else
/*
* start at lower memory and find first word that does not
@@ -335,39 +336,14 @@ void *Stack_check_find_high_water_mark(
base += PATTERN_SIZE_WORDS;
for (ebase = base + length; base < ebase; base++)
- if (*base != U32_PATTERN)
- return (void *) base;
+ if (*base != U32_PATTERN)
+ return (void *) base;
#endif
return (void *)0;
}
/*
- * Report Name
- */
-
-char *Stack_check_Get_object_name(
- Objects_Control *the_object,
- char **name
-)
-{
- Objects_Information *info;
-
- info = _Objects_Get_information(the_object->id);
- if ( info->is_string ) {
- *name = (char *) the_object->name;
- } else {
- uint32_t u32_name = (uint32_t) the_object->name;
- (*name)[ 0 ] = (u32_name >> 24) & 0xff;
- (*name)[ 1 ] = (u32_name >> 16) & 0xff;
- (*name)[ 2 ] = (u32_name >> 8) & 0xff;
- (*name)[ 3 ] = (u32_name >> 0) & 0xff;
- (*name)[ 4 ] = '\0';
- }
- return *name;
-}
-
-/*
* Stack_check_Dump_threads_usage(
*
* Try to print out how much stack was actually used by the task.
@@ -380,9 +356,7 @@ void Stack_check_Dump_threads_usage(
void *low;
void *high_water_mark;
Stack_Control *stack;
- uint32_t u32_name;
- char name_str[5];
- char *name;
+ char name[5];
if ( !the_thread )
return;
@@ -411,19 +385,17 @@ void Stack_check_Dump_threads_usage(
else
used = 0;
- name = name_str;
if ( the_thread ) {
- name = Stack_check_Get_object_name( &the_thread->Object, &name );
+ rtems_object_get_name( the_thread->Object.id, sizeof(name), name );
} else {
- u32_name = rtems_build_name('I', 'N', 'T', 'R');
- name[ 0 ] = (u32_name >> 24) & 0xff;
- name[ 1 ] = (u32_name >> 16) & 0xff;
- name[ 2 ] = (u32_name >> 8) & 0xff;
- name[ 3 ] = (u32_name >> 0) & 0xff;
+ name[ 0 ] = 'I';
+ name[ 1 ] = 'N';
+ name[ 2 ] = 'T';
+ name[ 3 ] = 'R';
name[ 4 ] = '\0';
}
- printk("0x%08" PRIx32 " %4s %p - %p %8" PRId32 " %8" PRId32 "\n",
+ printk("0x%08" PRIx32 " %4s 0x%p - 0x%p %8" PRId32 " %8" PRId32 "\n",
the_thread ? the_thread->Object.id : ~0,
name,
stack->area,
diff --git a/cpukit/rtems/include/rtems/rtems/ratemon.h b/cpukit/rtems/include/rtems/rtems/ratemon.h
index 84e3454164..3492772e2c 100644
--- a/cpukit/rtems/include/rtems/rtems/ratemon.h
+++ b/cpukit/rtems/include/rtems/rtems/ratemon.h
@@ -32,6 +32,20 @@
extern "C" {
#endif
+/*
+ * The user can define this at configure time and go back to ticks
+ * resolution.
+ */
+#ifndef __RTEMS_USE_TICKS_RATE_MONOTONIC_STATISTICS__
+ /*
+ * Enable the nanosecond accurate statistics
+ *
+ * When not defined, the older style tick accurate granularity
+ * is used.
+ */
+ #define RTEMS_ENABLE_NANOSECOND_RATE_MONOTONIC_STATISTICS
+#endif
+
#include <rtems/score/object.h>
#include <rtems/score/thread.h>
#include <rtems/score/watchdog.h>
@@ -68,12 +82,24 @@ typedef enum {
typedef struct {
uint32_t count;
uint32_t missed_count;
- uint32_t min_cpu_time;
- uint32_t max_cpu_time;
- uint32_t total_cpu_time;
- uint32_t min_wall_time;
- uint32_t max_wall_time;
- uint32_t total_wall_time;
+ #ifdef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS
+ struct timespec min_cpu_time;
+ struct timespec max_cpu_time;
+ struct timespec total_cpu_time;
+ #else
+ uint32_t min_cpu_time;
+ uint32_t max_cpu_time;
+ uint32_t total_cpu_time;
+ #endif
+ #ifdef RTEMS_ENABLE_NANOSECOND_RATE_MONOTONIC_STATISTICS
+ struct timespec min_wall_time;
+ struct timespec max_wall_time;
+ struct timespec total_wall_time;
+ #else
+ uint32_t min_wall_time;
+ uint32_t max_wall_time;
+ uint32_t total_wall_time;
+ #endif
} rtems_rate_monotonic_period_statistics;
/*
@@ -83,8 +109,16 @@ typedef struct {
typedef struct {
Objects_Id owner;
rtems_rate_monotonic_period_states state;
- uint32_t ticks_since_last_period;
- uint32_t ticks_executed_since_last_period;
+ #ifdef RTEMS_ENABLE_NANOSECOND_RATE_MONOTONIC_STATISTICS
+ struct timespec since_last_period;
+ #else
+ uint32_t ticks_since_last_period;
+ #endif
+ #ifdef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS
+ struct timespec executed_since_last_period;
+ #else
+ uint32_t ticks_executed_since_last_period;
+ #endif
} rtems_rate_monotonic_period_status;
/*
@@ -96,8 +130,16 @@ typedef struct {
Objects_Control Object;
Watchdog_Control Timer;
rtems_rate_monotonic_period_states state;
- uint32_t owner_ticks_executed_at_period;
- uint32_t time_at_period;
+ #ifdef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS
+ struct timespec owner_executed_at_period;
+ #else
+ uint32_t owner_ticks_executed_at_period;
+ #endif
+ #ifdef RTEMS_ENABLE_NANOSECOND_RATE_MONOTONIC_STATISTICS
+ struct timespec time_at_period;
+ #else
+ uint32_t time_at_period;
+ #endif
uint32_t next_length;
Thread_Control *owner;
rtems_rate_monotonic_period_statistics Statistics;
@@ -217,24 +259,24 @@ rtems_status_code rtems_rate_monotonic_reset_statistics(
);
/*
- * rtems_rate_montonic_reset_all_statistics
+ * rtems_rate_monotonic_reset_all_statistics
*
* DESCRIPTION:
*
* This directive allows a thread to reset the statistics information
* on ALL period instances.
*/
-void rtems_rate_montonic_reset_all_statistics( void );
+void rtems_rate_monotonic_reset_all_statistics( void );
/*
- * rtems_rate_montonic_report_statistics
+ * rtems_rate_monotonic_report_statistics
*
* DESCRIPTION:
*
* This directive allows a thread to print the statistics information
* on ALL period instances which have non-zero counts using printk.
*/
-void rtems_rate_montonic_report_statistics( void );
+void rtems_rate_monotonic_report_statistics( void );
/*
* rtems_rate_monotonic_period
@@ -278,6 +320,28 @@ void _Rate_monotonic_Timeout(
* This method resets the statistics information for a period instance.
*/
+#ifdef RTEMS_ENABLE_NANOSECOND_RATE_MONOTONIC_STATISTICS
+ #define _Rate_monotonic_Reset_wall_time_statistics( _the_period ) \
+ do { \
+ /* set the minimums to a large value */ \
+ (_the_period)->Statistics.min_wall_time.tv_sec = 0x7fffffff; \
+ (_the_period)->Statistics.min_wall_time.tv_nsec = 0x7fffffff; \
+ } while (0)
+#else
+ #define _Rate_monotonic_Reset_wall_time_statistics( _the_period )
+#endif
+
+#ifdef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS
+ #define _Rate_monotonic_Reset_cpu_use_statistics( _the_period ) \
+ do { \
+ /* set the minimums to a large value */ \
+ (_the_period)->Statistics.min_cpu_time.tv_sec = 0x7fffffff; \
+ (_the_period)->Statistics.min_cpu_time.tv_nsec = 0x7fffffff; \
+ } while (0)
+#else
+ #define _Rate_monotonic_Reset_cpu_use_statistics( _the_period )
+#endif
+
#define _Rate_monotonic_Reset_statistics( _the_period ) \
do { \
memset( \
@@ -285,8 +349,10 @@ void _Rate_monotonic_Timeout(
0, \
sizeof( rtems_rate_monotonic_period_statistics ) \
); \
+ _Rate_monotonic_Reset_cpu_use_statistics( _the_period ); \
+ _Rate_monotonic_Reset_wall_time_statistics( _the_period ); \
} while (0)
-
+
#ifndef __RTEMS_APPLICATION__
#include <rtems/rtems/ratemon.inl>
#endif
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;
diff --git a/cpukit/score/Makefile.am b/cpukit/score/Makefile.am
index 2b1c25e513..ad3c68e87e 100644
--- a/cpukit/score/Makefile.am
+++ b/cpukit/score/Makefile.am
@@ -148,7 +148,8 @@ libscore_a_SOURCES += src/threadq.c src/threadqdequeue.c \
## TIMESPEC_C_FILES
libscore_a_SOURCES += src/timespecaddto.c src/timespecfromticks.c \
src/timespecisvalid.c src/timespeclessthan.c src/timespecgreaterthan.c \
- src/timespecsubtract.c src/timespectoticks.c src/timespecdivide.c
+ src/timespecsubtract.c src/timespectoticks.c src/timespecdivide.c \
+ src/timespecdividebyinteger.c
## TOD_C_FILES
libscore_a_SOURCES += src/coretod.c src/coretodset.c src/coretodget.c \
diff --git a/cpukit/score/include/rtems/score/thread.h b/cpukit/score/include/rtems/score/thread.h
index c23f9cf05c..1d8ba50705 100644
--- a/cpukit/score/include/rtems/score/thread.h
+++ b/cpukit/score/include/rtems/score/thread.h
@@ -31,6 +31,20 @@
extern "C" {
#endif
+/*
+ * The user can define this at configure time and go back to ticks
+ * resolution.
+ */
+#ifndef __RTEMS_USE_TICKS_CPU_USAGE_STATISTICS__
+ /*
+ * Enable the nanosecond accurate statistics
+ *
+ * When not defined, the older style tick accurate granularity
+ * is used.
+ */
+ #define RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS
+#endif
+
#include <rtems/score/context.h>
#include <rtems/score/cpu.h>
#if defined(RTEMS_MULTIPROCESSING)
@@ -44,6 +58,10 @@ extern "C" {
#include <rtems/score/tqdata.h>
#include <rtems/score/watchdog.h>
+#ifdef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS
+ /* XXX include something for timespec */
+#endif
+
/**
* The following defines the "return type" of a thread.
*
@@ -318,10 +336,14 @@ struct Thread_Control_struct {
/** This field is the method invoked with the budgeted time is consumed. */
Thread_CPU_budget_algorithm_callout budget_callout;
- /** This field is the number of clock ticks executed by this thread
+ /** This field is the amount of CPU time consumed by this thread
* since it was created.
*/
- uint32_t ticks_executed;
+ #ifdef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS
+ struct timespec cpu_time_used;
+ #else
+ uint32_t ticks_executed;
+ #endif
/** This field points to the Ready FIFO for this priority. */
Chain_Control *ready;
/** This field contains precalculated priority map indices. */
@@ -435,6 +457,17 @@ SCORE_EXTERN Thread_Control *_Thread_Allocated_fp;
*/
SCORE_EXTERN struct _reent **_Thread_libc_reent;
+#ifdef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS
+
+ /**
+ * This contains the time since boot when the last context switch occurred.
+ * By placing it in the BSS, it will automatically be zeroed out at
+ * system initialization and does not need to be known outside this
+ * file.
+ */
+ SCORE_EXTERN struct timespec _Thread_Time_of_last_context_switch;
+#endif
+
/**
* This routine performs the initialization necessary for this handler.
*/
diff --git a/cpukit/score/include/rtems/score/timespec.h b/cpukit/score/include/rtems/score/timespec.h
index 2ffde63fc2..cc65e4084a 100644
--- a/cpukit/score/include/rtems/score/timespec.h
+++ b/cpukit/score/include/rtems/score/timespec.h
@@ -135,7 +135,7 @@ void _Timespec_Subtract(
struct timespec *result
);
-/** @brief Divide Timespec
+/** @brief Divide Timespec By Integet
*
* This routine divides a timespec by an integer value. The expected
* use is to assist in benchmark calculations where you typically
@@ -147,12 +147,31 @@ void _Timespec_Subtract(
*
* @return This method fills in @a result.
*/
-void _Timespec_Divide(
+void _Timespec_Divide_by_integer(
const struct timespec *time,
uint32_t iterations,
struct timespec *result
);
+/** @brief Divide Timespec
+ *
+ * This routine divides a timespec by another timespec. The
+ * intended use is for calculating percentages to three decimal points.
+ *
+ * @param[in] lhs is the left hand number
+ * @param[in] rhs is the righ hand number
+ * @param[in] ival_percentage is the integer portion of the average
+ * @param[in] fval_percentage is the thousandths of percentage
+ *
+ * @return This method fills in @a result.
+ */
+void _Timespec_Divide(
+ const struct timespec *lhs,
+ const struct timespec *rhs,
+ uint32_t *ival_percentage,
+ uint32_t *fval_percentage
+);
+
#ifdef __cplusplus
}
#endif
diff --git a/cpukit/score/src/threaddispatch.c b/cpukit/score/src/threaddispatch.c
index 136433be17..4c903b6c2a 100644
--- a/cpukit/score/src/threaddispatch.c
+++ b/cpukit/score/src/threaddispatch.c
@@ -2,7 +2,7 @@
* Thread Handler
*
*
- * COPYRIGHT (c) 1989-1999.
+ * COPYRIGHT (c) 1989-2007.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
@@ -30,6 +30,11 @@
#include <rtems/score/userext.h>
#include <rtems/score/wkspace.h>
+#ifdef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS
+
+ #include <rtems/score/timespec.h>
+#endif
+
/*PAGE
*
* _Thread_Dispatch
@@ -78,7 +83,17 @@ void _Thread_Dispatch( void )
heir->cpu_time_budget = _Thread_Ticks_per_timeslice;
_ISR_Enable( level );
- heir->ticks_executed++;
+ #ifdef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS
+ {
+ struct timespec uptime, ran;
+ _TOD_Get_uptime( &uptime );
+ _Timespec_Subtract(&_Thread_Time_of_last_context_switch, &uptime, &ran);
+ _Timespec_Add_to( &executing->cpu_time_used, &ran );
+ _Thread_Time_of_last_context_switch = uptime;
+ }
+ #else
+ heir->ticks_executed++;
+ #endif
/*
* Switch libc's task specific data.
diff --git a/cpukit/score/src/threadinitialize.c b/cpukit/score/src/threadinitialize.c
index e61cbac19a..f3e13a4944 100644
--- a/cpukit/score/src/threadinitialize.c
+++ b/cpukit/score/src/threadinitialize.c
@@ -187,17 +187,26 @@ boolean _Thread_Initialize(
break;
}
- the_thread->Start.isr_level = isr_level;
+ the_thread->Start.isr_level = isr_level;
+
+ the_thread->current_state = STATES_DORMANT;
+ the_thread->Wait.queue = NULL;
+ the_thread->resource_count = 0;
+ the_thread->suspend_count = 0;
+ the_thread->real_priority = priority;
+ the_thread->Start.initial_priority = priority;
+ _Thread_Set_priority( the_thread, priority );
- the_thread->current_state = STATES_DORMANT;
- the_thread->Wait.queue = NULL;
- the_thread->resource_count = 0;
- the_thread->suspend_count = 0;
- the_thread->real_priority = priority;
- the_thread->Start.initial_priority = priority;
- the_thread->ticks_executed = 0;
+ /*
+ * Initialize the CPU usage statistics
+ */
- _Thread_Set_priority( the_thread, priority );
+ #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
/*
* Open the object
diff --git a/cpukit/score/src/threadtickletimeslice.c b/cpukit/score/src/threadtickletimeslice.c
index 0666066b28..41f08aa8d0 100644
--- a/cpukit/score/src/threadtickletimeslice.c
+++ b/cpukit/score/src/threadtickletimeslice.c
@@ -49,11 +49,12 @@ void _Thread_Tickle_timeslice( void )
executing = _Thread_Executing;
- /*
- * Increment the number of ticks this thread has been executing
- */
-
- executing->ticks_executed++;
+ #ifndef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS
+ /*
+ * Increment the number of ticks this thread has been executing
+ */
+ executing->ticks_executed++;
+ #endif
/*
* If the thread is not preemptible or is not ready, then
diff --git a/cpukit/score/src/timespecdivide.c b/cpukit/score/src/timespecdivide.c
index 0535c22e11..74d6cdbc78 100644
--- a/cpukit/score/src/timespecdivide.c
+++ b/cpukit/score/src/timespecdivide.c
@@ -23,30 +23,35 @@
#include <rtems/score/tod.h>
void _Timespec_Divide(
- const struct timespec *time,
- uint32_t iterations,
- struct timespec *result
+ const struct timespec *lhs,
+ const struct timespec *rhs,
+ uint32_t *ival_percentage,
+ uint32_t *fval_percentage
)
{
- uint64_t t;
+ uint64_t left, right, answer;
/*
* For math simplicity just convert the timespec to nanoseconds
* in a 64-bit integer.
*/
- t = time->tv_sec * TOD_NANOSECONDS_PER_SECOND;
- t += time->tv_nsec;
+ left = lhs->tv_sec * (uint64_t)TOD_NANOSECONDS_PER_SECOND;
+ left += lhs->tv_nsec;
+ right = rhs->tv_sec * (uint64_t)TOD_NANOSECONDS_PER_SECOND;
+ right += rhs->tv_nsec;
- /*
- * Divide to get nanoseconds per iteration
- */
-
- t /= iterations;
+ if ( rhs == 0 ) {
+ *ival_percentage = 0;
+ *ival_percentage = 0;
+ return;
+ }
/*
* Put it back in the timespec result
*/
- result->tv_sec = t / TOD_NANOSECONDS_PER_SECOND;
- result->tv_nsec = t % TOD_NANOSECONDS_PER_SECOND;
+ answer = (left * 1000) / right;
+
+ *fval_percentage = answer % 1000;
+ *ival_percentage = answer / 1000;
}
diff --git a/cpukit/score/src/timespecdividebyinteger.c b/cpukit/score/src/timespecdividebyinteger.c
new file mode 100644
index 0000000000..eecd7c4e30
--- /dev/null
+++ b/cpukit/score/src/timespecdividebyinteger.c
@@ -0,0 +1,52 @@
+/**
+ * @file score/src/timespecdividebyinteger.c
+ */
+
+/*
+ * 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$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <sys/types.h>
+#include <rtems/score/timespec.h>
+#include <rtems/score/tod.h>
+
+void _Timespec_Divide_by_integer(
+ const struct timespec *time,
+ uint32_t iterations,
+ struct timespec *result
+)
+{
+ uint64_t t;
+
+ /*
+ * For math simplicity just convert the timespec to nanoseconds
+ * in a 64-bit integer.
+ */
+ t = time->tv_sec * TOD_NANOSECONDS_PER_SECOND;
+ t += time->tv_nsec;
+
+ /*
+ * Divide to get nanoseconds per iteration
+ */
+
+ t /= iterations;
+
+ /*
+ * Put it back in the timespec result
+ */
+
+ result->tv_sec = t / TOD_NANOSECONDS_PER_SECOND;
+ result->tv_nsec = t % TOD_NANOSECONDS_PER_SECOND;
+}