Changeset ee0e4135 in rtems


Ignore:
Timestamp:
Aug 4, 2016, 8:20:29 AM (3 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
master
Children:
69dd99b
Parents:
ca783bbe
Message:

score: Fix a release/cancel job race condition

Split up the potential thread priority change in the scheduler
release/cancel job operation. Protect the rate monotonic period state
with a dedicated SMP lock. This avoids a race condition during
_Rate_monotonic_Timeout() while _Rate_monotonic_Cancel() is called on
another processor.

Location:
cpukit
Files:
16 edited

Legend:

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

    rca783bbe ree0e4135  
    195195  Objects_Control                         Object;
    196196
     197  /**
     198   * @brief Protects the rate monotonic period state.
     199   */
     200  ISR_LOCK_MEMBER(                        Lock )
     201
    197202  /** This is the timer used to provide the unblocking mechanism. */
    198203  Watchdog_Control                        Timer;
  • cpukit/rtems/include/rtems/rtems/ratemonimpl.h

    rca783bbe ree0e4135  
    7070
    7171RTEMS_INLINE_ROUTINE void _Rate_monotonic_Acquire_critical(
    72   Thread_Control   *the_thread,
    73   ISR_lock_Context *lock_context
     72  Rate_monotonic_Control *the_period,
     73  ISR_lock_Context       *lock_context
    7474)
    7575{
    76   _Thread_Wait_acquire_default_critical( the_thread, lock_context );
     76  _ISR_lock_Acquire( &the_period->Lock, lock_context );
    7777}
    7878
    7979RTEMS_INLINE_ROUTINE void _Rate_monotonic_Release(
    80   Thread_Control   *the_thread,
    81   ISR_lock_Context *lock_context
     80  Rate_monotonic_Control *the_period,
     81  ISR_lock_Context       *lock_context
    8282)
    8383{
    84   _Thread_Wait_release_default( the_thread, lock_context );
     84  _ISR_lock_Release_and_ISR_enable( &the_period->Lock, lock_context );
    8585}
    8686
  • cpukit/rtems/src/ratemoncancel.c

    rca783bbe ree0e4135  
    2929{
    3030  Per_CPU_Control *cpu_self;
     31  Thread_Control  *update_priority;
     32
     33  _Rate_monotonic_Acquire_critical( the_period, lock_context );
    3134
    3235  _Watchdog_Per_CPU_remove_relative( &the_period->Timer );
    33 
    34   owner = the_period->owner;
    35   _Rate_monotonic_Acquire_critical( owner, lock_context );
    3636  the_period->state = RATE_MONOTONIC_INACTIVE;
     37  update_priority = _Scheduler_Cancel_job( the_period->owner );
    3738
    3839  cpu_self = _Thread_Dispatch_disable_critical( lock_context );
    39   _Rate_monotonic_Release( owner, lock_context );
    40 
    41   _Scheduler_Cancel_job( owner );
    42 
     40  _Rate_monotonic_Release( the_period, lock_context );
     41  _Thread_Update_priority( update_priority );
    4342  _Thread_Dispatch_enable( cpu_self );
    4443}
  • cpukit/rtems/src/ratemoncreate.c

    rca783bbe ree0e4135  
    6363  }
    6464
     65  _ISR_lock_Initialize( &the_period->Lock, "Rate Monotonic Period" );
     66
    6567  the_period->owner = _Thread_Get_executing();
    6668  the_period->state = RATE_MONOTONIC_INACTIVE;
  • cpukit/rtems/src/ratemongetstatistics.c

    rca783bbe ree0e4135  
    2929  Rate_monotonic_Control          *the_period;
    3030  ISR_lock_Context                 lock_context;
    31   Thread_Control                  *owner;
    3231  const Rate_monotonic_Statistics *src;
    3332
     
    4140  }
    4241
    43   owner = the_period->owner;
    44   _Rate_monotonic_Acquire_critical( owner, &lock_context );
     42  _Rate_monotonic_Acquire_critical( the_period, &lock_context );
    4543
    4644  src = &the_period->Statistics;
     
    5452  _Timestamp_To_timespec( &src->total_wall_time, &dst->total_wall_time );
    5553
    56   _Rate_monotonic_Release( owner, &lock_context );
     54  _Rate_monotonic_Release( the_period, &lock_context );
    5755  return RTEMS_SUCCESSFUL;
    5856}
  • cpukit/rtems/src/ratemongetstatus.c

    rca783bbe ree0e4135  
    2929  Rate_monotonic_Control *the_period;
    3030  ISR_lock_Context        lock_context;
    31   Thread_Control         *owner;
    3231  rtems_status_code       status;
    3332
     
    4140  }
    4241
    43   owner = the_period->owner;
    44   _Rate_monotonic_Acquire_critical( owner, &lock_context );
     42  _Rate_monotonic_Acquire_critical( the_period, &lock_context );
    4543
    46   period_status->owner = owner->Object.id;
     44  period_status->owner = the_period->owner->Object.id;
    4745  period_status->state = the_period->state;
    4846
     
    8280  }
    8381
    84   _Rate_monotonic_Release( owner, &lock_context );
     82  _Rate_monotonic_Release( the_period, &lock_context );
    8583  return status;
    8684}
  • cpukit/rtems/src/ratemonperiod.c

    rca783bbe ree0e4135  
    7272{
    7373  Per_CPU_Control *cpu_self;
    74   uint64_t deadline;
     74  Thread_Control  *update_priority;
     75  uint64_t         deadline;
    7576
    7677  cpu_self = _Thread_Dispatch_disable_critical( lock_context );
    77   _Rate_monotonic_Release( owner, lock_context );
    78 
    79   _ISR_lock_ISR_disable( lock_context );
     78
    8079  deadline = _Watchdog_Per_CPU_insert_relative(
    8180    &the_period->Timer,
     
    8382    next_length
    8483  );
    85   _ISR_lock_ISR_enable( lock_context );
    86 
    87   _Scheduler_Release_job( owner, deadline );
    88 
     84  update_priority = _Scheduler_Release_job( owner, deadline );
     85
     86  _Rate_monotonic_Release( the_period, lock_context );
     87  _Thread_Update_priority( update_priority );
    8988  _Thread_Dispatch_enable( cpu_self );
    9089}
     
    218217
    219218  cpu_self = _Thread_Dispatch_disable_critical( lock_context );
    220   _Rate_monotonic_Release( executing, lock_context );
     219  _Rate_monotonic_Release( the_period, lock_context );
    221220
    222221  _Thread_Set_state( executing, STATES_WAITING_FOR_PERIOD );
     
    279278  }
    280279
    281   _Rate_monotonic_Acquire_critical( executing, &lock_context );
     280  _Rate_monotonic_Acquire_critical( the_period, &lock_context );
    282281
    283282  state = the_period->state;
     
    285284  if ( length == RTEMS_PERIOD_STATUS ) {
    286285    status = _Rate_monotonic_Get_status_for_state( state );
    287     _Rate_monotonic_Release( executing, &lock_context );
     286    _Rate_monotonic_Release( the_period, &lock_context );
    288287  } else {
    289288    switch ( state ) {
  • cpukit/rtems/src/ratemonresetstatistics.c

    rca783bbe ree0e4135  
    2727  Rate_monotonic_Control *the_period;
    2828  ISR_lock_Context        lock_context;
    29   Thread_Control         *owner;
    3029
    3130  the_period = _Rate_monotonic_Get( id, &lock_context );
     
    3433  }
    3534
    36   owner = the_period->owner;
    37   _Rate_monotonic_Acquire_critical( owner, &lock_context );
     35  _Rate_monotonic_Acquire_critical( the_period, &lock_context );
    3836  _Rate_monotonic_Reset_statistics( the_period );
    39   _Rate_monotonic_Release( owner, &lock_context );
     37  _Rate_monotonic_Release( the_period, &lock_context );
    4038  return RTEMS_SUCCESSFUL;
    4139}
  • cpukit/rtems/src/ratemontimeout.c

    rca783bbe ree0e4135  
    3232
    3333  _ISR_lock_ISR_disable( &lock_context );
    34   _Rate_monotonic_Acquire_critical( owner, &lock_context );
     34  _Rate_monotonic_Acquire_critical( the_period, &lock_context );
    3535  wait_flags = _Thread_Wait_flags_get( owner );
    3636
     
    6464  } else {
    6565    the_period->state = RATE_MONOTONIC_EXPIRED;
    66     _Rate_monotonic_Release( owner, &lock_context );
     66    _Rate_monotonic_Release( the_period, &lock_context );
    6767  }
    6868}
  • cpukit/score/include/rtems/score/scheduler.h

    rca783bbe ree0e4135  
    140140
    141141  /** @see _Scheduler_Release_job() */
    142   void ( *release_job ) (
     142  Thread_Control *( *release_job ) (
    143143    const Scheduler_Control *,
    144144    Thread_Control *,
     
    147147
    148148  /** @see _Scheduler_Cancel_job() */
    149   void ( *cancel_job ) (
     149  Thread_Control *( *cancel_job ) (
    150150    const Scheduler_Control *,
    151151    Thread_Control *
     
    534534 * @param[in] the_thread Unused.
    535535 * @param[in] deadline Unused.
    536  */
    537 void _Scheduler_default_Release_job(
     536 *
     537 * @retval NULL Always.
     538 */
     539Thread_Control *_Scheduler_default_Release_job(
    538540  const Scheduler_Control *scheduler,
    539541  Thread_Control          *the_thread,
     
    546548 * @param[in] scheduler Unused.
    547549 * @param[in] the_thread Unused.
    548  */
    549 void _Scheduler_default_Cancel_job(
     550 *
     551 * @retval NULL Always.
     552 */
     553Thread_Control *_Scheduler_default_Cancel_job(
    550554  const Scheduler_Control *scheduler,
    551555  Thread_Control          *the_thread
  • cpukit/score/include/rtems/score/schedulercbs.h

    rca783bbe ree0e4135  
    164164);
    165165
    166 /**
    167  *  @brief Called when a new job of task is released.
    168  *
    169  *  This routine is called when a new job of task is released.
    170  *  It is called only from Rate Monotonic manager in the beginning
    171  *  of new period. Deadline has to be shifted and budget replenished.
    172  *
    173  *  @param[in] scheduler The scheduler instance.
    174  *  @param[in] the_thread is the owner of the job.
    175  *  @param[in] length of the new job from now. If equal to 0,
    176  *             the job was cancelled or deleted.
    177  */
    178 
    179 void _Scheduler_CBS_Release_job (
     166Thread_Control *_Scheduler_CBS_Release_job(
    180167  const Scheduler_Control *scheduler,
    181168  Thread_Control          *the_thread,
  • cpukit/score/include/rtems/score/scheduleredf.h

    rca783bbe ree0e4135  
    216216);
    217217
    218 /**
    219  *  @brief Called when a new job of task is released.
    220  *
    221  *  This routine is called when a new job of task is released.
    222  *  It is called only from Rate Monotonic manager in the beginning
    223  *  of new period.
    224  *
    225  *  @param[in] scheduler The scheduler instance.
    226  *  @param[in] the_thread is the owner of the job.
    227  *  @param[in] deadline of the new job from now. If equal to 0,
    228  *             the job was cancelled or deleted, thus a running task
    229  *             has to be suspended.
    230  */
    231 void _Scheduler_EDF_Release_job(
     218Thread_Control *_Scheduler_EDF_Release_job(
    232219  const Scheduler_Control *scheduler,
    233220  Thread_Control          *the_thread,
     
    235222);
    236223
    237 void _Scheduler_EDF_Cancel_job(
     224Thread_Control *_Scheduler_EDF_Cancel_job(
    238225  const Scheduler_Control *scheduler,
    239226  Thread_Control          *the_thread
  • cpukit/score/include/rtems/score/schedulerimpl.h

    rca783bbe ree0e4135  
    497497 * @param[in] the_thread The thread.
    498498 * @param[in] deadline The deadline in watchdog ticks since boot.
    499  */
    500 RTEMS_INLINE_ROUTINE void _Scheduler_Release_job(
     499 *
     500 * @return The thread to hand over to _Thread_Update_priority().
     501 */
     502RTEMS_INLINE_ROUTINE Thread_Control *_Scheduler_Release_job(
    501503  Thread_Control *the_thread,
    502504  uint64_t        deadline
     
    505507  const Scheduler_Control *scheduler = _Scheduler_Get( the_thread );
    506508
    507   ( *scheduler->Operations.release_job )( scheduler, the_thread, deadline );
     509  return ( *scheduler->Operations.release_job )(
     510    scheduler,
     511    the_thread,
     512    deadline
     513  );
    508514}
    509515
     
    512518 *
    513519 * @param[in] the_thread The thread.
    514  */
    515 RTEMS_INLINE_ROUTINE void _Scheduler_Cancel_job(
     520 *
     521 * @return The thread to hand over to _Thread_Update_priority().
     522 */
     523RTEMS_INLINE_ROUTINE Thread_Control *_Scheduler_Cancel_job(
    516524  Thread_Control *the_thread
    517525)
     
    519527  const Scheduler_Control *scheduler = _Scheduler_Get( the_thread );
    520528
    521   ( *scheduler->Operations.cancel_job )( scheduler, the_thread );
     529  return ( *scheduler->Operations.cancel_job )( scheduler, the_thread );
    522530}
    523531
  • cpukit/score/src/schedulercbsreleasejob.c

    rca783bbe ree0e4135  
    2222#include <rtems/score/schedulercbsimpl.h>
    2323
    24 void _Scheduler_CBS_Release_job(
     24Thread_Control *_Scheduler_CBS_Release_job(
    2525  const Scheduler_Control *scheduler,
    2626  Thread_Control          *the_thread,
     
    3131  Scheduler_CBS_Server *serv_info;
    3232
    33   _Scheduler_EDF_Release_job( scheduler, the_thread, deadline );
    34 
    3533  node = _Scheduler_CBS_Thread_get_node( the_thread );
    3634  serv_info = node->cbs_server;
     
    4038    the_thread->cpu_time_budget = serv_info->parameters.budget;
    4139  }
     40
     41  return _Scheduler_EDF_Release_job( scheduler, the_thread, deadline );
    4242}
  • cpukit/score/src/schedulerdefaultreleasejob.c

    rca783bbe ree0e4135  
    2222#include <rtems/score/scheduler.h>
    2323
    24 void _Scheduler_default_Release_job(
     24Thread_Control *_Scheduler_default_Release_job(
    2525  const Scheduler_Control *scheduler,
    2626  Thread_Control          *the_thread,
     
    3131  (void) the_thread;
    3232  (void) deadline;
     33
     34  return NULL;
    3335}
    3436
    35 void _Scheduler_default_Cancel_job(
     37Thread_Control *_Scheduler_default_Cancel_job(
    3638  const Scheduler_Control *scheduler,
    3739  Thread_Control          *the_thread
     
    4042  (void) scheduler;
    4143  (void) the_thread;
     44
     45  return NULL;
    4246}
  • cpukit/score/src/scheduleredfreleasejob.c

    rca783bbe ree0e4135  
    4343}
    4444
    45 void _Scheduler_EDF_Release_job(
     45Thread_Control *_Scheduler_EDF_Release_job(
    4646  const Scheduler_Control *scheduler,
    4747  Thread_Control          *the_thread,
     
    4949)
    5050{
    51   _Thread_Change_priority(
     51  return _Thread_Apply_priority(
    5252    the_thread,
    5353    deadline,
     
    8080}
    8181
    82 void _Scheduler_EDF_Cancel_job(
     82Thread_Control *_Scheduler_EDF_Cancel_job(
    8383  const Scheduler_Control *scheduler,
    8484  Thread_Control          *the_thread
    8585)
    8686{
    87   _Thread_Change_priority(
     87  return _Thread_Apply_priority(
    8888    the_thread,
    8989    0,
Note: See TracChangeset for help on using the changeset viewer.