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

Kuan-Hsun Chen c0066c at gmail.com
Fri Dec 9 16:21:40 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     |  42 ++++++--
 cpukit/rtems/include/rtems/rtems/ratemonimpl.h |  25 +++--
 cpukit/rtems/src/ratemonperiod.c               | 144 +++++++++++++++++++++----
 cpukit/rtems/src/ratemontimeout.c              |  13 ++-
 4 files changed, 183 insertions(+), 41 deletions(-)

diff --git a/cpukit/rtems/include/rtems/rtems/ratemon.h b/cpukit/rtems/include/rtems/rtems/ratemon.h
index 50b8478..71a99dc 100644
--- a/cpukit/rtems/include/rtems/rtems/ratemon.h
+++ b/cpukit/rtems/include/rtems/rtems/ratemon.h
@@ -22,6 +22,7 @@
 
 /* COPYRIGHT (c) 1989-2009, 2016.
  * On-Line Applications Research Corporation (OAR).
+ * COPYRIGHT (c) 2016 Kuan-Hsun Chen, TU Dortmund University (TUDo).
  *
  * The license and distribution terms for this file may be
  * found in the file LICENSE in this distribution or at
@@ -194,11 +195,6 @@ typedef struct {
   /** This field is the object management portion of a Period instance. */
   Objects_Control                         Object;
 
-  /**
-   * @brief Protects the rate monotonic period state.
-   */
-  ISR_LOCK_MEMBER(                        Lock )
-
   /** This is the timer used to provide the unblocking mechanism. */
   Watchdog_Control                        Timer;
 
@@ -206,12 +202,6 @@ typedef struct {
   rtems_rate_monotonic_period_states      state;
 
   /**
-   * @brief A priority node for use by the scheduler job release and cancel
-   * operations.
-   */
-  Priority_Node                           Priority;
-
-  /**
    * This field contains the length of the next period to be
    * executed.
    */
@@ -240,6 +230,19 @@ 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;
 
 /**
@@ -386,6 +389,23 @@ void rtems_rate_monotonic_report_statistics_with_plugin(
 void rtems_rate_monotonic_report_statistics( void );
 
 /**
+ * @brief RTEMS Return the number of postponed jobs
+ * 
+ * This is a helper function to return the number of postponed jobs by 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 given period_id.
+ *
+ */
+uint32_t rtems_rate_monotonic_Postponed_num(
+  rtems_id        period_id
+);
+
+/**
  * @brief RTEMS Rate Monotonic Period
  *
  * This routine implements the rtems_rate_monotonic_period directive. When
diff --git a/cpukit/rtems/include/rtems/rtems/ratemonimpl.h b/cpukit/rtems/include/rtems/rtems/ratemonimpl.h
index b6b3ffd..6cdaaeb 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, TU Dortmund University (TUDo).
  *
  *  The license and distribution terms for this file may be
  *  found in the file LICENSE in this distribution or at
@@ -69,19 +70,19 @@ RTEMS_INLINE_ROUTINE Rate_monotonic_Control *_Rate_monotonic_Allocate( void )
 }
 
 RTEMS_INLINE_ROUTINE void _Rate_monotonic_Acquire_critical(
-  Rate_monotonic_Control *the_period,
-  ISR_lock_Context       *lock_context
+  Thread_Control   *the_thread,
+  ISR_lock_Context *lock_context
 )
 {
-  _ISR_lock_Acquire( &the_period->Lock, lock_context );
+  _Thread_Wait_acquire_default_critical( the_thread, lock_context );
 }
 
 RTEMS_INLINE_ROUTINE void _Rate_monotonic_Release(
-  Rate_monotonic_Control *the_period,
-  ISR_lock_Context       *lock_context
+  Thread_Control   *the_thread,
+  ISR_lock_Context *lock_context
 )
 {
-  _ISR_lock_Release_and_ISR_enable( &the_period->Lock, lock_context );
+  _Thread_Wait_release_default( the_thread, lock_context );
 }
 
 RTEMS_INLINE_ROUTINE Rate_monotonic_Control *_Rate_monotonic_Get(
@@ -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..26cee58 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, TU Dortmund University (TUDo).
  *
  *  The license and distribution terms for this file may be
  *  found in the file LICENSE in this distribution or at
@@ -63,6 +64,24 @@ 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;
+  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->latest_deadline );
+
+  _Thread_Dispatch_enable( cpu_self );
+}
+
 static void _Rate_monotonic_Release_job(
   Rate_monotonic_Control *the_period,
   Thread_Control         *owner,
@@ -70,29 +89,49 @@ static void _Rate_monotonic_Release_job(
   ISR_lock_Context       *lock_context
 )
 {
-  Per_CPU_Control      *cpu_self;
-  Thread_queue_Context  queue_context;
-  uint64_t              deadline;
+  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,
     next_length
   );
-  _Scheduler_Release_job(
-    owner,
-    &the_period->Priority,
-    deadline,
-    &queue_context
-  );
+  _ISR_lock_ISR_enable( lock_context );
+
+  _Scheduler_Release_job( owner, deadline );
 
-  _Rate_monotonic_Release( the_period, lock_context );
-  _Thread_Priority_update( &queue_context );
   _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 +229,10 @@ static rtems_status_code _Rate_monotonic_Activate(
   ISR_lock_Context       *lock_context
 )
 {
+  
+  /* Initialize the number of postponed job variable */
+  the_period->postponed_jobs = 0;
+
   the_period->state = RATE_MONOTONIC_ACTIVE;
   the_period->next_length = length;
   _Rate_monotonic_Restart( the_period, executing, lock_context );
@@ -221,7 +264,7 @@ static rtems_status_code _Rate_monotonic_Block_while_active(
   _Thread_Wait_flags_set( executing, RATE_MONOTONIC_INTEND_TO_BLOCK );
 
   cpu_self = _Thread_Dispatch_disable_critical( lock_context );
-  _Rate_monotonic_Release( the_period, lock_context );
+  _Rate_monotonic_Release( executing, lock_context );
 
   _Thread_Set_state( executing, STATES_WAITING_FOR_PERIOD );
 
@@ -241,6 +284,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,6 +296,12 @@ 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
    */
@@ -255,11 +309,27 @@ static rtems_status_code _Rate_monotonic_Block_while_expired(
 
   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;
 }
 
+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
@@ -282,22 +352,44 @@ rtems_status_code rtems_rate_monotonic_period(
     return RTEMS_NOT_OWNER_OF_RESOURCE;
   }
 
-  _Rate_monotonic_Acquire_critical( the_period, &lock_context );
+  _Rate_monotonic_Acquire_critical( executing, &lock_context );
 
   state = the_period->state;
 
   if ( length == RTEMS_PERIOD_STATUS ) {
     status = _Rate_monotonic_Get_status_for_state( state );
-    _Rate_monotonic_Release( the_period, &lock_context );
+    _Rate_monotonic_Release( executing, &lock_context );
   } 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 +400,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 deadline"s" 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..be0a770 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, TU Dortmund University (TUDo).
+ *
  *  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.
@@ -31,7 +33,7 @@ void _Rate_monotonic_Timeout( Watchdog_Control *the_watchdog )
   owner = the_period->owner;
 
   _ISR_lock_ISR_disable( &lock_context );
-  _Rate_monotonic_Acquire_critical( the_period, &lock_context );
+  _Rate_monotonic_Acquire_critical( owner, &lock_context );
   wait_flags = _Thread_Wait_flags_get( owner );
 
   if (
@@ -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