Changeset 90960bd in rtems


Ignore:
Timestamp:
Mar 21, 2016, 2:01:57 PM (4 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
master
Children:
baa13626
Parents:
875c26d
git-author:
Sebastian Huber <sebastian.huber@…> (03/21/16 14:01:57)
git-committer:
Sebastian Huber <sebastian.huber@…> (03/22/16 06:05:05)
Message:

rtems: Rework rate-monotonic scheduler

Use the default thread lock to protect rate-monotonic state changes.
This 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.

Files:
11 edited

Legend:

Unmodified
Added
Removed
  • cpukit/rtems/include/rtems/rtems/ratemon.h

    r875c26d r90960bd  
    8585  /**
    8686   * This value indicates the period is on the watchdog chain, and
    87    * the owner is blocked waiting on it.
    88    */
    89   RATE_MONOTONIC_OWNER_IS_BLOCKING,
    90 
    91   /**
    92    * This value indicates the period is on the watchdog chain, and
    9387   * running.  The owner should be executed or blocked waiting on
    9488   * another object.
    9589   */
    9690  RATE_MONOTONIC_ACTIVE,
    97 
    98   /**
    99    * This value indicates the period is on the watchdog chain, and
    100    * has expired.  The owner should be blocked waiting for the next period.
    101    */
    102   RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING,
    10391
    10492  /**
     
    195183
    196184/**
    197  *  The following structure defines the control block used to manage
    198  *  each period.
     185 * @brief The following structure defines the control block used to manage each
     186 * period.
     187 *
     188 * State changes are protected by the default thread lock of the owner thread.
     189 * The owner thread is the thread that created the period object.  The owner
     190 * thread field is immutable after object creation.
    199191 */
    200192typedef struct {
  • cpukit/rtems/include/rtems/rtems/ratemonimpl.h

    r875c26d r90960bd  
    99/*  COPYRIGHT (c) 1989-2008.
    1010 *  On-Line Applications Research Corporation (OAR).
     11 *  Copyright (c) 2016 embedded brains GmbH.
    1112 *
    1213 *  The license and distribution terms for this file may be
     
    2021#include <rtems/rtems/ratemon.h>
    2122#include <rtems/score/objectimpl.h>
     23#include <rtems/score/schedulerimpl.h>
     24#include <rtems/score/threadimpl.h>
     25#include <rtems/score/watchdogimpl.h>
    2226
    2327#include <string.h>
     
    3438 * @{
    3539 */
     40
     41#define RATE_MONOTONIC_INTEND_TO_BLOCK \
     42  ( THREAD_WAIT_CLASS_PERIOD | THREAD_WAIT_STATE_INTEND_TO_BLOCK )
     43
     44#define RATE_MONOTONIC_BLOCKED \
     45  ( THREAD_WAIT_CLASS_PERIOD | THREAD_WAIT_STATE_BLOCKED )
     46
     47#define RATE_MONOTONIC_READY_AGAIN \
     48  ( THREAD_WAIT_CLASS_PERIOD | THREAD_WAIT_STATE_READY_AGAIN )
    3649
    3750/**
     
    5669}
    5770
    58 /**
    59  *  @brief Allocates a period control block from
    60  *  the inactive chain of free period control blocks.
    61  *
    62  *  This routine allocates a period control block from
    63  *  the inactive chain of free period control blocks.
    64  */
    65 RTEMS_INLINE_ROUTINE void _Rate_monotonic_Free (
    66   Rate_monotonic_Control *the_period
     71RTEMS_INLINE_ROUTINE void _Rate_monotonic_Acquire_critical(
     72  Thread_Control   *the_thread,
     73  ISR_lock_Context *lock_context
    6774)
    6875{
    69   _Objects_Free( &_Rate_monotonic_Information, &the_period->Object );
     76  _Thread_Lock_acquire_default_critical( the_thread, lock_context );
    7077}
    7178
    72 /**
    73  *  @brief Maps period IDs to period control blocks.
    74  *
    75  *  This function maps period IDs to period control blocks.
    76  *  If ID corresponds to a local period, then it returns
    77  *  the_period control pointer which maps to ID and location
    78  *  is set to OBJECTS_LOCAL.  Otherwise, location is set
    79  *  to OBJECTS_ERROR and the_period is undefined.
    80  */
    81 RTEMS_INLINE_ROUTINE Rate_monotonic_Control *_Rate_monotonic_Get (
    82   Objects_Id         id,
    83   Objects_Locations *location
     79RTEMS_INLINE_ROUTINE void _Rate_monotonic_Release(
     80  Thread_Control   *the_thread,
     81  ISR_lock_Context *lock_context
     82)
     83{
     84  _Thread_Lock_release_default( the_thread, lock_context );
     85}
     86
     87RTEMS_INLINE_ROUTINE Rate_monotonic_Control *_Rate_monotonic_Get(
     88  Objects_Id        id,
     89  ISR_lock_Context *lock_context
    8490)
    8591{
    8692  return (Rate_monotonic_Control *)
    87     _Objects_Get( &_Rate_monotonic_Information, id, location );
     93    _Objects_Get_local( &_Rate_monotonic_Information, id, lock_context );
    8894}
    8995
    90 /**
    91  *  @brief Checks if the_period is in the ACTIVE state.
    92  *
    93  *  This function returns TRUE if the_period is in the ACTIVE state,
    94  *  and FALSE otherwise.
    95  */
    96 RTEMS_INLINE_ROUTINE bool _Rate_monotonic_Is_active (
    97   Rate_monotonic_Control *the_period
    98 )
    99 {
    100   return (the_period->state == RATE_MONOTONIC_ACTIVE);
    101 }
    102 
    103 /**
    104  *  @brief Checks if the_period is in the ACTIVE state.
    105  *
    106  *  This function returns TRUE if the_period is in the ACTIVE state,
    107  *  and FALSE otherwise.
    108  */
    109 RTEMS_INLINE_ROUTINE bool _Rate_monotonic_Is_inactive (
    110   Rate_monotonic_Control *the_period
    111 )
    112 {
    113   return (the_period->state == RATE_MONOTONIC_INACTIVE);
    114 }
    115 
    116 /**
    117  *  @brief Checks if the_period is in the EXPIRED state.
    118  *
    119  *  This function returns TRUE if the_period is in the EXPIRED state,
    120  *  and FALSE otherwise.
    121  */
    122 RTEMS_INLINE_ROUTINE bool _Rate_monotonic_Is_expired (
    123   Rate_monotonic_Control *the_period
    124 )
    125 {
    126   return (the_period->state == RATE_MONOTONIC_EXPIRED);
    127 }
    128 
    129 /**
    130  * @brief Rate Monotonic Timeout
    131  *
    132  * This routine is invoked when the period represented by the watchdog expires.
    133  * If the thread which owns this period is blocked waiting for the period to
    134  * expire, then it is readied and the period is restarted. If the owning thread
    135  * is not waiting for the period to expire, then the period is placed in the
    136  * EXPIRED state and not restarted.
    137  */
    13896void _Rate_monotonic_Timeout( Watchdog_Control *watchdog );
    13997
     
    159117);
    160118
    161 /**
    162  *  @brief Restart Rate Monotonic Period
    163  *
    164  *  This routine is invoked when a period is initiated via an explicit
    165  *  call to rtems_rate_monotonic_period for the period's first iteration
    166  *  or from _Rate_monotonic_Timeout for period iterations 2-n.
    167  *
    168  *  @param[in] the_period points to the period being operated upon.
    169  */
    170119void _Rate_monotonic_Restart(
    171   Rate_monotonic_Control *the_period
     120  Rate_monotonic_Control *the_period,
     121  Thread_Control         *owner,
     122  ISR_lock_Context       *lock_context
     123);
     124
     125void _Rate_monotonic_Cancel(
     126  Rate_monotonic_Control *the_period,
     127  Thread_Control         *owner,
     128  ISR_lock_Context       *lock_context
    172129);
    173130
  • cpukit/rtems/src/ratemoncancel.c

    r875c26d r90960bd  
    99 *  COPYRIGHT (c) 1989-2007.
    1010 *  On-Line Applications Research Corporation (OAR).
     11 *  Copyright (c) 2016 embedded brains GmbH.
    1112 *
    1213 *  The license and distribution terms for this file may be
     
    2021
    2122#include <rtems/rtems/ratemonimpl.h>
    22 #include <rtems/score/schedulerimpl.h>
    23 #include <rtems/score/threadimpl.h>
    24 #include <rtems/score/watchdogimpl.h>
     23
     24void _Rate_monotonic_Cancel(
     25  Rate_monotonic_Control *the_period,
     26  Thread_Control         *owner,
     27  ISR_lock_Context       *lock_context
     28)
     29{
     30  Per_CPU_Control *cpu_self;
     31
     32  _Watchdog_Per_CPU_remove_relative( &the_period->Timer );
     33
     34  owner = the_period->owner;
     35  _Rate_monotonic_Acquire_critical( owner, lock_context );
     36  the_period->state = RATE_MONOTONIC_INACTIVE;
     37
     38  cpu_self = _Thread_Dispatch_disable_critical( lock_context );
     39  _Rate_monotonic_Release( owner, lock_context );
     40
     41  _Scheduler_Release_job( owner, 0 );
     42
     43  _Thread_Dispatch_enable( cpu_self );
     44}
    2545
    2646rtems_status_code rtems_rate_monotonic_cancel(
     
    2949{
    3050  Rate_monotonic_Control *the_period;
    31   Objects_Locations       location;
    32   ISR_Level               level;
     51  ISR_lock_Context        lock_context;
     52  Thread_Control         *executing;
    3353
    34   the_period = _Rate_monotonic_Get( id, &location );
    35   switch ( location ) {
    36 
    37     case OBJECTS_LOCAL:
    38       if ( !_Thread_Is_executing( the_period->owner ) ) {
    39         _Objects_Put( &the_period->Object );
    40         return RTEMS_NOT_OWNER_OF_RESOURCE;
    41       }
    42       _ISR_Disable( level );
    43       _Watchdog_Per_CPU_remove_relative( &the_period->Timer );
    44       _ISR_Enable( level );
    45       the_period->state = RATE_MONOTONIC_INACTIVE;
    46       _Scheduler_Release_job( the_period->owner, 0 );
    47       _Objects_Put( &the_period->Object );
    48       return RTEMS_SUCCESSFUL;
    49 
    50 #if defined(RTEMS_MULTIPROCESSING)
    51     case OBJECTS_REMOTE:
    52 #endif
    53     case OBJECTS_ERROR:
    54       break;
     54  the_period = _Rate_monotonic_Get( id, &lock_context );
     55  if ( the_period == NULL ) {
     56    return RTEMS_INVALID_ID;
    5557  }
    5658
    57   return RTEMS_INVALID_ID;
     59  executing = _Thread_Executing;
     60  if ( executing != the_period->owner ) {
     61    _ISR_lock_ISR_enable( &lock_context );
     62    return RTEMS_NOT_OWNER_OF_RESOURCE;
     63  }
     64
     65  _Rate_monotonic_Cancel( the_period, executing, &lock_context );
     66  return RTEMS_SUCCESSFUL;
    5867}
  • cpukit/rtems/src/ratemondelete.c

    r875c26d r90960bd  
    99 *  COPYRIGHT (c) 1989-2007.
    1010 *  On-Line Applications Research Corporation (OAR).
     11 *  Copyright (c) 2016 embedded brains GmbH.
    1112 *
    1213 *  The license and distribution terms for this file may be
     
    2021
    2122#include <rtems/rtems/ratemonimpl.h>
    22 #include <rtems/score/schedulerimpl.h>
    23 #include <rtems/score/thread.h>
    24 #include <rtems/score/watchdogimpl.h>
    2523
    2624rtems_status_code rtems_rate_monotonic_delete(
     
    2927{
    3028  Rate_monotonic_Control *the_period;
    31   Objects_Locations       location;
    32   ISR_Level               level;
     29  ISR_lock_Context        lock_context;
     30  rtems_status_code       status;
    3331
    3432  _Objects_Allocator_lock();
    35   the_period = _Rate_monotonic_Get( id, &location );
    36   switch ( location ) {
    3733
    38     case OBJECTS_LOCAL:
    39       _Scheduler_Release_job( the_period->owner, 0 );
    40       _Objects_Close( &_Rate_monotonic_Information, &the_period->Object );
    41       _ISR_Disable( level );
    42       _Watchdog_Per_CPU_remove_relative( &the_period->Timer );
    43       _ISR_Enable( level );
    44       the_period->state = RATE_MONOTONIC_INACTIVE;
    45       _Objects_Put( &the_period->Object );
    46       _Rate_monotonic_Free( the_period );
    47       _Objects_Allocator_unlock();
    48       return RTEMS_SUCCESSFUL;
    49 
    50 #if defined(RTEMS_MULTIPROCESSING)
    51     case OBJECTS_REMOTE:            /* should never return this */
    52 #endif
    53     case OBJECTS_ERROR:
    54       break;
     34  the_period = _Rate_monotonic_Get( id, &lock_context );
     35  if ( the_period != NULL ) {
     36    _Objects_Close( &_Rate_monotonic_Information, &the_period->Object );
     37    _Rate_monotonic_Cancel( the_period, the_period->owner, &lock_context );
     38    _Objects_Free( &_Rate_monotonic_Information, &the_period->Object );
     39    status = RTEMS_SUCCESSFUL;
     40  } else {
     41    status = RTEMS_INVALID_ID;
    5542  }
    5643
    5744  _Objects_Allocator_unlock();
    5845
    59   return RTEMS_INVALID_ID;
     46  return status;
    6047}
  • cpukit/rtems/src/ratemongetstatistics.c

    r875c26d r90960bd  
    99 *  COPYRIGHT (c) 1989-2009.
    1010 *  On-Line Applications Research Corporation (OAR).
     11 *  Copyright (c) 2016 embedded brains GmbH.
    1112 *
    1213 *  The license and distribution terms for this file may be
     
    1920#endif
    2021
    21 #include <rtems/system.h>
    22 #include <rtems/rtems/status.h>
    23 #include <rtems/rtems/support.h>
    24 #include <rtems/score/isr.h>
    2522#include <rtems/rtems/ratemonimpl.h>
    26 #include <rtems/score/thread.h>
    2723
    2824rtems_status_code rtems_rate_monotonic_get_statistics(
    2925  rtems_id                                id,
    30   rtems_rate_monotonic_period_statistics *statistics
     26  rtems_rate_monotonic_period_statistics *dst
    3127)
    3228{
    33   Objects_Locations                        location;
    34   Rate_monotonic_Control                  *the_period;
    35   rtems_rate_monotonic_period_statistics  *dst;
    36   Rate_monotonic_Statistics              *src;
     29  Rate_monotonic_Control          *the_period;
     30  ISR_lock_Context                 lock_context;
     31  Thread_Control                  *owner;
     32  const Rate_monotonic_Statistics *src;
    3733
    38   if ( !statistics )
     34  if ( dst == NULL ) {
    3935    return RTEMS_INVALID_ADDRESS;
    40 
    41   the_period = _Rate_monotonic_Get( id, &location );
    42   switch ( location ) {
    43 
    44     case OBJECTS_LOCAL:
    45       dst = statistics;
    46       src = &the_period->Statistics;
    47       dst->count        = src->count;
    48       dst->missed_count = src->missed_count;
    49       _Timestamp_To_timespec( &src->min_cpu_time,   &dst->min_cpu_time );
    50       _Timestamp_To_timespec( &src->max_cpu_time,   &dst->max_cpu_time );
    51       _Timestamp_To_timespec( &src->total_cpu_time, &dst->total_cpu_time );
    52       _Timestamp_To_timespec( &src->min_wall_time,   &dst->min_wall_time );
    53       _Timestamp_To_timespec( &src->max_wall_time,   &dst->max_wall_time );
    54       _Timestamp_To_timespec( &src->total_wall_time, &dst->total_wall_time );
    55 
    56       _Objects_Put( &the_period->Object );
    57       return RTEMS_SUCCESSFUL;
    58 
    59 #if defined(RTEMS_MULTIPROCESSING)
    60     case OBJECTS_REMOTE:            /* should never return this */
    61 #endif
    62     case OBJECTS_ERROR:
    63       break;
    6436  }
    6537
    66   return RTEMS_INVALID_ID;
     38  the_period = _Rate_monotonic_Get( id, &lock_context );
     39  if ( the_period == NULL ) {
     40    return RTEMS_INVALID_ID;
     41  }
     42
     43  owner = the_period->owner;
     44  _Rate_monotonic_Acquire_critical( owner, &lock_context );
     45
     46  src = &the_period->Statistics;
     47  dst->count        = src->count;
     48  dst->missed_count = src->missed_count;
     49  _Timestamp_To_timespec( &src->min_cpu_time,    &dst->min_cpu_time );
     50  _Timestamp_To_timespec( &src->max_cpu_time,    &dst->max_cpu_time );
     51  _Timestamp_To_timespec( &src->total_cpu_time,  &dst->total_cpu_time );
     52  _Timestamp_To_timespec( &src->min_wall_time,   &dst->min_wall_time );
     53  _Timestamp_To_timespec( &src->max_wall_time,   &dst->max_wall_time );
     54  _Timestamp_To_timespec( &src->total_wall_time, &dst->total_wall_time );
     55
     56  _Rate_monotonic_Release( owner, &lock_context );
     57  return RTEMS_SUCCESSFUL;
    6758}
  • cpukit/rtems/src/ratemongetstatus.c

    r875c26d r90960bd  
    99 *  COPYRIGHT (c) 1989-2009.
    1010 *  On-Line Applications Research Corporation (OAR).
     11 *  Copyright (c) 2016 embedded brains GmbH.
    1112 *
    1213 *  The license and distribution terms for this file may be
     
    1920#endif
    2021
    21 #include <rtems/system.h>
    22 #include <rtems/rtems/status.h>
    23 #include <rtems/rtems/support.h>
    24 #include <rtems/score/isr.h>
    2522#include <rtems/rtems/ratemonimpl.h>
    26 #include <rtems/score/thread.h>
    27 #include <rtems/score/timespec.h>
    2823
    2924rtems_status_code rtems_rate_monotonic_get_status(
    3025  rtems_id                            id,
    31   rtems_rate_monotonic_period_status *status
     26  rtems_rate_monotonic_period_status *period_status
    3227)
    3328{
    34   Timestamp_Control       executed;
    35   Objects_Locations       location;
    36   Timestamp_Control       since_last_period;
    3729  Rate_monotonic_Control *the_period;
    38   bool                    valid_status;
     30  ISR_lock_Context        lock_context;
     31  Thread_Control         *owner;
     32  rtems_status_code       status;
    3933
    40   if ( !status )
     34  if ( period_status == NULL ) {
    4135    return RTEMS_INVALID_ADDRESS;
    42 
    43   the_period = _Rate_monotonic_Get( id, &location );
    44   switch ( location ) {
    45 
    46     case OBJECTS_LOCAL:
    47       status->owner = the_period->owner->Object.id;
    48       status->state = the_period->state;
    49 
    50       /*
    51        *  If the period is inactive, there is no information.
    52        */
    53       if ( status->state == RATE_MONOTONIC_INACTIVE ) {
    54         _Timespec_Set_to_zero( &status->since_last_period );
    55         _Timespec_Set_to_zero( &status->executed_since_last_period );
    56       } else {
    57 
    58         /*
    59          *  Grab the current status.
    60          */
    61         valid_status =
    62           _Rate_monotonic_Get_status(
    63             the_period, &since_last_period, &executed
    64           );
    65         if (!valid_status) {
    66           _Objects_Put( &the_period->Object );
    67           return RTEMS_NOT_DEFINED;
    68         }
    69 
    70         _Timestamp_To_timespec(
    71           &since_last_period, &status->since_last_period
    72         );
    73         _Timestamp_To_timespec(
    74           &executed, &status->executed_since_last_period
    75         );
    76       }
    77 
    78       _Objects_Put( &the_period->Object );
    79       return RTEMS_SUCCESSFUL;
    80 
    81 #if defined(RTEMS_MULTIPROCESSING)
    82     case OBJECTS_REMOTE:            /* should never return this */
    83 #endif
    84     case OBJECTS_ERROR:
    85       break;
    8636  }
    8737
    88   return RTEMS_INVALID_ID;
     38  the_period = _Rate_monotonic_Get( id, &lock_context );
     39  if ( the_period == NULL ) {
     40    return RTEMS_INVALID_ID;
     41  }
     42
     43  owner = the_period->owner;
     44  _Rate_monotonic_Acquire_critical( owner, &lock_context );
     45
     46  period_status->owner = owner->Object.id;
     47  period_status->state = the_period->state;
     48
     49  if ( the_period->state == RATE_MONOTONIC_INACTIVE ) {
     50    /*
     51     *  If the period is inactive, there is no information.
     52     */
     53    _Timespec_Set_to_zero( &period_status->since_last_period );
     54    _Timespec_Set_to_zero( &period_status->executed_since_last_period );
     55    status = RTEMS_SUCCESSFUL;
     56  } else {
     57    Timestamp_Control wall_since_last_period;
     58    Timestamp_Control cpu_since_last_period;
     59    bool              valid_status;
     60
     61    /*
     62     *  Grab the current status.
     63     */
     64    valid_status = _Rate_monotonic_Get_status(
     65      the_period,
     66      &wall_since_last_period,
     67      &cpu_since_last_period
     68    );
     69    if ( valid_status ) {
     70      _Timestamp_To_timespec(
     71        &wall_since_last_period,
     72        &period_status->since_last_period
     73      );
     74      _Timestamp_To_timespec(
     75        &cpu_since_last_period,
     76        &period_status->executed_since_last_period
     77      );
     78      status = RTEMS_SUCCESSFUL;
     79    } else {
     80      status = RTEMS_NOT_DEFINED;
     81    }
     82  }
     83
     84  _Rate_monotonic_Release( owner, &lock_context );
     85  return status;
    8986}
  • cpukit/rtems/src/ratemonperiod.c

    r875c26d r90960bd  
    99 *  COPYRIGHT (c) 1989-2010.
    1010 *  On-Line Applications Research Corporation (OAR).
     11 *  Copyright (c) 2016 embedded brains GmbH.
    1112 *
    1213 *  The license and distribution terms for this file may be
     
    2122#include <rtems/rtems/ratemonimpl.h>
    2223#include <rtems/score/schedulerimpl.h>
    23 #include <rtems/score/threadimpl.h>
    2424#include <rtems/score/todimpl.h>
    25 #include <rtems/score/watchdogimpl.h>
    2625
    2726bool _Rate_monotonic_Get_status(
     
    6564}
    6665
    67 void _Rate_monotonic_Restart( Rate_monotonic_Control *the_period )
    68 {
    69   ISR_Level level;
    70 
    71   /*
    72    *  Set the starting point and the CPU time used for the statistics.
    73    */
    74   _TOD_Get_uptime( &the_period->time_period_initiated );
    75   _Thread_Get_CPU_time_used(
    76     the_period->owner,
    77     &the_period->cpu_usage_period_initiated
    78   );
    79 
    80   _Scheduler_Release_job( the_period->owner, the_period->next_length );
    81 
    82   _ISR_Disable( level );
     66static void _Rate_monotonic_Release_job(
     67  Rate_monotonic_Control *the_period,
     68  Thread_Control         *owner,
     69  rtems_interval          next_length,
     70  ISR_lock_Context       *lock_context
     71)
     72{
     73  Per_CPU_Control *cpu_self;
     74
     75  cpu_self = _Thread_Dispatch_disable_critical( lock_context );
     76  _Rate_monotonic_Release( owner, lock_context );
     77
     78  _Scheduler_Release_job( owner, next_length );
     79
     80  _ISR_lock_ISR_disable( lock_context );
    8381  _Watchdog_Per_CPU_insert_relative(
    8482    &the_period->Timer,
    85     _Per_CPU_Get(),
    86     the_period->next_length
    87   );
    88   _ISR_Enable( level );
     83    cpu_self,
     84    next_length
     85  );
     86  _ISR_lock_ISR_enable( lock_context );
     87
     88  _Thread_Dispatch_enable( cpu_self );
     89}
     90
     91void _Rate_monotonic_Restart(
     92  Rate_monotonic_Control *the_period,
     93  Thread_Control         *owner,
     94  ISR_lock_Context       *lock_context
     95)
     96{
     97  /*
     98   *  Set the starting point and the CPU time used for the statistics.
     99   */
     100  _TOD_Get_uptime( &the_period->time_period_initiated );
     101  _Thread_Get_CPU_time_used( owner, &the_period->cpu_usage_period_initiated );
     102
     103  _Rate_monotonic_Release_job(
     104    the_period,
     105    owner,
     106    the_period->next_length,
     107    lock_context
     108  );
    89109}
    90110
     
    144164}
    145165
     166static rtems_status_code _Rate_monotonic_Get_status_for_state(
     167  rtems_rate_monotonic_period_states state
     168)
     169{
     170  switch ( state ) {
     171    case RATE_MONOTONIC_INACTIVE:
     172      return RTEMS_NOT_DEFINED;
     173    case RATE_MONOTONIC_EXPIRED:
     174      return RTEMS_TIMEOUT;
     175    default:
     176      _Assert( state == RATE_MONOTONIC_ACTIVE );
     177      return RTEMS_SUCCESSFUL;
     178  }
     179}
     180
     181static rtems_status_code _Rate_monotonic_Activate(
     182  Rate_monotonic_Control *the_period,
     183  rtems_interval          length,
     184  Thread_Control         *executing,
     185  ISR_lock_Context       *lock_context
     186)
     187{
     188  the_period->state = RATE_MONOTONIC_ACTIVE;
     189  the_period->next_length = length;
     190  _Rate_monotonic_Restart( the_period, executing, lock_context );
     191  return RTEMS_SUCCESSFUL;
     192}
     193
     194static rtems_status_code _Rate_monotonic_Block_while_active(
     195  Rate_monotonic_Control *the_period,
     196  rtems_interval          length,
     197  Thread_Control         *executing,
     198  ISR_lock_Context       *lock_context
     199)
     200{
     201  Per_CPU_Control *cpu_self;
     202  bool             success;
     203
     204  /*
     205   *  Update statistics from the concluding period.
     206   */
     207  _Rate_monotonic_Update_statistics( the_period );
     208
     209  /*
     210   *  This tells the _Rate_monotonic_Timeout that this task is
     211   *  in the process of blocking on the period and that we
     212   *  may be changing the length of the next period.
     213   */
     214  the_period->next_length = length;
     215  executing->Wait.return_argument = the_period;
     216  _Thread_Wait_flags_set( executing, RATE_MONOTONIC_INTEND_TO_BLOCK );
     217
     218  cpu_self = _Thread_Dispatch_disable_critical( lock_context );
     219  _Rate_monotonic_Release( executing, lock_context );
     220
     221  _Thread_Set_state( executing, STATES_WAITING_FOR_PERIOD );
     222
     223  success = _Thread_Wait_flags_try_change(
     224    executing,
     225    RATE_MONOTONIC_INTEND_TO_BLOCK,
     226    RATE_MONOTONIC_BLOCKED
     227  );
     228  if ( !success ) {
     229    _Assert(
     230      _Thread_Wait_flags_get( executing ) == RATE_MONOTONIC_READY_AGAIN
     231    );
     232    _Thread_Unblock( executing );
     233  }
     234
     235  _Thread_Dispatch_enable( cpu_self );
     236  return RTEMS_SUCCESSFUL;
     237}
     238
     239static rtems_status_code _Rate_monotonic_Block_while_expired(
     240  Rate_monotonic_Control *the_period,
     241  rtems_interval          length,
     242  Thread_Control         *executing,
     243  ISR_lock_Context       *lock_context
     244)
     245{
     246  /*
     247   *  Update statistics from the concluding period
     248   */
     249  _Rate_monotonic_Update_statistics( the_period );
     250
     251  the_period->state = RATE_MONOTONIC_ACTIVE;
     252  the_period->next_length = length;
     253
     254  _Rate_monotonic_Release_job( the_period, executing, length, lock_context );
     255  return RTEMS_TIMEOUT;
     256}
     257
    146258rtems_status_code rtems_rate_monotonic_period(
    147259  rtems_id       id,
     
    149261)
    150262{
    151   Rate_monotonic_Control              *the_period;
    152   Objects_Locations                    location;
    153   rtems_status_code                    return_value;
    154   rtems_rate_monotonic_period_states   local_state;
    155   ISR_Level                            level;
    156 
    157   the_period = _Rate_monotonic_Get( id, &location );
    158 
    159   switch ( location ) {
    160     case OBJECTS_LOCAL:
    161       if ( !_Thread_Is_executing( the_period->owner ) ) {
    162         _Objects_Put( &the_period->Object );
    163         return RTEMS_NOT_OWNER_OF_RESOURCE;
    164       }
    165 
    166       if ( length == RTEMS_PERIOD_STATUS ) {
    167         switch ( the_period->state ) {
    168           case RATE_MONOTONIC_INACTIVE:
    169             return_value = RTEMS_NOT_DEFINED;
    170             break;
    171           case RATE_MONOTONIC_EXPIRED:
    172           case RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING:
    173             return_value = RTEMS_TIMEOUT;
    174             break;
    175           case RATE_MONOTONIC_ACTIVE:
    176           default:              /* unreached -- only to remove warnings */
    177             return_value = RTEMS_SUCCESSFUL;
    178             break;
    179         }
    180         _Objects_Put( &the_period->Object );
    181         return( return_value );
    182       }
    183 
    184       _ISR_Disable( level );
    185       if ( the_period->state == RATE_MONOTONIC_INACTIVE ) {
    186         _ISR_Enable( level );
    187 
    188         the_period->state = RATE_MONOTONIC_ACTIVE;
    189         the_period->next_length = length;
    190         _Rate_monotonic_Restart( the_period );
    191         _Objects_Put( &the_period->Object );
    192         return RTEMS_SUCCESSFUL;
    193       }
    194 
    195       if ( the_period->state == RATE_MONOTONIC_ACTIVE ) {
    196         /*
    197          *  Update statistics from the concluding period.
    198          */
    199         _Rate_monotonic_Update_statistics( the_period );
    200 
    201         /*
    202          *  This tells the _Rate_monotonic_Timeout that this task is
    203          *  in the process of blocking on the period and that we
    204          *  may be changing the length of the next period.
    205          */
    206         the_period->state = RATE_MONOTONIC_OWNER_IS_BLOCKING;
    207         the_period->next_length = length;
    208 
    209         _ISR_Enable( level );
    210 
    211         _Thread_Executing->Wait.id = the_period->Object.id;
    212         _Thread_Set_state( _Thread_Executing, STATES_WAITING_FOR_PERIOD );
    213 
    214         /*
    215          *  Did the watchdog timer expire while we were actually blocking
    216          *  on it?
    217          */
    218         _ISR_Disable( level );
    219           local_state = the_period->state;
    220           the_period->state = RATE_MONOTONIC_ACTIVE;
    221         _ISR_Enable( level );
    222 
    223         /*
    224          *  If it did, then we want to unblock ourself and continue as
    225          *  if nothing happen.  The period was reset in the timeout routine.
    226          */
    227         if ( local_state == RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING )
    228           _Thread_Clear_state( _Thread_Executing, STATES_WAITING_FOR_PERIOD );
    229 
    230         _Objects_Put( &the_period->Object );
    231         return RTEMS_SUCCESSFUL;
    232       }
    233 
    234       if ( the_period->state == RATE_MONOTONIC_EXPIRED ) {
    235         /*
    236          *  Update statistics from the concluding period
    237          */
    238         _Rate_monotonic_Update_statistics( the_period );
    239 
    240         _ISR_Enable( level );
    241 
    242         the_period->state = RATE_MONOTONIC_ACTIVE;
    243         the_period->next_length = length;
    244 
    245         _Watchdog_Per_CPU_insert_relative(
    246           &the_period->Timer,
    247           _Per_CPU_Get(),
    248           length
     263  Rate_monotonic_Control            *the_period;
     264  ISR_lock_Context                   lock_context;
     265  Thread_Control                    *executing;
     266  rtems_status_code                  status;
     267  rtems_rate_monotonic_period_states state;
     268
     269  the_period = _Rate_monotonic_Get( id, &lock_context );
     270  if ( the_period == NULL ) {
     271    return RTEMS_INVALID_ID;
     272  }
     273
     274  executing = _Thread_Executing;
     275  if ( executing != the_period->owner ) {
     276    _ISR_lock_ISR_enable( &lock_context );
     277    return RTEMS_NOT_OWNER_OF_RESOURCE;
     278  }
     279
     280  _Rate_monotonic_Acquire_critical( executing, &lock_context );
     281
     282  state = the_period->state;
     283
     284  if ( length == RTEMS_PERIOD_STATUS ) {
     285    status = _Rate_monotonic_Get_status_for_state( state );
     286    _Rate_monotonic_Release( executing, &lock_context );
     287  } else {
     288    switch ( state ) {
     289      case RATE_MONOTONIC_ACTIVE:
     290        status = _Rate_monotonic_Block_while_active(
     291          the_period,
     292          length,
     293          executing,
     294          &lock_context
    249295        );
    250         _Scheduler_Release_job( the_period->owner, the_period->next_length );
    251         _Objects_Put( &the_period->Object );
    252         return RTEMS_TIMEOUT;
    253       }
    254 
    255       /*
    256        *  These should never happen so just return invalid Id.
    257        *    - RATE_MONOTONIC_OWNER_IS_BLOCKING:
    258        *    - RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING:
    259        */
    260 #if defined(RTEMS_MULTIPROCESSING)
    261     case OBJECTS_REMOTE:            /* should never return this */
    262 #endif
    263     case OBJECTS_ERROR:
    264       break;
    265   }
    266 
    267   return RTEMS_INVALID_ID;
    268 }
     296        break;
     297      case RATE_MONOTONIC_INACTIVE:
     298        status = _Rate_monotonic_Activate(
     299          the_period,
     300          length,
     301          executing,
     302          &lock_context
     303        );
     304        break;
     305      default:
     306        _Assert( state == RATE_MONOTONIC_EXPIRED );
     307        status = _Rate_monotonic_Block_while_expired(
     308          the_period,
     309          length,
     310          executing,
     311          &lock_context
     312        );
     313        break;
     314    }
     315  }
     316
     317  return status;
     318}
  • cpukit/rtems/src/ratemonresetstatistics.c

    r875c26d r90960bd  
    1919#endif
    2020
    21 #include <rtems/system.h>
    22 #include <rtems/rtems/status.h>
    23 #include <rtems/rtems/support.h>
    24 #include <rtems/score/isr.h>
    2521#include <rtems/rtems/ratemonimpl.h>
    26 #include <rtems/score/thread.h>
    27 
    28 /*
    29  *  rtems_rate_monotonic_reset_statistics
    30  *
    31  *  This directive allows a thread to reset the statistics information
    32  *  on a specific period instance.
    33  *
    34  *  Input parameters:
    35  *    id         - rate monotonic id
    36  *
    37  *  Output parameters:
    38  *    RTEMS_SUCCESSFUL - if successful
    39  *    error code       - if unsuccessful
    40  *
    41  */
    4222
    4323rtems_status_code rtems_rate_monotonic_reset_statistics(
     
    4525)
    4626{
    47   Objects_Locations              location;
    48   Rate_monotonic_Control        *the_period;
     27  Rate_monotonic_Control *the_period;
     28  ISR_lock_Context        lock_context;
     29  Thread_Control         *owner;
    4930
    50   the_period = _Rate_monotonic_Get( id, &location );
    51   switch ( location ) {
    52 
    53     case OBJECTS_LOCAL:
    54       _Rate_monotonic_Reset_statistics( the_period );
    55       _Objects_Put( &the_period->Object );
    56       return RTEMS_SUCCESSFUL;
    57 
    58 #if defined(RTEMS_MULTIPROCESSING)
    59     case OBJECTS_REMOTE:            /* should never return this */
    60 #endif
    61     case OBJECTS_ERROR:
    62       break;
     31  the_period = _Rate_monotonic_Get( id, &lock_context );
     32  if ( the_period == NULL ) {
     33    return RTEMS_INVALID_ID;
    6334  }
    6435
    65   return RTEMS_INVALID_ID;
     36  owner = the_period->owner;
     37  _Rate_monotonic_Acquire_critical( owner, &lock_context );
     38  _Rate_monotonic_Reset_statistics( the_period );
     39  _Rate_monotonic_Release( owner, &lock_context );
     40  return RTEMS_SUCCESSFUL;
    6641}
  • cpukit/rtems/src/ratemontimeout.c

    r875c26d r90960bd  
    2020
    2121#include <rtems/rtems/ratemonimpl.h>
    22 #include <rtems/score/threadimpl.h>
    23 #include <rtems/score/watchdogimpl.h>
    2422
    25 void _Rate_monotonic_Timeout( Watchdog_Control *watchdog )
     23void _Rate_monotonic_Timeout( Watchdog_Control *the_watchdog )
    2624{
    2725  Rate_monotonic_Control *the_period;
    28   Thread_Control         *the_thread;
     26  Thread_Control         *owner;
     27  ISR_lock_Context        lock_context;
     28  Thread_Wait_flags       wait_flags;
    2929
    30   /*
    31    *  When we get here, the Timer is already off the chain so we do not
    32    *  have to worry about that -- hence no _Watchdog_Remove().
    33    */
    34   the_period = RTEMS_CONTAINER_OF( watchdog, Rate_monotonic_Control, Timer );
    35   the_thread = the_period->owner;
     30  the_period = RTEMS_CONTAINER_OF( the_watchdog, Rate_monotonic_Control, Timer );
     31  owner = the_period->owner;
    3632
    37   _Thread_Disable_dispatch();
     33  _ISR_lock_ISR_disable( &lock_context );
     34  _Rate_monotonic_Acquire_critical( owner, &lock_context );
     35  wait_flags = _Thread_Wait_flags_get( owner );
    3836
    39   if ( _States_Is_waiting_for_period( the_thread->current_state ) &&
    40         the_thread->Wait.id == the_period->Object.id ) {
    41     _Thread_Unblock( the_thread );
    42     _Rate_monotonic_Restart( the_period );
    43   } else if ( the_period->state == RATE_MONOTONIC_OWNER_IS_BLOCKING ) {
    44     the_period->state = RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING;
    45     _Rate_monotonic_Restart( the_period );
     37  if (
     38    ( wait_flags & THREAD_WAIT_CLASS_PERIOD ) != 0
     39      && owner->Wait.return_argument == the_period
     40  ) {
     41    bool unblock;
     42    bool success;
     43
     44    owner->Wait.return_argument = NULL;
     45
     46    success = _Thread_Wait_flags_try_change_critical(
     47      owner,
     48      RATE_MONOTONIC_INTEND_TO_BLOCK,
     49      RATE_MONOTONIC_READY_AGAIN
     50    );
     51    if ( success ) {
     52      unblock = false;
     53    } else {
     54      _Assert( _Thread_Wait_flags_get( owner ) == RATE_MONOTONIC_BLOCKED );
     55      _Thread_Wait_flags_set( owner, RATE_MONOTONIC_READY_AGAIN );
     56      unblock = true;
     57    }
     58
     59    _Rate_monotonic_Restart( the_period, owner, &lock_context );
     60
     61    if ( unblock ) {
     62      _Thread_Unblock( owner );
     63    }
    4664  } else {
    4765    the_period->state = RATE_MONOTONIC_EXPIRED;
     66    _Rate_monotonic_Release( owner, &lock_context );
    4867  }
    49 
    50   _Thread_Unnest_dispatch();
    5168}
  • cpukit/score/include/rtems/score/threadimpl.h

    r875c26d r90960bd  
    12811281
    12821282/**
    1283  * @brief Indicates that the thread waits for a object.
     1283 * @brief Indicates that the thread waits for an object.
    12841284 */
    12851285#define THREAD_WAIT_CLASS_OBJECT 0x400U
     1286
     1287/**
     1288 * @brief Indicates that the thread waits for a period.
     1289 */
     1290#define THREAD_WAIT_CLASS_PERIOD 0x800U
    12861291
    12871292RTEMS_INLINE_ROUTINE void _Thread_Wait_flags_set(
  • testsuites/sptests/spintrcritical08/init.c

    r875c26d r90960bd  
    2626static volatile bool case_hit = false;
    2727
     28static Thread_Control *thread;
     29
    2830static rtems_rate_monotonic_period_states getState(void)
    2931{
    30   Objects_Locations       location;
    31   Rate_monotonic_Control *period;
     32  Rate_monotonic_Control *the_period;
     33  ISR_lock_Context        lock_context;
    3234
    33   period = (Rate_monotonic_Control *)_Objects_Get(
    34     &_Rate_monotonic_Information, Period, &location );
    35   if ( location != OBJECTS_LOCAL ) {
    36     puts( "Bad object lookup" );
    37     rtems_test_exit(0);
    38   }
    39   _Thread_Unnest_dispatch();
     35  the_period = _Rate_monotonic_Get( Period, &lock_context );
     36  rtems_test_assert( the_period != NULL );
     37  _ISR_lock_ISR_enable( &lock_context );
    4038
    41   return period->state;
     39  return the_period->state;
    4240}
    4341
     
    5654      && watchdog->routine == _Rate_monotonic_Timeout
    5755  ) {
     56    Thread_Wait_flags flags = _Thread_Wait_flags_get( thread );
     57
    5858    _Watchdog_Per_CPU_remove_relative( watchdog );
     59
     60    rtems_test_assert( getState() == RATE_MONOTONIC_ACTIVE );
    5961
    6062    (*watchdog->routine)( watchdog );
    6163
    62     if ( getState() == RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING ) {
     64    if ( flags == RATE_MONOTONIC_INTEND_TO_BLOCK ) {
     65      rtems_test_assert(
     66        _Thread_Wait_flags_get( thread ) == RATE_MONOTONIC_READY_AGAIN
     67      );
     68      rtems_test_assert( getState() == RATE_MONOTONIC_ACTIVE );
    6369      case_hit = true;
    6470    }
     
    9399
    94100  puts( "Init - Trying to generate period ending while blocking" );
     101
     102  thread = _Thread_Get_executing();
    95103
    96104  puts( "Init - rtems_rate_monotonic_create - OK" );
Note: See TracChangeset for help on using the changeset viewer.