From 3a46b72455721c223ad1501c209a9e414d409f7a Mon Sep 17 00:00:00 2001 From: Kuan-Hsun Chen Date: Wed, 21 Dec 2016 17:42:39 +0100 Subject: Enhancement of the RMS manager for the overrun handling. Three additional functions: rtems_rate_monotonic_postponed_job_count, _Rate_monotonic_Renew_deadline, and _Rate_monotonic_Release_postponed_job. Four refined functions: _Rate_monotonic_Activate, _Rate_monotonic_Block_while_expired, rtems_rate_monotonic_period, _Rate_monotonic_Timeout. Rate_monotonic_Control contains one counter for counting the postponed jobs and one for recording the recent deadline. Update #2795. --- 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 50b847840f..2eadfc2a7c 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 b6b3ffd404..c4133c7e03 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 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, diff --git a/cpukit/rtems/src/ratemontimeout.c b/cpukit/rtems/src/ratemontimeout.c index e514a314b3..c2a0291fd8 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 ); } } -- cgit v1.2.3