Looks good.
On Mon, Mar 21, 2016 at 10:40 AM, Sebastian Huber <sebastian.hu...@embedded-brains.de> wrote: > Use the default thread lock to protect rate-monotonic state changes. > his avoids use of the Giant lock. Split rtems_rate_monotonic_period() > body into several static functions. Introduce a new thread wait class > THREAD_WAIT_CLASS_PERIOD for period objects to synchronize the blocking > operation. > > Close #2631. > --- > cpukit/rtems/include/rtems/rtems/ratemon.h | 20 +- > cpukit/rtems/include/rtems/rtems/ratemonimpl.h | 113 +++------ > cpukit/rtems/src/ratemoncancel.c | 65 +++--- > cpukit/rtems/src/ratemondelete.c | 39 ++-- > cpukit/rtems/src/ratemongetstatistics.c | 61 +++-- > cpukit/rtems/src/ratemongetstatus.c | 101 ++++---- > cpukit/rtems/src/ratemonperiod.c | 307 > ++++++++++++++----------- > cpukit/rtems/src/ratemonresetstatistics.c | 47 +--- > cpukit/rtems/src/ratemontimeout.c | 63 +++-- > cpukit/score/include/rtems/score/threadimpl.h | 7 +- > testsuites/sptests/spintrcritical08/init.c | 24 +- > 11 files changed, 412 insertions(+), 435 deletions(-) > > diff --git a/cpukit/rtems/include/rtems/rtems/ratemon.h > b/cpukit/rtems/include/rtems/rtems/ratemon.h > index 0159e5c..87bd064c 100644 > --- a/cpukit/rtems/include/rtems/rtems/ratemon.h > +++ b/cpukit/rtems/include/rtems/rtems/ratemon.h > @@ -84,24 +84,12 @@ typedef enum { > > /** > * This value indicates the period is on the watchdog chain, and > - * the owner is blocked waiting on it. > - */ > - RATE_MONOTONIC_OWNER_IS_BLOCKING, > - > - /** > - * This value indicates the period is on the watchdog chain, and > * running. The owner should be executed or blocked waiting on > * another object. > */ > RATE_MONOTONIC_ACTIVE, > > /** > - * This value indicates the period is on the watchdog chain, and > - * has expired. The owner should be blocked waiting for the next period. > - */ > - RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING, > - > - /** > * This value indicates the period is off the watchdog chain, and > * has expired. The owner is still executing and has taken too much > * all time to complete this iteration of the period. > @@ -194,8 +182,12 @@ typedef struct { > } rtems_rate_monotonic_period_status; > > /** > - * The following structure defines the control block used to manage > - * each period. > + * @brief The following structure defines the control block used to manage > each > + * period. > + * > + * State changes are protected by the default thread lock of the owner > thread. > + * The owner thread is the thread that created the period object. The owner > + * thread field is immutable after object creation. > */ > typedef struct { > /** This field is the object management portion of a Period instance. */ > diff --git a/cpukit/rtems/include/rtems/rtems/ratemonimpl.h > b/cpukit/rtems/include/rtems/rtems/ratemonimpl.h > index 3141bfa..28837a2 100644 > --- a/cpukit/rtems/include/rtems/rtems/ratemonimpl.h > +++ b/cpukit/rtems/include/rtems/rtems/ratemonimpl.h > @@ -8,6 +8,7 @@ > > /* COPYRIGHT (c) 1989-2008. > * On-Line Applications Research Corporation (OAR). > + * Copyright (c) 2016 embedded brains GmbH. > * > * The license and distribution terms for this file may be > * found in the file LICENSE in this distribution or at > @@ -19,6 +20,9 @@ > > #include <rtems/rtems/ratemon.h> > #include <rtems/score/objectimpl.h> > +#include <rtems/score/schedulerimpl.h> > +#include <rtems/score/threadimpl.h> > +#include <rtems/score/watchdogimpl.h> > > #include <string.h> > > @@ -34,6 +38,15 @@ extern "C" { > * @{ > */ > > +#define RATE_MONOTONIC_INTEND_TO_BLOCK \ > + ( THREAD_WAIT_CLASS_PERIOD | THREAD_WAIT_STATE_INTEND_TO_BLOCK ) > + > +#define RATE_MONOTONIC_BLOCKED \ > + ( THREAD_WAIT_CLASS_PERIOD | THREAD_WAIT_STATE_BLOCKED ) > + > +#define RATE_MONOTONIC_READY_AGAIN \ > + ( THREAD_WAIT_CLASS_PERIOD | THREAD_WAIT_STATE_READY_AGAIN ) > + > /** > * @brief Rate Monotonic Period Class Management Structure > * > @@ -55,86 +68,31 @@ RTEMS_INLINE_ROUTINE Rate_monotonic_Control > *_Rate_monotonic_Allocate( void ) > _Objects_Allocate( &_Rate_monotonic_Information ); > } > > -/** > - * @brief Allocates a period control block from > - * the inactive chain of free period control blocks. > - * > - * This routine allocates a period control block from > - * the inactive chain of free period control blocks. > - */ > -RTEMS_INLINE_ROUTINE void _Rate_monotonic_Free ( > - Rate_monotonic_Control *the_period > +RTEMS_INLINE_ROUTINE void _Rate_monotonic_Acquire_critical( > + Thread_Control *the_thread, > + ISR_lock_Context *lock_context > ) > { > - _Objects_Free( &_Rate_monotonic_Information, &the_period->Object ); > + _Thread_Lock_acquire_default_critical( the_thread, lock_context ); > } > > -/** > - * @brief Maps period IDs to period control blocks. > - * > - * This function maps period IDs to period control blocks. > - * If ID corresponds to a local period, then it returns > - * the_period control pointer which maps to ID and location > - * is set to OBJECTS_LOCAL. Otherwise, location is set > - * to OBJECTS_ERROR and the_period is undefined. > - */ > -RTEMS_INLINE_ROUTINE Rate_monotonic_Control *_Rate_monotonic_Get ( > - Objects_Id id, > - Objects_Locations *location > +RTEMS_INLINE_ROUTINE void _Rate_monotonic_Release( > + Thread_Control *the_thread, > + ISR_lock_Context *lock_context > ) > { > - return (Rate_monotonic_Control *) > - _Objects_Get( &_Rate_monotonic_Information, id, location ); > + _Thread_Lock_release_default( the_thread, lock_context ); > } > > -/** > - * @brief Checks if the_period is in the ACTIVE state. > - * > - * This function returns TRUE if the_period is in the ACTIVE state, > - * and FALSE otherwise. > - */ > -RTEMS_INLINE_ROUTINE bool _Rate_monotonic_Is_active ( > - Rate_monotonic_Control *the_period > +RTEMS_INLINE_ROUTINE Rate_monotonic_Control *_Rate_monotonic_Get( > + Objects_Id id, > + ISR_lock_Context *lock_context > ) > { > - return (the_period->state == RATE_MONOTONIC_ACTIVE); > -} > - > -/** > - * @brief Checks if the_period is in the ACTIVE state. > - * > - * This function returns TRUE if the_period is in the ACTIVE state, > - * and FALSE otherwise. > - */ > -RTEMS_INLINE_ROUTINE bool _Rate_monotonic_Is_inactive ( > - Rate_monotonic_Control *the_period > -) > -{ > - return (the_period->state == RATE_MONOTONIC_INACTIVE); > -} > - > -/** > - * @brief Checks if the_period is in the EXPIRED state. > - * > - * This function returns TRUE if the_period is in the EXPIRED state, > - * and FALSE otherwise. > - */ > -RTEMS_INLINE_ROUTINE bool _Rate_monotonic_Is_expired ( > - Rate_monotonic_Control *the_period > -) > -{ > - return (the_period->state == RATE_MONOTONIC_EXPIRED); > + return (Rate_monotonic_Control *) > + _Objects_Get_local( &_Rate_monotonic_Information, id, lock_context ); > } > > -/** > - * @brief Rate Monotonic Timeout > - * > - * This routine is invoked when the period represented by the watchdog > expires. > - * If the thread which owns this period is blocked waiting for the period to > - * expire, then it is readied and the period is restarted. If the owning > thread > - * is not waiting for the period to expire, then the period is placed in the > - * EXPIRED state and not restarted. > - */ > void _Rate_monotonic_Timeout( Watchdog_Control *watchdog ); > > /** > @@ -158,17 +116,16 @@ bool _Rate_monotonic_Get_status( > Timestamp_Control *cpu_since_last_period > ); > > -/** > - * @brief Restart Rate Monotonic Period > - * > - * This routine is invoked when a period is initiated via an explicit > - * call to rtems_rate_monotonic_period for the period's first iteration > - * or from _Rate_monotonic_Timeout for period iterations 2-n. > - * > - * @param[in] the_period points to the period being operated upon. > - */ > void _Rate_monotonic_Restart( > - Rate_monotonic_Control *the_period > + Rate_monotonic_Control *the_period, > + Thread_Control *owner, > + ISR_lock_Context *lock_context > +); > + > +void _Rate_monotonic_Cancel( > + Rate_monotonic_Control *the_period, > + Thread_Control *owner, > + ISR_lock_Context *lock_context > ); > > RTEMS_INLINE_ROUTINE void _Rate_monotonic_Reset_min_time( > diff --git a/cpukit/rtems/src/ratemoncancel.c > b/cpukit/rtems/src/ratemoncancel.c > index 2e4d532..af6b1ec 100644 > --- a/cpukit/rtems/src/ratemoncancel.c > +++ b/cpukit/rtems/src/ratemoncancel.c > @@ -8,6 +8,7 @@ > /* > * COPYRIGHT (c) 1989-2007. > * On-Line Applications Research Corporation (OAR). > + * Copyright (c) 2016 embedded brains GmbH. > * > * The license and distribution terms for this file may be > * found in the file LICENSE in this distribution or at > @@ -19,40 +20,48 @@ > #endif > > #include <rtems/rtems/ratemonimpl.h> > -#include <rtems/score/schedulerimpl.h> > -#include <rtems/score/threadimpl.h> > -#include <rtems/score/watchdogimpl.h> > + > +void _Rate_monotonic_Cancel( > + Rate_monotonic_Control *the_period, > + Thread_Control *owner, > + ISR_lock_Context *lock_context > +) > +{ > + Per_CPU_Control *cpu_self; > + > + _Watchdog_Per_CPU_remove_relative( &the_period->Timer ); > + > + owner = the_period->owner; > + _Rate_monotonic_Acquire_critical( owner, lock_context ); > + the_period->state = RATE_MONOTONIC_INACTIVE; > + > + cpu_self = _Thread_Dispatch_disable_critical( lock_context ); > + _Rate_monotonic_Release( owner, lock_context ); > + > + _Scheduler_Release_job( owner, 0 ); > + > + _Thread_Dispatch_enable( cpu_self ); > +} > > rtems_status_code rtems_rate_monotonic_cancel( > rtems_id id > ) > { > Rate_monotonic_Control *the_period; > - Objects_Locations location; > - ISR_Level level; > - > - the_period = _Rate_monotonic_Get( id, &location ); > - switch ( location ) { > - > - case OBJECTS_LOCAL: > - if ( !_Thread_Is_executing( the_period->owner ) ) { > - _Objects_Put( &the_period->Object ); > - return RTEMS_NOT_OWNER_OF_RESOURCE; > - } > - _ISR_Disable( level ); > - _Watchdog_Per_CPU_remove_relative( &the_period->Timer ); > - _ISR_Enable( level ); > - the_period->state = RATE_MONOTONIC_INACTIVE; > - _Scheduler_Release_job( the_period->owner, 0 ); > - _Objects_Put( &the_period->Object ); > - return RTEMS_SUCCESSFUL; > - > -#if defined(RTEMS_MULTIPROCESSING) > - case OBJECTS_REMOTE: > -#endif > - case OBJECTS_ERROR: > - break; > + ISR_lock_Context lock_context; > + Thread_Control *executing; > + > + the_period = _Rate_monotonic_Get( id, &lock_context ); > + if ( the_period == NULL ) { > + return RTEMS_INVALID_ID; > + } > + > + executing = _Thread_Executing; > + if ( executing != the_period->owner ) { > + _ISR_lock_ISR_enable( &lock_context ); > + return RTEMS_NOT_OWNER_OF_RESOURCE; > } > > - return RTEMS_INVALID_ID; > + _Rate_monotonic_Cancel( the_period, executing, &lock_context ); > + return RTEMS_SUCCESSFUL; > } > diff --git a/cpukit/rtems/src/ratemondelete.c > b/cpukit/rtems/src/ratemondelete.c > index 09b9ab6..cb07694 100644 > --- a/cpukit/rtems/src/ratemondelete.c > +++ b/cpukit/rtems/src/ratemondelete.c > @@ -8,6 +8,7 @@ > /* > * COPYRIGHT (c) 1989-2007. > * On-Line Applications Research Corporation (OAR). > + * Copyright (c) 2016 embedded brains GmbH. > * > * The license and distribution terms for this file may be > * found in the file LICENSE in this distribution or at > @@ -19,42 +20,28 @@ > #endif > > #include <rtems/rtems/ratemonimpl.h> > -#include <rtems/score/schedulerimpl.h> > -#include <rtems/score/thread.h> > -#include <rtems/score/watchdogimpl.h> > > rtems_status_code rtems_rate_monotonic_delete( > rtems_id id > ) > { > Rate_monotonic_Control *the_period; > - Objects_Locations location; > - ISR_Level level; > + ISR_lock_Context lock_context; > + rtems_status_code status; > > _Objects_Allocator_lock(); > - the_period = _Rate_monotonic_Get( id, &location ); > - switch ( location ) { > - > - case OBJECTS_LOCAL: > - _Scheduler_Release_job( the_period->owner, 0 ); > - _Objects_Close( &_Rate_monotonic_Information, &the_period->Object ); > - _ISR_Disable( level ); > - _Watchdog_Per_CPU_remove_relative( &the_period->Timer ); > - _ISR_Enable( level ); > - the_period->state = RATE_MONOTONIC_INACTIVE; > - _Objects_Put( &the_period->Object ); > - _Rate_monotonic_Free( the_period ); > - _Objects_Allocator_unlock(); > - return RTEMS_SUCCESSFUL; > - > -#if defined(RTEMS_MULTIPROCESSING) > - case OBJECTS_REMOTE: /* should never return this */ > -#endif > - case OBJECTS_ERROR: > - break; > + > + the_period = _Rate_monotonic_Get( id, &lock_context ); > + if ( the_period != NULL ) { > + _Objects_Close( &_Rate_monotonic_Information, &the_period->Object ); > + _Rate_monotonic_Cancel( the_period, the_period->owner, &lock_context ); > + _Objects_Free( &_Rate_monotonic_Information, &the_period->Object ); > + status = RTEMS_SUCCESSFUL; > + } else { > + status = RTEMS_INVALID_ID; > } > > _Objects_Allocator_unlock(); > > - return RTEMS_INVALID_ID; > + return status; > } > diff --git a/cpukit/rtems/src/ratemongetstatistics.c > b/cpukit/rtems/src/ratemongetstatistics.c > index 6644562..a6a0525 100644 > --- a/cpukit/rtems/src/ratemongetstatistics.c > +++ b/cpukit/rtems/src/ratemongetstatistics.c > @@ -8,6 +8,7 @@ > /* > * COPYRIGHT (c) 1989-2009. > * On-Line Applications Research Corporation (OAR). > + * Copyright (c) 2016 embedded brains GmbH. > * > * The license and distribution terms for this file may be > * found in the file LICENSE in this distribution or at > @@ -18,50 +19,40 @@ > #include "config.h" > #endif > > -#include <rtems/system.h> > -#include <rtems/rtems/status.h> > -#include <rtems/rtems/support.h> > -#include <rtems/score/isr.h> > #include <rtems/rtems/ratemonimpl.h> > -#include <rtems/score/thread.h> > > rtems_status_code rtems_rate_monotonic_get_statistics( > rtems_id id, > - rtems_rate_monotonic_period_statistics *statistics > + rtems_rate_monotonic_period_statistics *dst > ) > { > - Objects_Locations location; > - Rate_monotonic_Control *the_period; > - rtems_rate_monotonic_period_statistics *dst; > - Rate_monotonic_Statistics *src; > + Rate_monotonic_Control *the_period; > + ISR_lock_Context lock_context; > + Thread_Control *owner; > + const Rate_monotonic_Statistics *src; > > - if ( !statistics ) > + if ( dst == NULL ) { > return RTEMS_INVALID_ADDRESS; > + } > > - the_period = _Rate_monotonic_Get( id, &location ); > - switch ( location ) { > - > - case OBJECTS_LOCAL: > - dst = statistics; > - src = &the_period->Statistics; > - dst->count = src->count; > - dst->missed_count = src->missed_count; > - _Timestamp_To_timespec( &src->min_cpu_time, &dst->min_cpu_time ); > - _Timestamp_To_timespec( &src->max_cpu_time, &dst->max_cpu_time ); > - _Timestamp_To_timespec( &src->total_cpu_time, &dst->total_cpu_time ); > - _Timestamp_To_timespec( &src->min_wall_time, &dst->min_wall_time ); > - _Timestamp_To_timespec( &src->max_wall_time, &dst->max_wall_time ); > - _Timestamp_To_timespec( &src->total_wall_time, &dst->total_wall_time ); > - > - _Objects_Put( &the_period->Object ); > - return RTEMS_SUCCESSFUL; > - > -#if defined(RTEMS_MULTIPROCESSING) > - case OBJECTS_REMOTE: /* should never return this */ > -#endif > - case OBJECTS_ERROR: > - break; > + the_period = _Rate_monotonic_Get( id, &lock_context ); > + if ( the_period == NULL ) { > + return RTEMS_INVALID_ID; > } > > - return RTEMS_INVALID_ID; > + owner = the_period->owner; > + _Rate_monotonic_Acquire_critical( owner, &lock_context ); > + > + src = &the_period->Statistics; > + dst->count = src->count; > + dst->missed_count = src->missed_count; > + _Timestamp_To_timespec( &src->min_cpu_time, &dst->min_cpu_time ); > + _Timestamp_To_timespec( &src->max_cpu_time, &dst->max_cpu_time ); > + _Timestamp_To_timespec( &src->total_cpu_time, &dst->total_cpu_time ); > + _Timestamp_To_timespec( &src->min_wall_time, &dst->min_wall_time ); > + _Timestamp_To_timespec( &src->max_wall_time, &dst->max_wall_time ); > + _Timestamp_To_timespec( &src->total_wall_time, &dst->total_wall_time ); > + > + _Rate_monotonic_Release( owner, &lock_context ); > + return RTEMS_SUCCESSFUL; > } > diff --git a/cpukit/rtems/src/ratemongetstatus.c > b/cpukit/rtems/src/ratemongetstatus.c > index 29296eb..82a950e 100644 > --- a/cpukit/rtems/src/ratemongetstatus.c > +++ b/cpukit/rtems/src/ratemongetstatus.c > @@ -8,6 +8,7 @@ > /* > * COPYRIGHT (c) 1989-2009. > * On-Line Applications Research Corporation (OAR). > + * Copyright (c) 2016 embedded brains GmbH. > * > * The license and distribution terms for this file may be > * found in the file LICENSE in this distribution or at > @@ -18,72 +19,68 @@ > #include "config.h" > #endif > > -#include <rtems/system.h> > -#include <rtems/rtems/status.h> > -#include <rtems/rtems/support.h> > -#include <rtems/score/isr.h> > #include <rtems/rtems/ratemonimpl.h> > -#include <rtems/score/thread.h> > -#include <rtems/score/timespec.h> > > rtems_status_code rtems_rate_monotonic_get_status( > rtems_id id, > - rtems_rate_monotonic_period_status *status > + rtems_rate_monotonic_period_status *period_status > ) > { > - Timestamp_Control executed; > - Objects_Locations location; > - Timestamp_Control since_last_period; > Rate_monotonic_Control *the_period; > - bool valid_status; > + ISR_lock_Context lock_context; > + Thread_Control *owner; > + rtems_status_code status; > > - if ( !status ) > + if ( period_status == NULL ) { > return RTEMS_INVALID_ADDRESS; > + } > > - the_period = _Rate_monotonic_Get( id, &location ); > - switch ( location ) { > - > - case OBJECTS_LOCAL: > - status->owner = the_period->owner->Object.id; > - status->state = the_period->state; > - > - /* > - * If the period is inactive, there is no information. > - */ > - if ( status->state == RATE_MONOTONIC_INACTIVE ) { > - _Timespec_Set_to_zero( &status->since_last_period ); > - _Timespec_Set_to_zero( &status->executed_since_last_period ); > - } else { > + the_period = _Rate_monotonic_Get( id, &lock_context ); > + if ( the_period == NULL ) { > + return RTEMS_INVALID_ID; > + } > > - /* > - * Grab the current status. > - */ > - valid_status = > - _Rate_monotonic_Get_status( > - the_period, &since_last_period, &executed > - ); > - if (!valid_status) { > - _Objects_Put( &the_period->Object ); > - return RTEMS_NOT_DEFINED; > - } > + owner = the_period->owner; > + _Rate_monotonic_Acquire_critical( owner, &lock_context ); > > - _Timestamp_To_timespec( > - &since_last_period, &status->since_last_period > - ); > - _Timestamp_To_timespec( > - &executed, &status->executed_since_last_period > - ); > - } > + period_status->owner = owner->Object.id; > + period_status->state = the_period->state; > > - _Objects_Put( &the_period->Object ); > - return RTEMS_SUCCESSFUL; > + if ( the_period->state == RATE_MONOTONIC_INACTIVE ) { > + /* > + * If the period is inactive, there is no information. > + */ > + _Timespec_Set_to_zero( &period_status->since_last_period ); > + _Timespec_Set_to_zero( &period_status->executed_since_last_period ); > + status = RTEMS_SUCCESSFUL; > + } else { > + Timestamp_Control wall_since_last_period; > + Timestamp_Control cpu_since_last_period; > + bool valid_status; > > -#if defined(RTEMS_MULTIPROCESSING) > - case OBJECTS_REMOTE: /* should never return this */ > -#endif > - case OBJECTS_ERROR: > - break; > + /* > + * Grab the current status. > + */ > + valid_status = _Rate_monotonic_Get_status( > + the_period, > + &wall_since_last_period, > + &cpu_since_last_period > + ); > + if ( valid_status ) { > + _Timestamp_To_timespec( > + &wall_since_last_period, > + &period_status->since_last_period > + ); > + _Timestamp_To_timespec( > + &cpu_since_last_period, > + &period_status->executed_since_last_period > + ); > + status = RTEMS_SUCCESSFUL; > + } else { > + status = RTEMS_NOT_DEFINED; > + } > } > > - return RTEMS_INVALID_ID; > + _Rate_monotonic_Release( owner, &lock_context ); > + return status; > } > diff --git a/cpukit/rtems/src/ratemonperiod.c > b/cpukit/rtems/src/ratemonperiod.c > index e03d8cf..96ea65c 100644 > --- a/cpukit/rtems/src/ratemonperiod.c > +++ b/cpukit/rtems/src/ratemonperiod.c > @@ -8,6 +8,7 @@ > /* > * COPYRIGHT (c) 1989-2010. > * On-Line Applications Research Corporation (OAR). > + * Copyright (c) 2016 embedded brains GmbH. > * > * The license and distribution terms for this file may be > * found in the file LICENSE in this distribution or at > @@ -20,9 +21,7 @@ > > #include <rtems/rtems/ratemonimpl.h> > #include <rtems/score/schedulerimpl.h> > -#include <rtems/score/threadimpl.h> > #include <rtems/score/todimpl.h> > -#include <rtems/score/watchdogimpl.h> > > bool _Rate_monotonic_Get_status( > const Rate_monotonic_Control *the_period, > @@ -64,28 +63,49 @@ bool _Rate_monotonic_Get_status( > return true; > } > > -void _Rate_monotonic_Restart( Rate_monotonic_Control *the_period ) > +static void _Rate_monotonic_Release_job( > + Rate_monotonic_Control *the_period, > + Thread_Control *owner, > + rtems_interval next_length, > + ISR_lock_Context *lock_context > +) > { > - ISR_Level level; > + Per_CPU_Control *cpu_self; > + > + cpu_self = _Thread_Dispatch_disable_critical( lock_context ); > + _Rate_monotonic_Release( owner, lock_context ); > + > + _Scheduler_Release_job( owner, next_length ); > + > + _ISR_lock_ISR_disable( lock_context ); > + _Watchdog_Per_CPU_insert_relative( > + &the_period->Timer, > + cpu_self, > + next_length > + ); > + _ISR_lock_ISR_enable( lock_context ); > > + _Thread_Dispatch_enable( cpu_self ); > +} > + > +void _Rate_monotonic_Restart( > + Rate_monotonic_Control *the_period, > + Thread_Control *owner, > + ISR_lock_Context *lock_context > +) > +{ > /* > * Set the starting point and the CPU time used for the statistics. > */ > _TOD_Get_uptime( &the_period->time_period_initiated ); > - _Thread_Get_CPU_time_used( > - the_period->owner, > - &the_period->cpu_usage_period_initiated > - ); > - > - _Scheduler_Release_job( the_period->owner, the_period->next_length ); > + _Thread_Get_CPU_time_used( owner, &the_period->cpu_usage_period_initiated > ); > > - _ISR_Disable( level ); > - _Watchdog_Per_CPU_insert_relative( > - &the_period->Timer, > - _Per_CPU_Get(), > - the_period->next_length > + _Rate_monotonic_Release_job( > + the_period, > + owner, > + the_period->next_length, > + lock_context > ); > - _ISR_Enable( level ); > } > > static void _Rate_monotonic_Update_statistics( > @@ -143,126 +163,153 @@ static void _Rate_monotonic_Update_statistics( > stats->max_wall_time = since_last_period; > } > > +static rtems_status_code _Rate_monotonic_Get_status_for_state( > + rtems_rate_monotonic_period_states state > +) > +{ > + switch ( state ) { > + case RATE_MONOTONIC_INACTIVE: > + return RTEMS_NOT_DEFINED; > + case RATE_MONOTONIC_EXPIRED: > + return RTEMS_TIMEOUT; > + default: > + _Assert( state == RATE_MONOTONIC_ACTIVE ); > + return RTEMS_SUCCESSFUL; > + } > +} > + > +static rtems_status_code _Rate_monotonic_Activate( > + Rate_monotonic_Control *the_period, > + rtems_interval length, > + Thread_Control *executing, > + ISR_lock_Context *lock_context > +) > +{ > + the_period->state = RATE_MONOTONIC_ACTIVE; > + the_period->next_length = length; > + _Rate_monotonic_Restart( the_period, executing, lock_context ); > + return RTEMS_SUCCESSFUL; > +} > + > +static rtems_status_code _Rate_monotonic_Block_while_active( > + Rate_monotonic_Control *the_period, > + rtems_interval length, > + Thread_Control *executing, > + ISR_lock_Context *lock_context > +) > +{ > + Per_CPU_Control *cpu_self; > + bool success; > + > + /* > + * Update statistics from the concluding period. > + */ > + _Rate_monotonic_Update_statistics( the_period ); > + > + /* > + * This tells the _Rate_monotonic_Timeout that this task is > + * in the process of blocking on the period and that we > + * may be changing the length of the next period. > + */ > + the_period->next_length = length; > + executing->Wait.return_argument = the_period; > + _Thread_Wait_flags_set( executing, RATE_MONOTONIC_INTEND_TO_BLOCK ); > + > + cpu_self = _Thread_Dispatch_disable_critical( lock_context ); > + _Rate_monotonic_Release( executing, lock_context ); > + > + _Thread_Set_state( executing, STATES_WAITING_FOR_PERIOD ); > + > + success = _Thread_Wait_flags_try_change( > + executing, > + RATE_MONOTONIC_INTEND_TO_BLOCK, > + RATE_MONOTONIC_BLOCKED > + ); > + if ( !success ) { > + _Thread_Unblock( executing ); > + } > + > + _Thread_Dispatch_enable( cpu_self ); > + return RTEMS_SUCCESSFUL; > +} > + > +static rtems_status_code _Rate_monotonic_Block_while_expired( > + Rate_monotonic_Control *the_period, > + rtems_interval length, > + Thread_Control *executing, > + ISR_lock_Context *lock_context > +) > +{ > + /* > + * 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 ); > + return RTEMS_TIMEOUT; > +} > + > rtems_status_code rtems_rate_monotonic_period( > rtems_id id, > rtems_interval length > ) > { > - Rate_monotonic_Control *the_period; > - Objects_Locations location; > - rtems_status_code return_value; > - rtems_rate_monotonic_period_states local_state; > - ISR_Level level; > - > - the_period = _Rate_monotonic_Get( id, &location ); > - > - switch ( location ) { > - case OBJECTS_LOCAL: > - if ( !_Thread_Is_executing( the_period->owner ) ) { > - _Objects_Put( &the_period->Object ); > - return RTEMS_NOT_OWNER_OF_RESOURCE; > - } > - > - if ( length == RTEMS_PERIOD_STATUS ) { > - switch ( the_period->state ) { > - case RATE_MONOTONIC_INACTIVE: > - return_value = RTEMS_NOT_DEFINED; > - break; > - case RATE_MONOTONIC_EXPIRED: > - case RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING: > - return_value = RTEMS_TIMEOUT; > - break; > - case RATE_MONOTONIC_ACTIVE: > - default: /* unreached -- only to remove warnings */ > - return_value = RTEMS_SUCCESSFUL; > - break; > - } > - _Objects_Put( &the_period->Object ); > - return( return_value ); > - } > - > - _ISR_Disable( level ); > - if ( the_period->state == RATE_MONOTONIC_INACTIVE ) { > - _ISR_Enable( level ); > - > - the_period->state = RATE_MONOTONIC_ACTIVE; > - the_period->next_length = length; > - _Rate_monotonic_Restart( the_period ); > - _Objects_Put( &the_period->Object ); > - return RTEMS_SUCCESSFUL; > - } > - > - if ( the_period->state == RATE_MONOTONIC_ACTIVE ) { > - /* > - * Update statistics from the concluding period. > - */ > - _Rate_monotonic_Update_statistics( the_period ); > - > - /* > - * This tells the _Rate_monotonic_Timeout that this task is > - * in the process of blocking on the period and that we > - * may be changing the length of the next period. > - */ > - the_period->state = RATE_MONOTONIC_OWNER_IS_BLOCKING; > - the_period->next_length = length; > - > - _ISR_Enable( level ); > - > - _Thread_Executing->Wait.id = the_period->Object.id; > - _Thread_Set_state( _Thread_Executing, STATES_WAITING_FOR_PERIOD ); > - > - /* > - * Did the watchdog timer expire while we were actually blocking > - * on it? > - */ > - _ISR_Disable( level ); > - local_state = the_period->state; > - the_period->state = RATE_MONOTONIC_ACTIVE; > - _ISR_Enable( level ); > - > - /* > - * If it did, then we want to unblock ourself and continue as > - * if nothing happen. The period was reset in the timeout routine. > - */ > - if ( local_state == RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING ) > - _Thread_Clear_state( _Thread_Executing, STATES_WAITING_FOR_PERIOD > ); > - > - _Objects_Put( &the_period->Object ); > - return RTEMS_SUCCESSFUL; > - } > - > - if ( the_period->state == RATE_MONOTONIC_EXPIRED ) { > - /* > - * Update statistics from the concluding period > - */ > - _Rate_monotonic_Update_statistics( the_period ); > - > - _ISR_Enable( level ); > - > - the_period->state = RATE_MONOTONIC_ACTIVE; > - the_period->next_length = length; > - > - _Watchdog_Per_CPU_insert_relative( > - &the_period->Timer, > - _Per_CPU_Get(), > - length > + Rate_monotonic_Control *the_period; > + ISR_lock_Context lock_context; > + Thread_Control *executing; > + rtems_status_code status; > + rtems_rate_monotonic_period_states state; > + > + the_period = _Rate_monotonic_Get( id, &lock_context ); > + if ( the_period == NULL ) { > + return RTEMS_INVALID_ID; > + } > + > + executing = _Thread_Executing; > + if ( executing != the_period->owner ) { > + _ISR_lock_ISR_enable( &lock_context ); > + return RTEMS_NOT_OWNER_OF_RESOURCE; > + } > + > + _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( executing, &lock_context ); > + } else { > + switch ( state ) { > + case RATE_MONOTONIC_ACTIVE: > + status = _Rate_monotonic_Block_while_active( > + the_period, > + length, > + executing, > + &lock_context > ); > - _Scheduler_Release_job( the_period->owner, the_period->next_length ); > - _Objects_Put( &the_period->Object ); > - return RTEMS_TIMEOUT; > - } > - > - /* > - * These should never happen so just return invalid Id. > - * - RATE_MONOTONIC_OWNER_IS_BLOCKING: > - * - RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING: > - */ > -#if defined(RTEMS_MULTIPROCESSING) > - case OBJECTS_REMOTE: /* should never return this */ > -#endif > - case OBJECTS_ERROR: > - break; > + break; > + case RATE_MONOTONIC_INACTIVE: > + status = _Rate_monotonic_Activate( > + the_period, > + length, > + executing, > + &lock_context > + ); > + break; > + default: > + _Assert( state == RATE_MONOTONIC_EXPIRED ); > + status = _Rate_monotonic_Block_while_expired( > + the_period, > + length, > + executing, > + &lock_context > + ); > + break; > + } > } > > - return RTEMS_INVALID_ID; > + return status; > } > diff --git a/cpukit/rtems/src/ratemonresetstatistics.c > b/cpukit/rtems/src/ratemonresetstatistics.c > index 1256409..b146e6a 100644 > --- a/cpukit/rtems/src/ratemonresetstatistics.c > +++ b/cpukit/rtems/src/ratemonresetstatistics.c > @@ -18,49 +18,24 @@ > #include "config.h" > #endif > > -#include <rtems/system.h> > -#include <rtems/rtems/status.h> > -#include <rtems/rtems/support.h> > -#include <rtems/score/isr.h> > #include <rtems/rtems/ratemonimpl.h> > -#include <rtems/score/thread.h> > - > -/* > - * rtems_rate_monotonic_reset_statistics > - * > - * This directive allows a thread to reset the statistics information > - * on a specific period instance. > - * > - * Input parameters: > - * id - rate monotonic id > - * > - * Output parameters: > - * RTEMS_SUCCESSFUL - if successful > - * error code - if unsuccessful > - * > - */ > > rtems_status_code rtems_rate_monotonic_reset_statistics( > rtems_id id > ) > { > - Objects_Locations location; > - Rate_monotonic_Control *the_period; > - > - the_period = _Rate_monotonic_Get( id, &location ); > - switch ( location ) { > + Rate_monotonic_Control *the_period; > + ISR_lock_Context lock_context; > + Thread_Control *owner; > > - case OBJECTS_LOCAL: > - _Rate_monotonic_Reset_statistics( the_period ); > - _Objects_Put( &the_period->Object ); > - return RTEMS_SUCCESSFUL; > - > -#if defined(RTEMS_MULTIPROCESSING) > - case OBJECTS_REMOTE: /* should never return this */ > -#endif > - case OBJECTS_ERROR: > - break; > + the_period = _Rate_monotonic_Get( id, &lock_context ); > + if ( the_period == NULL ) { > + return RTEMS_INVALID_ID; > } > > - return RTEMS_INVALID_ID; > + owner = the_period->owner; > + _Rate_monotonic_Acquire_critical( owner, &lock_context ); > + _Rate_monotonic_Reset_statistics( the_period ); > + _Rate_monotonic_Release( owner, &lock_context ); > + return RTEMS_SUCCESSFUL; > } > diff --git a/cpukit/rtems/src/ratemontimeout.c > b/cpukit/rtems/src/ratemontimeout.c > index 7c25595..78c78e2 100644 > --- a/cpukit/rtems/src/ratemontimeout.c > +++ b/cpukit/rtems/src/ratemontimeout.c > @@ -19,33 +19,50 @@ > #endif > > #include <rtems/rtems/ratemonimpl.h> > -#include <rtems/score/threadimpl.h> > -#include <rtems/score/watchdogimpl.h> > > -void _Rate_monotonic_Timeout( Watchdog_Control *watchdog ) > +void _Rate_monotonic_Timeout( Watchdog_Control *the_watchdog ) > { > Rate_monotonic_Control *the_period; > - Thread_Control *the_thread; > - > - /* > - * When we get here, the Timer is already off the chain so we do not > - * have to worry about that -- hence no _Watchdog_Remove(). > - */ > - the_period = RTEMS_CONTAINER_OF( watchdog, Rate_monotonic_Control, Timer ); > - the_thread = the_period->owner; > - > - _Thread_Disable_dispatch(); > - > - if ( _States_Is_waiting_for_period( the_thread->current_state ) && > - the_thread->Wait.id == the_period->Object.id ) { > - _Thread_Unblock( the_thread ); > - _Rate_monotonic_Restart( the_period ); > - } else if ( the_period->state == RATE_MONOTONIC_OWNER_IS_BLOCKING ) { > - the_period->state = RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING; > - _Rate_monotonic_Restart( the_period ); > + Thread_Control *owner; > + ISR_lock_Context lock_context; > + Thread_Wait_flags wait_flags; > + > + the_period = RTEMS_CONTAINER_OF( the_watchdog, Rate_monotonic_Control, > Timer ); > + owner = the_period->owner; > + > + _ISR_lock_ISR_disable( &lock_context ); > + _Rate_monotonic_Acquire_critical( owner, &lock_context ); > + wait_flags = _Thread_Wait_flags_get( owner ); > + > + if ( > + ( wait_flags & THREAD_WAIT_CLASS_PERIOD ) != 0 > + && owner->Wait.return_argument == the_period > + ) { > + bool unblock; > + bool success; > + > + owner->Wait.return_argument = NULL; > + > + success = _Thread_Wait_flags_try_change_critical( > + owner, > + RATE_MONOTONIC_INTEND_TO_BLOCK, > + RATE_MONOTONIC_READY_AGAIN > + ); > + if ( success ) { > + unblock = false; > + } else { > + _Assert( _Thread_Wait_flags_get( owner ) == RATE_MONOTONIC_BLOCKED ); > + _Thread_Wait_flags_set( owner, RATE_MONOTONIC_READY_AGAIN ); > + unblock = true; > + } > + > + _Rate_monotonic_Restart( the_period, owner, &lock_context ); > + > + if ( unblock ) { > + _Thread_Unblock( owner ); > + } > } else { > the_period->state = RATE_MONOTONIC_EXPIRED; > + _Rate_monotonic_Release( owner, &lock_context ); > } > - > - _Thread_Unnest_dispatch(); > } > diff --git a/cpukit/score/include/rtems/score/threadimpl.h > b/cpukit/score/include/rtems/score/threadimpl.h > index 37ac596..55fdb22 100644 > --- a/cpukit/score/include/rtems/score/threadimpl.h > +++ b/cpukit/score/include/rtems/score/threadimpl.h > @@ -1280,10 +1280,15 @@ RTEMS_INLINE_ROUTINE void > _Thread_Lock_restore_default( > #define THREAD_WAIT_CLASS_SYSTEM_EVENT 0x200U > > /** > - * @brief Indicates that the thread waits for a object. > + * @brief Indicates that the thread waits for an object. > */ > #define THREAD_WAIT_CLASS_OBJECT 0x400U > > +/** > + * @brief Indicates that the thread waits for a period. > + */ > +#define THREAD_WAIT_CLASS_PERIOD 0x800U > + > RTEMS_INLINE_ROUTINE void _Thread_Wait_flags_set( > Thread_Control *the_thread, > Thread_Wait_flags flags > diff --git a/testsuites/sptests/spintrcritical08/init.c > b/testsuites/sptests/spintrcritical08/init.c > index 3610e65..2e700da 100644 > --- a/testsuites/sptests/spintrcritical08/init.c > +++ b/testsuites/sptests/spintrcritical08/init.c > @@ -27,18 +27,14 @@ static volatile bool case_hit = false; > > static rtems_rate_monotonic_period_states getState(void) > { > - Objects_Locations location; > - Rate_monotonic_Control *period; > - > - period = (Rate_monotonic_Control *)_Objects_Get( > - &_Rate_monotonic_Information, Period, &location ); > - if ( location != OBJECTS_LOCAL ) { > - puts( "Bad object lookup" ); > - rtems_test_exit(0); > - } > - _Thread_Unnest_dispatch(); > + Rate_monotonic_Control *the_period; > + ISR_lock_Context lock_context; > + > + the_period = _Rate_monotonic_Get( Period, &lock_context ); > + rtems_test_assert( the_period != NULL ); > + _ISR_lock_ISR_enable( &lock_context ); > > - return period->state; > + return the_period->state; > } > > static rtems_timer_service_routine test_release_from_isr( > @@ -57,10 +53,14 @@ static rtems_timer_service_routine test_release_from_isr( > ) { > _Watchdog_Per_CPU_remove_relative( watchdog ); > > + rtems_test_assert( getState() == RATE_MONOTONIC_ACTIVE ); > + > (*watchdog->routine)( watchdog ); > > - if ( getState() == RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING ) { > + if ( getState() == RATE_MONOTONIC_EXPIRED ) { > case_hit = true; > + } else { > + rtems_test_assert( getState() == RATE_MONOTONIC_ACTIVE ); > } > } > } > -- > 1.8.4.5 > > _______________________________________________ > devel mailing list > devel@rtems.org > http://lists.rtems.org/mailman/listinfo/devel _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel