summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cpukit/ChangeLog6
-rw-r--r--cpukit/rtems/include/rtems/rtems/ratemon.h35
-rw-r--r--cpukit/rtems/src/ratemonperiod.c145
-rw-r--r--cpukit/rtems/src/ratemontimeout.c7
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 <glenn.humphrey@oarcorp.com>
+
+ 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 <joel.sherrill@OARcorp.com>
* 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.
*/
@@ -374,6 +375,32 @@ void _Rate_monotonic_Timeout(
);
/**
+ * @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
*
* This method resets the statistics information for a period instance.
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
@@ -97,17 +160,6 @@ void _Rate_monotonic_Update_statistics(
#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;