From f7c285e6ca81a7b20a01b360a7f26ad4445984a6 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Fri, 30 Oct 2009 17:54:15 +0000 Subject: 2009-10-30 Glenn Humphrey PR pr1462/cpukit * rtems/include/rtems/rtems/ratemon.h, rtems/src/ratemonperiod.c, rtems/src/ratemontimeout.c: Fix bugs in rate monotonic statistics. --- cpukit/ChangeLog | 6 ++ cpukit/rtems/include/rtems/rtems/ratemon.h | 35 ++++++- cpukit/rtems/src/ratemonperiod.c | 145 +++++++++++++++-------------- cpukit/rtems/src/ratemontimeout.c | 7 +- 4 files changed, 118 insertions(+), 75 deletions(-) diff --git a/cpukit/ChangeLog b/cpukit/ChangeLog index cc0d263bc3..8ddde13bbd 100644 --- a/cpukit/ChangeLog +++ b/cpukit/ChangeLog @@ -1,3 +1,9 @@ +2009-10-30 Glenn Humphrey + + PR pr1462/cpukit + * rtems/include/rtems/rtems/ratemon.h, rtems/src/ratemonperiod.c, + rtems/src/ratemontimeout.c: Fix bugs in rate monotonic statistics. + 2009-10-15 Joel Sherrill * sapi/include/confdefs.h: Correct type of rtems_malloc_dirty_helper so diff --git a/cpukit/rtems/include/rtems/rtems/ratemon.h b/cpukit/rtems/include/rtems/rtems/ratemon.h index 41eb68ed31..4a713ff7e2 100644 --- a/cpukit/rtems/include/rtems/rtems/ratemon.h +++ b/cpukit/rtems/include/rtems/rtems/ratemon.h @@ -3,7 +3,8 @@ * * This include file contains all the constants, structures, and * prototypes associated with the Rate Monotonic Manager. This manager - * provides facilities to implement tasks which execute in a periodic fashion. + * provides facilities to implement threads which execute in a periodic + * fashion. * * Directives provided are: * @@ -14,7 +15,7 @@ * - obtain status information on a period */ -/* COPYRIGHT (c) 1989-2008. +/* COPYRIGHT (c) 1989-2009. * On-Line Applications Research Corporation (OAR). * * The license and distribution terms for this file may be @@ -362,9 +363,9 @@ rtems_status_code rtems_rate_monotonic_period( * @brief _Rate_monotonic_Timeout * * This routine is invoked when the period represented - * by ID expires. If the task which owns this period is blocked + * by ID expires. If the thread which owns this period is blocked * waiting for the period to expire, then it is readied and the - * period is restarted. If the owning task is not waiting for the + * period is restarted. If the owning thread is not waiting for the * period to expire, then the period is placed in the EXPIRED * state and not restarted. */ @@ -373,6 +374,32 @@ void _Rate_monotonic_Timeout( void *ignored ); +/** + * @brief _Rate_monotonic_Initiate_per_period_statistics( + * + * This routine is invoked when a period is initiated via an explicit + * call to rtems_rate_monotonic_period for the period's first iteration + * or from _Rate_monotonic_Timeout for period iterations 2-n. + * + * @param[in] the_period points to the period being operated upon. + */ +void _Rate_monotonic_Initiate_per_period_statistics( + Rate_monotonic_Control *the_period +); + +/** + * @brief _Rate_monotonic_Initiate_statistics( + * + * This routine is invoked when a period is initiated via an explicit + * call to rtems_rate_monotonic_period for the period's first iteration + * or from _Rate_monotonic_Timeout for period iterations 2-n. + * + * @param[in] the_period points to the period being operated upon. + */ +void _Rate_monotonic_Initiate_statistics( + Rate_monotonic_Control *the_period +); + /** * @brief _Rate_monotonic_Reset_wall_time_statistics * diff --git a/cpukit/rtems/src/ratemonperiod.c b/cpukit/rtems/src/ratemonperiod.c index 26db51f43b..6641802fff 100644 --- a/cpukit/rtems/src/ratemonperiod.c +++ b/cpukit/rtems/src/ratemonperiod.c @@ -1,7 +1,7 @@ /* * Rate Monotonic Manager - Period Blocking and Status * - * COPYRIGHT (c) 1989-2007. + * COPYRIGHT (c) 1989-2009. * On-Line Applications Research Corporation (OAR). * * The license and distribution terms for this file may be @@ -28,6 +28,61 @@ extern struct timespec _Thread_Time_of_last_context_switch; #endif +void _Rate_monotonic_Initiate_statistics( + Rate_monotonic_Control *the_period +) +{ + Thread_Control *owning_thread = the_period->owner; + + /* + * If any statistics are at nanosecond granularity, we need to + * obtain the uptime. + */ + #if defined(RTEMS_ENABLE_NANOSECOND_RATE_MONOTONIC_STATISTICS) || \ + defined(RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS) + + struct timespec uptime; + + _TOD_Get_uptime( &uptime ); + #endif + + /* + * Set the starting point and the CPU time used for the statistics. + */ + #ifdef RTEMS_ENABLE_NANOSECOND_RATE_MONOTONIC_STATISTICS + the_period->time_at_period = uptime; + #else + the_period->time_at_period = _Watchdog_Ticks_since_boot; + #endif + + the_period->owner_executed_at_period = owning_thread->cpu_time_used; + + /* + * If using nanosecond granularity for CPU Usage Statistics and the + * period's thread is currently executing, then we need to take into + * account how much time the executing thread has run since the last + * context switch. When this routine is invoked from + * rtems_rate_monotonic_period, the owner will be the executing thread. + * When this routine is invoked from _Rate_monotonic_Timeout, it will not. + */ + #ifdef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS + if (owning_thread == _Thread_Executing) { + + rtems_thread_cpu_usage_t ran; + + /* + * Adjust the CPU time used to account for the time since last + * context switch. + */ + _Timespec_Subtract( + &_Thread_Time_of_last_context_switch, &uptime, &ran + ); + + _Timespec_Add_to( &the_period->owner_executed_at_period, &ran ); + } + #endif +} + void _Rate_monotonic_Update_statistics( Rate_monotonic_Control *the_period ) @@ -55,7 +110,17 @@ void _Rate_monotonic_Update_statistics( */ /* - * Grab basic information + * Update the counts. + */ + + stats = &the_period->Statistics; + stats->count++; + + if ( the_period->state == RATE_MONOTONIC_EXPIRED ) + stats->missed_count++; + + /* + * Grab basic information for time statistics. */ #ifdef RTEMS_ENABLE_NANOSECOND_RATE_MONOTONIC_STATISTICS @@ -86,9 +151,7 @@ void _Rate_monotonic_Update_statistics( /* executed = current cpu usage - value at start of period */ _Timespec_Subtract( - &the_period->owner_executed_at_period, - &used, - &executed + &the_period->owner_executed_at_period, &used, &executed ); } #else @@ -96,17 +159,6 @@ void _Rate_monotonic_Update_statistics( the_period->owner_executed_at_period; #endif - /* - * Now update the statistics - */ - - stats = &the_period->Statistics; - stats->count++; - - - if ( the_period->state == RATE_MONOTONIC_EXPIRED ) - stats->missed_count++; - /* * Update CPU time */ @@ -180,8 +232,8 @@ rtems_status_code rtems_rate_monotonic_period( ISR_Level level; the_period = _Rate_monotonic_Get( id, &location ); - switch ( location ) { + switch ( location ) { case OBJECTS_LOCAL: if ( !_Thread_Is_executing( the_period->owner ) ) { _Thread_Enable_dispatch(); @@ -207,59 +259,16 @@ rtems_status_code rtems_rate_monotonic_period( } _ISR_Disable( level ); + switch ( the_period->state ) { case RATE_MONOTONIC_INACTIVE: { - #if defined(RTEMS_ENABLE_NANOSECOND_RATE_MONOTONIC_STATISTICS) || \ - defined(RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS) - struct timespec uptime; - #endif - - /* - * No need to update statistics -- there are not a period active - */ _ISR_Enable( level ); - - #if defined(RTEMS_ENABLE_NANOSECOND_RATE_MONOTONIC_STATISTICS) || \ - defined(RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS) - _TOD_Get_uptime( &uptime ); - #endif - - #ifdef RTEMS_ENABLE_NANOSECOND_RATE_MONOTONIC_STATISTICS - /* - * Since the statistics didn't update the starting time, - * we do it here. - */ - the_period->time_at_period = uptime; - #else - the_period->time_at_period = _Watchdog_Ticks_since_boot; - #endif - - #ifdef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS - { - rtems_thread_cpu_usage_t ran; - - 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 - ); - - /* The thread had executed before the last context switch also. - * - * the_period->owner_executed_at_period += ran - */ - _Timespec_Add_to( &the_period->owner_executed_at_period, &ran ); - } - #else - the_period->owner_executed_at_period = - _Thread_Executing->cpu_time_used; - #endif + /* + * Baseline statistics information for the beginning of a period. + */ + _Rate_monotonic_Initiate_statistics( the_period ); the_period->state = RATE_MONOTONIC_ACTIVE; _Watchdog_Initialize( @@ -278,7 +287,7 @@ rtems_status_code rtems_rate_monotonic_period( case RATE_MONOTONIC_ACTIVE: /* - * Update statistics from the concluding period + * Update statistics from the concluding period. */ _Rate_monotonic_Update_statistics( the_period ); @@ -287,7 +296,6 @@ rtems_status_code rtems_rate_monotonic_period( * in the process of blocking on the period and that we * may be changing the length of the next period. */ - the_period->state = RATE_MONOTONIC_OWNER_IS_BLOCKING; the_period->next_length = length; @@ -300,7 +308,6 @@ rtems_status_code rtems_rate_monotonic_period( * Did the watchdog timer expire while we were actually blocking * on it? */ - _ISR_Disable( level ); local_state = the_period->state; the_period->state = RATE_MONOTONIC_ACTIVE; @@ -310,7 +317,6 @@ rtems_status_code rtems_rate_monotonic_period( * If it did, then we want to unblock ourself and continue as * if nothing happen. The period was reset in the timeout routine. */ - if ( local_state == RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING ) _Thread_Clear_state( _Thread_Executing, STATES_WAITING_FOR_PERIOD ); @@ -319,6 +325,7 @@ rtems_status_code rtems_rate_monotonic_period( break; case RATE_MONOTONIC_EXPIRED: + /* * Update statistics from the concluding period */ diff --git a/cpukit/rtems/src/ratemontimeout.c b/cpukit/rtems/src/ratemontimeout.c index 2e91fd2803..de1674636c 100644 --- a/cpukit/rtems/src/ratemontimeout.c +++ b/cpukit/rtems/src/ratemontimeout.c @@ -1,7 +1,7 @@ /* * Rate Monotonic Manager -- Period End Timeout Handler * - * COPYRIGHT (c) 1989-2007. + * COPYRIGHT (c) 1989-2009. * On-Line Applications Research Corporation (OAR). * * The license and distribution terms for this file may be @@ -51,7 +51,6 @@ void _Rate_monotonic_Timeout( * When we get here, the Timer is already off the chain so we do not * have to worry about that -- hence no _Watchdog_Remove(). */ - the_period = _Rate_monotonic_Get( id, &location ); switch ( location ) { @@ -61,10 +60,14 @@ void _Rate_monotonic_Timeout( the_thread->Wait.id == the_period->Object.id ) { _Thread_Unblock( the_thread ); + _Rate_monotonic_Initiate_statistics( the_period ); + _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; + _Rate_monotonic_Initiate_statistics( the_period ); + _Watchdog_Insert_ticks( &the_period->Timer, the_period->next_length ); } else the_period->state = RATE_MONOTONIC_EXPIRED; -- cgit v1.2.3