summaryrefslogtreecommitdiffstats
path: root/cpukit/rtems/src/ratemonperiod.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/rtems/src/ratemonperiod.c')
-rw-r--r--cpukit/rtems/src/ratemonperiod.c128
1 files changed, 120 insertions, 8 deletions
diff --git a/cpukit/rtems/src/ratemonperiod.c b/cpukit/rtems/src/ratemonperiod.c
index 77bd996819..c98f37a3bd 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,
@@ -249,17 +306,42 @@ static rtems_status_code _Rate_monotonic_Block_while_expired(
)
{
/*
- * Update statistics from the concluding period
+ * 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
*/
_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,