[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