[PATCH 1/3] Enhancement of the RMS manager for the overrun handling.

Kuan-Hsun Chen c0066c at gmail.com
Wed Dec 21 16:42:39 UTC 2016


Three additional functions:
RM_Postponed_num, RM_Renew_deadline, and RM_Release_postponedjob.

Four refined functions:
RM_Activate, RM_Block_while_expired, rtems_rate_monotonic_period, RM_Timeout.

Rate_monotonic_Control contains one counter for counting the postponed jobs and one for recording the recent deadline.
---
 cpukit/rtems/include/rtems/rtems/ratemon.h     |  33 +++++++
 cpukit/rtems/include/rtems/rtems/ratemonimpl.h |  13 +++
 cpukit/rtems/src/ratemonperiod.c               | 128 +++++++++++++++++++++++--
 cpukit/rtems/src/ratemontimeout.c              |  11 ++-
 4 files changed, 176 insertions(+), 9 deletions(-)

diff --git a/cpukit/rtems/include/rtems/rtems/ratemon.h b/cpukit/rtems/include/rtems/rtems/ratemon.h
index 50b8478..17b2ebf 100644
--- a/cpukit/rtems/include/rtems/rtems/ratemon.h
+++ b/cpukit/rtems/include/rtems/rtems/ratemon.h
@@ -18,10 +18,12 @@
  * - delete a rate monotonic timer
  * - conclude current and start the next period
  * - obtain status information on a period
+ * - obtain the number of postponed jobs
  */
 
 /* COPYRIGHT (c) 1989-2009, 2016.
  * On-Line Applications Research Corporation (OAR).
+ * COPYRIGHT (c) 2016 Kuan-Hsun Chen.
  *
  * The license and distribution terms for this file may be
  * found in the file LICENSE in this distribution or at
@@ -240,6 +242,18 @@ typedef struct {
    * This field contains the statistics maintained for the period.
    */
   Rate_monotonic_Statistics               Statistics;
+
+  /**
+   * This field contains the number of postponed jobs. 
+   * When the watchdog timeout, this variable will be increased immediately.
+   */
+  uint32_t                                postponed_jobs;
+
+  /**
+   *  This field contains the tick of the latest deadline decided by the period
+   *  watchdog.
+  */
+  uint64_t                                latest_deadline;
 }   Rate_monotonic_Control;
 
 /**
@@ -403,6 +417,25 @@ rtems_status_code rtems_rate_monotonic_period(
   rtems_interval  length
 );
 
+/**
+ * @brief RTEMS Return the number of postponed jobs
+ * 
+ * This is a helper function for runtime monitoring to return 
+ * the number of postponed jobs in this given period. This number 
+ * is only increased by the corresponding watchdog, 
+ * and is decreased by RMS manager with the postponed job releasing.
+ *
+ * @param[in] id is the period id
+ *
+ * @retval This helper function returns the number of postponed 
+ * jobs with a given period_id.
+ *
+ */
+uint32_t rtems_rate_monotonic_postponed_num(
+  rtems_id        period_id
+);
+
+
 /**@}*/
 
 #ifdef __cplusplus
diff --git a/cpukit/rtems/include/rtems/rtems/ratemonimpl.h b/cpukit/rtems/include/rtems/rtems/ratemonimpl.h
index b6b3ffd..c67586b 100644
--- a/cpukit/rtems/include/rtems/rtems/ratemonimpl.h
+++ b/cpukit/rtems/include/rtems/rtems/ratemonimpl.h
@@ -9,6 +9,7 @@
 /*  COPYRIGHT (c) 1989-2008.
  *  On-Line Applications Research Corporation (OAR).
  *  Copyright (c) 2016 embedded brains GmbH.
+ *  COPYRIGHT (c) 2016 Kuan-Hsun Chen.
  *
  *  The license and distribution terms for this file may be
  *  found in the file LICENSE in this distribution or at
@@ -116,6 +117,18 @@ bool _Rate_monotonic_Get_status(
   Timestamp_Control            *cpu_since_last_period
 );
 
+/**
+ * @brief Renew the watchdog deadline
+ *
+ * This routine is prepared for the watchdog timeout to renew its deadline
+ * without releasing jobs. 
+ */
+void _Rate_monotonic_Renew_deadline(
+  Rate_monotonic_Control *the_period,
+  Thread_Control         *owner,
+  ISR_lock_Context       *lock_context
+);
+
 void _Rate_monotonic_Restart(
   Rate_monotonic_Control *the_period,
   Thread_Control         *owner,
diff --git a/cpukit/rtems/src/ratemonperiod.c b/cpukit/rtems/src/ratemonperiod.c
index 77bd996..28ac810 100644
--- a/cpukit/rtems/src/ratemonperiod.c
+++ b/cpukit/rtems/src/ratemonperiod.c
@@ -9,6 +9,7 @@
  *  COPYRIGHT (c) 1989-2010.
  *  On-Line Applications Research Corporation (OAR).
  *  Copyright (c) 2016 embedded brains GmbH.
+ *  COPYRIGHT (c) 2016 Kuan-Hsun Chen.
  *
  *  The license and distribution terms for this file may be
  *  found in the file LICENSE in this distribution or at
@@ -63,6 +64,32 @@ bool _Rate_monotonic_Get_status(
   return true;
 }
 
+static void _Rate_monotonic_Release_postponedjob(
+  Rate_monotonic_Control *the_period,
+  Thread_Control         *owner,
+  rtems_interval          next_length,
+  ISR_lock_Context       *lock_context
+)
+{
+  /* This function only releases the postponed jobs. */
+  Per_CPU_Control *cpu_self;
+  Thread_queue_Context  queue_context;
+  cpu_self = _Thread_Dispatch_disable_critical( lock_context );
+  _Rate_monotonic_Release( owner, lock_context );
+  
+  the_period->postponed_jobs -=1;
+  _Scheduler_Release_job(
+    owner,
+    &the_period->Priority,
+    the_period->latest_deadline,
+    &queue_context
+  );
+  
+  _Rate_monotonic_Release( the_period, lock_context );
+  _Thread_Priority_update( &queue_context );
+  _Thread_Dispatch_enable( cpu_self );
+}
+
 static void _Rate_monotonic_Release_job(
   Rate_monotonic_Control *the_period,
   Thread_Control         *owner,
@@ -93,6 +120,30 @@ static void _Rate_monotonic_Release_job(
   _Thread_Dispatch_enable( cpu_self );
 }
 
+void _Rate_monotonic_Renew_deadline(
+  Rate_monotonic_Control *the_period,
+  Thread_Control         *owner,
+  ISR_lock_Context       *lock_context
+)
+{
+  Per_CPU_Control *cpu_self;
+  uint64_t deadline;
+
+  cpu_self = _Thread_Dispatch_disable_critical( lock_context );
+  _Rate_monotonic_Release( owner, lock_context );
+
+  _ISR_lock_ISR_disable( lock_context );
+  deadline = _Watchdog_Per_CPU_insert_relative(
+    &the_period->Timer,
+    cpu_self,
+    the_period->next_length
+  );
+  the_period->latest_deadline = deadline;
+  _ISR_lock_ISR_enable( lock_context );
+  _Thread_Dispatch_enable( cpu_self );
+
+}
+
 void _Rate_monotonic_Restart(
   Rate_monotonic_Control *the_period,
   Thread_Control         *owner,
@@ -190,6 +241,7 @@ static rtems_status_code _Rate_monotonic_Activate(
   ISR_lock_Context       *lock_context
 )
 {
+  the_period->postponed_jobs = 0;
   the_period->state = RATE_MONOTONIC_ACTIVE;
   the_period->next_length = length;
   _Rate_monotonic_Restart( the_period, executing, lock_context );
@@ -241,6 +293,11 @@ static rtems_status_code _Rate_monotonic_Block_while_active(
   return RTEMS_SUCCESSFUL;
 }
 
+/* 
+ * There are two possible cases: one is that the previous deadline is missed, 
+ * The other is that the number of postponed jobs is not 0, but the current 
+ * deadline is still not expired, i.e., state = RATE_MONOTONIC_ACTIVE.
+ */
 static rtems_status_code _Rate_monotonic_Block_while_expired(
   Rate_monotonic_Control *the_period,
   rtems_interval          length,
@@ -248,18 +305,43 @@ static rtems_status_code _Rate_monotonic_Block_while_expired(
   ISR_lock_Context       *lock_context
 )
 {
+  /* 
+   * No matter the just finished jobs in time or not, 
+   * they are actually missing their deadlines already. 
+   */
+  the_period->state = RATE_MONOTONIC_EXPIRED;
+
   /*
-   *  Update statistics from the concluding period
+   * Update statistics from the concluding period
    */
   _Rate_monotonic_Update_statistics( the_period );
 
   the_period->state = RATE_MONOTONIC_ACTIVE;
   the_period->next_length = length;
 
-  _Rate_monotonic_Release_job( the_period, executing, length, lock_context );
+  _Rate_monotonic_Release_postponedjob( the_period, executing, length, lock_context );
   return RTEMS_TIMEOUT;
 }
 
+/*
+ * This helper function is prepared for run-time monitoring.
+ */
+uint32_t rtems_rate_monotonic_postponed_num(
+    rtems_id   period_id
+)
+{  
+  Rate_monotonic_Control             *the_period;
+  ISR_lock_Context                    lock_context;
+  Thread_Control                     *owner;
+
+  the_period = _Rate_monotonic_Get( period_id, &lock_context );
+  _Assert( the_period != NULL );
+  uint32_t jobs = the_period->postponed_jobs;
+  owner = the_period->owner;
+  _Rate_monotonic_Release( owner, &lock_context );
+  return jobs;
+}
+
 rtems_status_code rtems_rate_monotonic_period(
   rtems_id       id,
   rtems_interval length
@@ -292,12 +374,34 @@ rtems_status_code rtems_rate_monotonic_period(
   } else {
     switch ( state ) {
       case RATE_MONOTONIC_ACTIVE:
-        status = _Rate_monotonic_Block_while_active(
-          the_period,
-          length,
-          executing,
-          &lock_context
-        );
+
+        if( the_period->postponed_jobs > 0 ){
+          /* 
+           * If the number of postponed jobs is not 0, it means the 
+           * previous postponed instance is finished without exceeding 
+           * the current period deadline. 
+           * 
+           * Do nothing on the watchdog deadline assignment but release the next 
+           * remaining postponed job.
+           */           
+          status = _Rate_monotonic_Block_while_expired(
+            the_period,
+            length,
+            executing,
+            &lock_context
+          );
+        }else{
+          /* 
+           * Normal case that no postponed jobs and no expiration, so wait for the period
+           * and update the deadline of watchdog accordingly.
+           */
+          status = _Rate_monotonic_Block_while_active(
+            the_period,
+            length,
+            executing,
+            &lock_context
+          );
+        }
         break;
       case RATE_MONOTONIC_INACTIVE:
         status = _Rate_monotonic_Activate(
@@ -308,6 +412,14 @@ rtems_status_code rtems_rate_monotonic_period(
         );
         break;
       default:
+        /* 
+         * As now this period was already TIMEOUT, there must be at least one 
+         * postponed job recorded by the watchdog. The one which exceeded
+         * the previous deadlines was just finished.
+         * 
+         * Maybe there is more than one job postponed due to the preemption or
+         * the previous finished job.
+         */
         _Assert( state == RATE_MONOTONIC_EXPIRED );
         status = _Rate_monotonic_Block_while_expired(
           the_period,
diff --git a/cpukit/rtems/src/ratemontimeout.c b/cpukit/rtems/src/ratemontimeout.c
index e514a31..f877e99 100644
--- a/cpukit/rtems/src/ratemontimeout.c
+++ b/cpukit/rtems/src/ratemontimeout.c
@@ -9,6 +9,8 @@
  *  COPYRIGHT (c) 1989-2009.
  *  On-Line Applications Research Corporation (OAR).
  *
+ *  COPYRIGHT (c) 2016 Kuan-Hsun Chen.
+ *
  *  The license and distribution terms for this file may be
  *  found in the file LICENSE in this distribution or at
  *  http://www.rtems.org/license/LICENSE.
@@ -62,7 +64,14 @@ void _Rate_monotonic_Timeout( Watchdog_Control *the_watchdog )
       _Thread_Unblock( owner );
     }
   } else {
+    /* 
+     * If the watchdog is timeout, it means there is an additional postponed
+     * job in the next period but it is not available to release now:
+     * Either the current task is still executed, or it is preemptive by the
+     * other higher priority tasks.
+     */
+    the_period->postponed_jobs += 1;
     the_period->state = RATE_MONOTONIC_EXPIRED;
-    _Rate_monotonic_Release( the_period, &lock_context );
+    _Rate_monotonic_Renew_deadline( the_period, owner, &lock_context );
   }
 }
-- 
1.9.1



More information about the devel mailing list