diff options
Diffstat (limited to 'cpukit/score')
-rw-r--r-- | cpukit/score/Makefile.am | 3 | ||||
-rw-r--r-- | cpukit/score/include/rtems/score/thread.h | 37 | ||||
-rw-r--r-- | cpukit/score/include/rtems/score/timespec.h | 23 | ||||
-rw-r--r-- | cpukit/score/src/threaddispatch.c | 19 | ||||
-rw-r--r-- | cpukit/score/src/threadinitialize.c | 27 | ||||
-rw-r--r-- | cpukit/score/src/threadtickletimeslice.c | 11 | ||||
-rw-r--r-- | cpukit/score/src/timespecdivide.c | 31 | ||||
-rw-r--r-- | cpukit/score/src/timespecdividebyinteger.c | 52 |
8 files changed, 169 insertions, 34 deletions
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; +} |