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/rtems/src/ratemonperiod.c | 145 ++++++++++++++++++++------------------- 1 file changed, 76 insertions(+), 69 deletions(-) (limited to 'cpukit/rtems/src/ratemonperiod.c') 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 */ -- cgit v1.2.3