Changeset 900d337f in rtems


Ignore:
Timestamp:
May 5, 2015, 11:05:54 AM (4 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
4.11, master
Children:
80f376d
Parents:
4438ac25
git-author:
Sebastian Huber <sebastian.huber@…> (05/05/15 11:05:54)
git-committer:
Sebastian Huber <sebastian.huber@…> (05/19/15 10:00:47)
Message:

score: Rework _Thread_Change_priority()

Move the writes to Thread_Control::current_priority and
Thread_Control::real_priority into _Thread_Change_priority() under the
protection of the thread lock. Add a filter function to
_Thread_Change_priority() to enable specialized variants.

Avoid race conditions during a thread priority restore with the new
Thread_Control::priority_restore_hint for an important average case
optimizations used by priority inheritance mutexes.

Update #2273.

Files:
20 edited

Legend:

Unmodified
Added
Removed
  • cpukit/posix/src/pthread.c

    r4438ac25 r900d337f  
    8484};
    8585
     86static bool _POSIX_Threads_Sporadic_budget_TSR_filter(
     87  Thread_Control   *the_thread,
     88  Priority_Control *new_priority,
     89  void             *arg
     90)
     91{
     92  the_thread->real_priority = *new_priority;
     93
     94  /*
     95   * If holding a resource, then do not change it.
     96   *
     97   * If this would make them less important, then do not change it.
     98   */
     99  return !_Thread_Owns_resources( the_thread ) &&
     100    _Thread_Priority_less_than( the_thread->current_priority, *new_priority );
     101}
     102
    86103/*
    87104 *  _POSIX_Threads_Sporadic_budget_TSR
     
    93110{
    94111  uint32_t            ticks;
    95   uint32_t            new_priority;
    96112  Thread_Control     *the_thread;
    97113  POSIX_API_Control  *api;
     
    106122  the_thread->cpu_time_budget = ticks;
    107123
    108   new_priority = _POSIX_Priority_To_core( api->schedparam.sched_priority );
    109   the_thread->real_priority = new_priority;
    110 
    111   /*
    112    *  If holding a resource, then do not change it.
    113    */
    114   #if 0
    115     printk( "TSR %d %d %d\n", the_thread->resource_count,
    116         the_thread->current_priority, new_priority );
    117   #endif
    118   if ( !_Thread_Owns_resources( the_thread ) ) {
    119     /*
    120      *  If this would make them less important, then do not change it.
    121      */
    122     if ( the_thread->current_priority > new_priority ) {
    123       _Thread_Change_priority( the_thread, new_priority, true );
    124       #if 0
    125         printk( "raise priority\n" );
    126       #endif
    127     }
    128   }
     124  _Thread_Change_priority(
     125    the_thread,
     126    _POSIX_Priority_To_core( api->schedparam.sched_priority ),
     127    NULL,
     128    _POSIX_Threads_Sporadic_budget_TSR_filter,
     129    true
     130  );
    129131
    130132  /* ticks is guaranteed to be at least one */
     
    134136}
    135137
     138static bool _POSIX_Threads_Sporadic_budget_callout_filter(
     139  Thread_Control   *the_thread,
     140  Priority_Control *new_priority,
     141  void             *arg
     142)
     143{
     144  the_thread->real_priority = *new_priority;
     145
     146  /*
     147   * If holding a resource, then do not change it.
     148   *
     149   * Make sure we are actually lowering it. If they have lowered it
     150   * to logically lower than sched_ss_low_priority, then we do not want to
     151   * change it.
     152   */
     153  return !_Thread_Owns_resources( the_thread ) &&
     154    _Thread_Priority_less_than( *new_priority, the_thread->current_priority );
     155}
     156
    136157/*
    137158 *  _POSIX_Threads_Sporadic_budget_callout
     
    142163{
    143164  POSIX_API_Control *api;
    144   uint32_t           new_priority;
    145165
    146166  api = the_thread->API_Extensions[ THREAD_API_POSIX ];
     
    152172  the_thread->cpu_time_budget = UINT32_MAX;
    153173
    154   new_priority = _POSIX_Priority_To_core(api->schedparam.sched_ss_low_priority);
    155   the_thread->real_priority = new_priority;
    156 
    157   /*
    158    *  If holding a resource, then do not change it.
    159    */
    160   #if 0
    161     printk( "callout %d %d %d\n", the_thread->resource_count,
    162         the_thread->current_priority, new_priority );
    163   #endif
    164   if ( !_Thread_Owns_resources( the_thread ) ) {
    165     /*
    166      *  Make sure we are actually lowering it. If they have lowered it
    167      *  to logically lower than sched_ss_low_priority, then we do not want to
    168      *  change it.
    169      */
    170     if ( the_thread->current_priority < new_priority ) {
    171       _Thread_Change_priority( the_thread, new_priority, true );
    172       #if 0
    173         printk( "lower priority\n" );
    174       #endif
    175     }
    176   }
     174  _Thread_Change_priority(
     175    the_thread,
     176    _POSIX_Priority_To_core( api->schedparam.sched_ss_low_priority ),
     177    NULL,
     178    _POSIX_Threads_Sporadic_budget_callout_filter,
     179    true
     180  );
    177181}
    178182
  • cpukit/posix/src/pthreadsetschedparam.c

    r4438ac25 r900d337f  
    4545  Objects_Locations                    location;
    4646  int                                  rc;
     47  Priority_Control                     unused;
    4748
    4849  /*
     
    8889            rtems_configuration_get_ticks_per_timeslice();
    8990
    90           the_thread->real_priority =
    91             _POSIX_Priority_To_core( api->schedparam.sched_priority );
    92 
    93           _Thread_Change_priority(
    94              the_thread,
    95              the_thread->real_priority,
    96              true
     91          _Thread_Set_priority(
     92            the_thread,
     93            _POSIX_Priority_To_core( api->schedparam.sched_priority ),
     94            &unused,
     95            true
    9796          );
    9897          break;
  • cpukit/rtems/src/tasksetpriority.c

    r4438ac25 r900d337f  
    4242
    4343    case OBJECTS_LOCAL:
    44       *old_priority = _RTEMS_tasks_Priority_from_Core(
    45                         the_thread->current_priority
    46                       );
    4744      if ( new_priority != RTEMS_CURRENT_PRIORITY ) {
    48         the_thread->real_priority = _RTEMS_tasks_Priority_to_Core(
    49                                       new_priority
    50                                     );
    51         if ( !_Thread_Owns_resources( the_thread ) ||
    52              the_thread->current_priority > new_priority )
    53           _Thread_Change_priority( the_thread, new_priority, false );
     45        _Thread_Set_priority(
     46          the_thread,
     47          _RTEMS_tasks_Priority_to_Core( new_priority ),
     48          old_priority,
     49          false
     50        );
     51        *old_priority = _RTEMS_tasks_Priority_from_Core( *old_priority );
     52      } else {
     53        *old_priority = _RTEMS_tasks_Priority_from_Core(
     54          the_thread->current_priority
     55        );
    5456      }
    5557      _Objects_Put( &the_thread->Object );
  • cpukit/score/include/rtems/score/coremuteximpl.h

    r4438ac25 r900d337f  
    492492        cpu_self = _Thread_Dispatch_disable_critical();
    493493        _Thread_queue_Release( &the_mutex->Wait_queue, lock_context );
    494         _Thread_Change_priority(
    495           executing,
    496           ceiling,
    497           false
    498         );
     494        _Thread_Raise_priority( executing, ceiling );
    499495        _Thread_Dispatch_enable( cpu_self );
    500496        return 0;
  • cpukit/score/include/rtems/score/mrspimpl.h

    r4438ac25 r900d337f  
    3737 */
    3838
    39 RTEMS_INLINE_ROUTINE void _MRSP_Elevate_priority(
    40   MRSP_Control     *mrsp,
    41   Thread_Control   *new_owner,
    42   Priority_Control  ceiling_priority
    43 )
    44 {
    45   _Thread_Change_priority( new_owner, ceiling_priority, false );
     39RTEMS_INLINE_ROUTINE bool _MRSP_Restore_priority_filter(
     40  Thread_Control   *thread,
     41  Priority_Control *new_priority,
     42  void             *arg
     43)
     44{
     45  *new_priority = _Thread_Priority_highest(
     46    thread->real_priority,
     47    *new_priority
     48  );
     49
     50  return *new_priority != thread->current_priority;
    4651}
    4752
     
    5661   */
    5762  if ( thread->resource_count == 0 ) {
    58     Priority_Control new_priority = _Scheduler_Highest_priority_of_two(
    59       _Scheduler_Get( thread ),
     63    _Thread_Change_priority(
     64      thread,
    6065      initial_priority,
    61       thread->real_priority
     66      NULL,
     67      _MRSP_Restore_priority_filter,
     68      true
    6269    );
    63 
    64     _Thread_Change_priority( thread, new_priority, true );
    6570  }
    6671}
     
    7681  _Resource_Set_owner( &mrsp->Resource, &new_owner->Resource_node );
    7782  mrsp->initial_priority_of_owner = initial_priority;
    78   _MRSP_Elevate_priority( mrsp, new_owner, ceiling_priority );
     83  _Thread_Raise_priority( new_owner, ceiling_priority );
    7984  _Scheduler_Thread_change_help_state( new_owner, SCHEDULER_HELP_ACTIVE_OWNER );
    8085}
     
    178183  rival.status = MRSP_WAIT_FOR_OWNERSHIP;
    179184
    180   _MRSP_Elevate_priority( mrsp, executing, ceiling_priority );
     185  _Thread_Raise_priority( executing, ceiling_priority );
    181186
    182187  _ISR_Disable( level );
     
    236241  Priority_Control ceiling_priority =
    237242    _MRSP_Get_ceiling_priority( mrsp, scheduler_index );
    238   bool priority_ok = !_Scheduler_Is_priority_higher_than(
    239     scheduler,
    240     initial_priority,
    241     ceiling_priority
     243  bool priority_ok = !_Thread_Priority_less_than(
     244    ceiling_priority,
     245    initial_priority
    242246  );
    243247  Resource_Node *owner;
  • cpukit/score/include/rtems/score/schedulerimpl.h

    r4438ac25 r900d337f  
    692692{
    693693  return _Scheduler_Priority_compare( scheduler, p1,  p2 ) > 0;
    694 }
    695 
    696 /**
    697  * @brief Returns the priority encoding @a p1 or @a p2 with the higher priority
    698  * in the intuitive sense of priority.
    699  */
    700 RTEMS_INLINE_ROUTINE Priority_Control _Scheduler_Highest_priority_of_two(
    701   const Scheduler_Control *scheduler,
    702   Priority_Control         p1,
    703   Priority_Control         p2
    704 )
    705 {
    706   return _Scheduler_Is_priority_higher_than( scheduler, p1, p2 ) ? p1 : p2;
    707 }
    708 
    709 /**
    710  * @brief Sets the thread priority to @a priority if it is higher than the
    711  * current priority of the thread in the intuitive sense of priority.
    712  */
    713 RTEMS_INLINE_ROUTINE void _Scheduler_Set_priority_if_higher(
    714   const Scheduler_Control *scheduler,
    715   Thread_Control          *the_thread,
    716   Priority_Control         priority
    717 )
    718 {
    719   Priority_Control current = the_thread->current_priority;
    720 
    721   if ( _Scheduler_Is_priority_higher_than( scheduler, priority, current ) ) {
    722     _Thread_Set_priority( the_thread, priority );
    723   }
    724 }
    725 
    726 /**
    727  * @brief Changes the thread priority to @a priority if it is higher than the
    728  * current priority of the thread in the intuitive sense of priority.
    729  */
    730 RTEMS_INLINE_ROUTINE void _Scheduler_Change_priority_if_higher(
    731   const Scheduler_Control *scheduler,
    732   Thread_Control          *the_thread,
    733   Priority_Control         priority,
    734   bool                     prepend_it
    735 )
    736 {
    737   Priority_Control current = the_thread->current_priority;
    738 
    739   if ( _Scheduler_Is_priority_higher_than( scheduler, priority, current ) ) {
    740     _Thread_Change_priority( the_thread, priority, prepend_it );
    741   }
    742694}
    743695
  • cpukit/score/include/rtems/score/thread.h

    r4438ac25 r900d337f  
    367367  /** This field is the current execution state of this proxy. */
    368368  States_Control           current_state;
    369   /** This field is the current priority state of this proxy. */
     369
     370  /**
     371   * @brief This field is the current priority state of this thread.
     372   *
     373   * Writes to this field are only allowed in _Thread_Initialize() or via
     374   * _Thread_Change_priority().
     375   */
    370376  Priority_Control         current_priority;
    371   /** This field is the base priority of this proxy. */
     377
     378  /**
     379   * @brief This field is the base priority of this thread.
     380   *
     381   * Writes to this field are only allowed in _Thread_Initialize() or via
     382   * _Thread_Change_priority().
     383   */
    372384  Priority_Control         real_priority;
    373385
     
    379391   */
    380392  uint32_t                 priority_generation;
     393
     394  /**
     395   * @brief Hints if a priority restore is necessary once the resource count
     396   * changes from one to zero.
     397   *
     398   * This is an optimization to speed up the mutex surrender sequence in case
     399   * no attempt to change the priority was made during the mutex ownership.  On
     400   * SMP configurations atomic fences must synchronize writes to
     401   * Thread_Control::priority_restore_hint and Thread_Control::resource_count.
     402   */
     403  bool                     priority_restore_hint;
    381404
    382405  /** This field is the number of mutexes currently held by this proxy. */
     
    654677  /** This field is the current execution state of this thread. */
    655678  States_Control           current_state;
    656   /** This field is the current priority state of this thread. */
     679
     680  /**
     681   * @brief This field is the current priority state of this thread.
     682   *
     683   * Writes to this field are only allowed in _Thread_Initialize() or via
     684   * _Thread_Change_priority().
     685   */
    657686  Priority_Control         current_priority;
    658   /** This field is the base priority of this thread. */
     687
     688  /**
     689   * @brief This field is the base priority of this thread.
     690   *
     691   * Writes to this field are only allowed in _Thread_Initialize() or via
     692   * _Thread_Change_priority().
     693   */
    659694  Priority_Control         real_priority;
    660695
     
    666701   */
    667702  uint32_t                 priority_generation;
     703
     704  /**
     705   * @brief Hints if a priority restore is necessary once the resource count
     706   * changes from one to zero.
     707   *
     708   * This is an optimization to speed up the mutex surrender sequence in case
     709   * no attempt to change the priority was made during the mutex ownership.  On
     710   * SMP configurations atomic fences must synchronize writes to
     711   * Thread_Control::priority_restore_hint and Thread_Control::resource_count.
     712   */
     713  bool                     priority_restore_hint;
    668714
    669715  /** This field is the number of mutexes currently held by this thread. */
  • cpukit/score/include/rtems/score/threadimpl.h

    r4438ac25 r900d337f  
    334334
    335335/**
    336  *  @brief Change the priority of a thread.
    337  *
    338  *  This routine changes the current priority of @a the_thread to
    339  *  @a new_priority.  It performs any necessary scheduling operations
    340  *  including the selection of a new heir thread.
    341  *
    342  *  @param[in] the_thread is the thread to change
    343  *  @param[in] new_priority is the priority to set @a the_thread to
    344  *  @param[in] prepend_it is a switch to prepend the thread
    345  */
    346 void _Thread_Change_priority (
     336 * @brief Returns true if the left thread priority is less than the right
     337 * thread priority in the intuitive sense of priority and false otherwise.
     338 */
     339RTEMS_INLINE_ROUTINE bool _Thread_Priority_less_than(
     340  Priority_Control left,
     341  Priority_Control right
     342)
     343{
     344  return left > right;
     345}
     346
     347/**
     348 * @brief Returns the highest priority of the left and right thread priorities
     349 * in the intuitive sense of priority.
     350 */
     351RTEMS_INLINE_ROUTINE Priority_Control _Thread_Priority_highest(
     352  Priority_Control left,
     353  Priority_Control right
     354)
     355{
     356  return _Thread_Priority_less_than( left, right ) ? right : left;
     357}
     358
     359/**
     360 * @brief Filters a thread priority change.
     361 *
     362 * Called by _Thread_Change_priority() under the protection of the thread lock.
     363 *
     364 * @param[in] the_thread The thread.
     365 * @param[in, out] new_priority The new priority of the thread.  The filter may
     366 * alter this value.
     367 * @param[in] arg The argument passed to _Thread_Change_priority().
     368 *
     369 * @retval true Change the current priority.
     370 * @retval false Otherwise.
     371 */
     372typedef bool ( *Thread_Change_priority_filter )(
     373  Thread_Control   *the_thread,
     374  Priority_Control *new_priority,
     375  void             *arg
     376);
     377
     378/**
     379 * @brief Changes the priority of a thread if allowed by the filter function.
     380 *
     381 * It changes current priority of the thread to the new priority in case the
     382 * filter function returns true.  In this case the scheduler is notified of the
     383 * priority change as well.
     384 *
     385 * @param[in] the_thread The thread.
     386 * @param[in] new_priority The new priority of the thread.
     387 * @param[in] arg The argument for the filter function.
     388 * @param[in] filter The filter function to determine if a priority change is
     389 * allowed and optionally perform other actions under the protection of the
     390 * thread lock simultaneously with the update of the current priority.
     391 * @param[in] prepend_it In case this is true, then the thread is prepended to
     392 * its priority group in its scheduler instance, otherwise it is appended.
     393 */
     394void _Thread_Change_priority(
     395  Thread_Control                *the_thread,
     396  Priority_Control               new_priority,
     397  void                          *arg,
     398  Thread_Change_priority_filter  filter,
     399  bool                           prepend_it
     400);
     401
     402/**
     403 * @brief Raises the priority of a thread.
     404 *
     405 * It changes the current priority of the thread to the new priority if the new
     406 * priority is higher than the current priority.  In this case the thread is
     407 * appended to its new priority group in its scheduler instance.
     408 *
     409 * @param[in] the_thread The thread.
     410 * @param[in] new_priority The new priority of the thread.
     411 *
     412 * @see _Thread_Change_priority().
     413 */
     414void _Thread_Raise_priority(
     415  Thread_Control   *the_thread,
     416  Priority_Control  new_priority
     417);
     418
     419/**
     420 * @brief Sets the current to the real priority of a thread.
     421 *
     422 * Sets the priority restore hint to false.
     423 */
     424void _Thread_Restore_priority( Thread_Control *the_thread );
     425
     426/**
     427 * @brief Sets the priority of a thread.
     428 *
     429 * It sets the real priority of the thread.  In addition it changes the current
     430 * priority of the thread if the new priority is higher than the current
     431 * priority or the thread owns no resources.
     432 *
     433 * @param[in] the_thread The thread.
     434 * @param[in] new_priority The new priority of the thread.
     435 * @param[out] old_priority The old real priority of the thread.  This pointer
     436 * must not be @c NULL.
     437 * @param[in] prepend_it In case this is true, then the thread is prepended to
     438 * its priority group in its scheduler instance, otherwise it is appended.
     439 *
     440 * @see _Thread_Change_priority().
     441 */
     442void _Thread_Set_priority(
    347443  Thread_Control   *the_thread,
    348444  Priority_Control  new_priority,
     445  Priority_Control *old_priority,
    349446  bool              prepend_it
    350 );
    351 
    352 /**
    353  *  @brief Set thread priority.
    354  *
    355  *  This routine updates the priority related fields in the_thread
    356  *  control block to indicate the current priority is now new_priority.
    357  */
    358 void _Thread_Set_priority(
    359   Thread_Control   *the_thread,
    360   Priority_Control  new_priority
    361447);
    362448
  • cpukit/score/src/coremutex.c

    r4438ac25 r900d337f  
    5151      Per_CPU_Control *cpu_self;
    5252
    53       /*
    54        * The mutex initialization is only protected by the allocator lock in
    55        * general.  Disable thread dispatching before the priority check to
    56        * prevent interference with priority inheritance.
    57        */
     53      /* The mutex initialization is only protected by the allocator lock */
    5854      cpu_self = _Thread_Dispatch_disable();
    5955
     56      /*
     57       * The test to check for a ceiling violation is a bit arbitrary.  In case
     58       * this thread is the owner of a priority inheritance mutex, then it may
     59       * get a higher priority later or anytime on SMP configurations.
     60       */
    6061      if ( is_priority_ceiling && executing->current_priority < ceiling ) {
    61         _Thread_Enable_dispatch();
     62        /*
     63         * There is no need to undo the previous work since this error aborts
     64         * the object creation.
     65         */
     66        _Thread_Dispatch_enable( cpu_self );
    6267        return CORE_MUTEX_STATUS_CEILING_VIOLATED;
    6368      }
     
    7277
    7378      if ( is_priority_ceiling ) {
    74         _Thread_Change_priority( executing, ceiling, false );
     79        _Thread_Raise_priority( executing, ceiling );
    7580      }
    7681
  • cpukit/score/src/coremutexseize.c

    r4438ac25 r900d337f  
    2222#include <rtems/score/isr.h>
    2323#include <rtems/score/coremuteximpl.h>
    24 #include <rtems/score/schedulerimpl.h>
    2524#include <rtems/score/statesimpl.h>
    2625#include <rtems/score/thread.h>
     
    7776#endif
    7877
    79     _Scheduler_Change_priority_if_higher(
    80       _Scheduler_Get( holder ),
    81       holder,
    82       executing->current_priority,
    83       false
    84     );
     78    _Thread_Raise_priority( holder, executing->current_priority );
    8579
    8680#if !defined(RTEMS_SMP)
  • cpukit/score/src/coremutexsurrender.c

    r4438ac25 r900d337f  
    208208          _CORE_mutex_Push_priority( the_mutex, the_thread );
    209209          the_thread->resource_count++;
    210           if (the_mutex->Attributes.priority_ceiling <
    211               the_thread->current_priority){
    212               _Thread_Change_priority(
    213                 the_thread,
    214                 the_mutex->Attributes.priority_ceiling,
    215                 false
    216               );
    217           }
     210          _Thread_Raise_priority(
     211            the_thread,
     212            the_mutex->Attributes.priority_ceiling
     213          );
    218214          break;
    219215      }
     
    247243   *  mutex (i.e. resource) this task has.
    248244   */
    249   if ( !_Thread_Owns_resources( holder ) &&
    250        holder->real_priority != holder->current_priority ) {
    251     Per_CPU_Control *cpu_self;
    252 
    253     cpu_self = _Thread_Dispatch_disable();
    254     _Thread_Change_priority( holder, holder->real_priority, true );
    255     _Thread_Dispatch_enable( cpu_self );
     245  if ( !_Thread_Owns_resources( holder ) ) {
     246    /*
     247     * Ensure that the holder resource count is visible to all other processors
     248     * and that we read the latest priority restore hint.
     249     */
     250    _Atomic_Fence( ATOMIC_ORDER_ACQ_REL );
     251
     252    if ( holder->priority_restore_hint ) {
     253      Per_CPU_Control *cpu_self;
     254
     255      cpu_self = _Thread_Dispatch_disable();
     256      _Thread_Restore_priority( holder );
     257      _Thread_Dispatch_enable( cpu_self );
     258    }
    256259  }
    257260
  • cpukit/score/src/schedulercbs.c

    r4438ac25 r900d337f  
    2828{
    2929  Priority_Control          new_priority;
     30  Priority_Control          unused;
    3031  Scheduler_CBS_Node       *node;
    3132  Scheduler_CBS_Server_id   server_id;
     
    3334  /* Put violating task to background until the end of period. */
    3435  new_priority = the_thread->Start.initial_priority;
    35   if ( the_thread->real_priority != new_priority )
    36     the_thread->real_priority = new_priority;
    37   if ( the_thread->current_priority != new_priority )
    38     _Thread_Change_priority(the_thread, new_priority, true);
     36  _Thread_Set_priority( the_thread, new_priority, &unused, true );
    3937
    4038  /* Invoke callback function if any. */
  • cpukit/score/src/schedulercbsreleasejob.c

    r4438ac25 r900d337f  
    3333  Scheduler_CBS_Server *serv_info = node->cbs_server;
    3434  Priority_Control      new_priority;
     35  Priority_Control      unused;
    3536
    3637  if (deadline) {
     
    5253    the_thread->cpu_time_budget = serv_info->parameters.budget;
    5354
    54   the_thread->real_priority = new_priority;
    55   _Thread_Change_priority(the_thread, new_priority, true);
     55  _Thread_Set_priority( the_thread, new_priority, &unused, true );
    5656}
  • cpukit/score/src/scheduleredfreleasejob.c

    r4438ac25 r900d337f  
    3030{
    3131  Priority_Control new_priority;
     32  Priority_Control unused;
    3233
    3334  (void) scheduler;
     
    4344  }
    4445
    45   the_thread->real_priority = new_priority;
    46   _Thread_Change_priority(the_thread, new_priority, true);
     46  _Thread_Set_priority( the_thread, new_priority, &unused, true );
    4747}
  • cpukit/score/src/thread.c

    r4438ac25 r900d337f  
    3333THREAD_OFFSET_ASSERT( real_priority );
    3434THREAD_OFFSET_ASSERT( priority_generation );
     35THREAD_OFFSET_ASSERT( priority_restore_hint );
    3536THREAD_OFFSET_ASSERT( resource_count );
    3637THREAD_OFFSET_ASSERT( Wait );
  • cpukit/score/src/threadchangepriority.c

    r4438ac25 r900d337f  
    2222#include <rtems/score/threadimpl.h>
    2323#include <rtems/score/schedulerimpl.h>
    24 #include <rtems/score/threadqimpl.h>
    2524
    2625void _Thread_Change_priority(
    27   Thread_Control   *the_thread,
    28   Priority_Control  new_priority,
    29   bool              prepend_it
     26  Thread_Control                *the_thread,
     27  Priority_Control               new_priority,
     28  void                          *arg,
     29  Thread_Change_priority_filter  filter,
     30  bool                           prepend_it
    3031)
    3132{
     
    3637
    3738  /*
     39   * For simplicity set the priority restore hint unconditionally since this is
     40   * an average case optimization.  Otherwise complicated atomic operations
     41   * would be necessary.  Synchronize with a potential read of the resource
     42   * count in the filter function.  See also _CORE_mutex_Surrender(),
     43   * _Thread_Set_priority_filter() and _Thread_Restore_priority_filter().
     44   */
     45  the_thread->priority_restore_hint = true;
     46  _Atomic_Fence( ATOMIC_ORDER_ACQ_REL );
     47
     48  /*
    3849   *  Do not bother recomputing all the priority related information if
    3950   *  we are not REALLY changing priority.
    4051   */
    41   if ( the_thread->current_priority != new_priority ) {
     52  if ( ( *filter )( the_thread, &new_priority, arg ) ) {
    4253    uint32_t my_generation;
    4354
     
    7384  }
    7485}
     86
     87static bool _Thread_Raise_priority_filter(
     88  Thread_Control   *the_thread,
     89  Priority_Control *new_priority,
     90  void             *arg
     91)
     92{
     93  return _Thread_Priority_less_than(
     94    the_thread->current_priority,
     95    *new_priority
     96  );
     97}
     98
     99void _Thread_Raise_priority(
     100  Thread_Control   *the_thread,
     101  Priority_Control  new_priority
     102)
     103{
     104  _Thread_Change_priority(
     105    the_thread,
     106    new_priority,
     107    NULL,
     108    _Thread_Raise_priority_filter,
     109    false
     110  );
     111}
     112
     113static bool _Thread_Restore_priority_filter(
     114  Thread_Control   *the_thread,
     115  Priority_Control *new_priority,
     116  void             *arg
     117)
     118{
     119  *new_priority = the_thread->real_priority;
     120
     121  the_thread->priority_restore_hint = false;
     122
     123  return *new_priority != the_thread->current_priority;
     124}
     125
     126void _Thread_Restore_priority( Thread_Control *the_thread )
     127{
     128  _Thread_Change_priority(
     129    the_thread,
     130    0,
     131    NULL,
     132    _Thread_Restore_priority_filter,
     133    true
     134  );
     135}
  • cpukit/score/src/threadinitialize.c

    r4438ac25 r900d337f  
    202202  the_thread->Wait.operations         = &_Thread_queue_Operations_default;
    203203  the_thread->resource_count          = 0;
     204  the_thread->current_priority        = priority;
    204205  the_thread->real_priority           = priority;
    205206  the_thread->priority_generation     = 0;
     
    211212  scheduler_node_initialized = true;
    212213
    213   _Thread_Set_priority( the_thread, priority );
     214  _Scheduler_Update_priority( the_thread, priority );
    214215
    215216  /*
  • cpukit/score/src/threadrestart.c

    r4438ac25 r900d337f  
    4343};
    4444
     45static bool _Thread_Raise_real_priority_filter(
     46  Thread_Control   *the_thread,
     47  Priority_Control *new_priority_ptr,
     48  void             *arg
     49)
     50{
     51  Priority_Control real_priority;
     52  Priority_Control new_priority;
     53  Priority_Control current_priority;
     54
     55  real_priority = the_thread->real_priority;
     56  new_priority = *new_priority_ptr;
     57  current_priority = the_thread->current_priority;
     58
     59  new_priority = _Thread_Priority_highest( real_priority, new_priority );
     60  *new_priority_ptr = new_priority;
     61
     62  the_thread->real_priority = new_priority;
     63
     64  return _Thread_Priority_less_than( current_priority, new_priority );
     65}
     66
    4567static void _Thread_Make_zombie( Thread_Control *the_thread )
    4668{
     
    232254  the_thread->budget_algorithm = the_thread->Start.budget_algorithm;
    233255  the_thread->budget_callout   = the_thread->Start.budget_callout;
    234   the_thread->real_priority    = priority;
    235256
    236257  _Thread_Set_state( the_thread, STATES_RESTARTING );
    237258  _Thread_queue_Extract_with_proxy( the_thread );
    238259  _Watchdog_Remove_ticks( &the_thread->Timer );
    239   _Scheduler_Set_priority_if_higher( scheduler, the_thread, priority );
     260  _Thread_Change_priority(
     261    the_thread,
     262    priority,
     263    NULL,
     264    _Thread_Raise_real_priority_filter,
     265    false
     266  );
    240267  _Thread_Add_post_switch_action( the_thread, &the_thread->Life.Action );
    241268  _Thread_Ready( the_thread );
     
    261288  scheduler = _Scheduler_Get( the_thread );
    262289  if ( the_thread == executing ) {
    263     executing->real_priority = priority;
    264 
    265     _Scheduler_Set_priority_if_higher( scheduler, the_thread, priority );
     290    Priority_Control unused;
     291
     292    _Thread_Set_priority( the_thread, priority, &unused, true );
    266293    _Thread_Start_life_change_for_executing( executing );
    267294  } else if ( previous_life_state == THREAD_LIFE_NORMAL ) {
     
    271298
    272299    if ( _Thread_Is_life_terminating( additional_life_state ) ) {
    273       the_thread->real_priority = _Scheduler_Highest_priority_of_two(
    274         scheduler,
    275         the_thread->real_priority,
    276         priority
    277       );
    278 
    279       _Scheduler_Change_priority_if_higher(
    280         scheduler,
     300      _Thread_Change_priority(
    281301        the_thread,
    282302        priority,
     303        NULL,
     304        _Thread_Raise_real_priority_filter,
    283305        false
    284306      );
  • cpukit/score/src/threadsetpriority.c

    r4438ac25 r900d337f  
    2020
    2121#include <rtems/score/threadimpl.h>
    22 #include <rtems/score/schedulerimpl.h>
     22
     23static bool _Thread_Set_priority_filter(
     24  Thread_Control   *the_thread,
     25  Priority_Control *new_priority_ptr,
     26  void             *arg
     27)
     28{
     29  Priority_Control  current_priority;
     30  Priority_Control  new_priority;
     31  Priority_Control *old_priority_ptr;
     32
     33  current_priority = the_thread->current_priority;
     34  new_priority = *new_priority_ptr;
     35
     36  old_priority_ptr = arg;
     37  *old_priority_ptr = current_priority;
     38
     39  the_thread->real_priority = new_priority;
     40
     41  return _Thread_Priority_less_than( current_priority, new_priority )
     42    || !_Thread_Owns_resources( the_thread );
     43}
    2344
    2445void _Thread_Set_priority(
    2546  Thread_Control   *the_thread,
    26   Priority_Control  new_priority
     47  Priority_Control  new_priority,
     48  Priority_Control *old_priority,
     49  bool              prepend_it
    2750)
    2851{
    29   the_thread->current_priority = new_priority;
    30 
    31   _Scheduler_Update_priority( the_thread, new_priority );
     52  _Thread_Change_priority(
     53    the_thread,
     54    new_priority,
     55    old_priority,
     56    _Thread_Set_priority_filter,
     57    prepend_it
     58  );
    3259}
  • testsuites/smptests/smpscheduler03/init.c

    r4438ac25 r900d337f  
    4141static test_context test_instance;
    4242
     43static bool change_priority_filter(
     44  Thread_Control   *thread,
     45  Priority_Control *new_priority,
     46  void             *arg
     47)
     48{
     49  return thread->current_priority != *new_priority;
     50}
     51
     52static void change_priority(
     53  Thread_Control   *thread,
     54  Priority_Control  new_priority,
     55  bool              prepend_it
     56)
     57{
     58  _Thread_Change_priority(
     59    thread,
     60    new_priority,
     61    NULL,
     62    change_priority_filter,
     63    prepend_it
     64  );
     65}
     66
    4367static void barrier_wait(test_context *ctx)
    4468{
     
    98122  switch (start_state) {
    99123    case SCHEDULER_SMP_NODE_SCHEDULED:
    100       _Thread_Change_priority(executing, 1, true);
     124      change_priority(executing, 1, true);
    101125      break;
    102126    case SCHEDULER_SMP_NODE_READY:
    103       _Thread_Change_priority(executing, 4, true);
     127      change_priority(executing, 4, true);
    104128      break;
    105129    default:
     
    109133  rtems_test_assert(node->state == start_state);
    110134
    111   _Thread_Change_priority(executing, prio, prepend_it);
     135  change_priority(executing, prio, prepend_it);
    112136  rtems_test_assert(node->state == new_state);
    113137}
     
    154178  }
    155179
    156   _Thread_Change_priority(executing, 1, true);
     180  change_priority(executing, 1, true);
    157181  rtems_test_assert(node->state == SCHEDULER_SMP_NODE_SCHEDULED);
    158182
     
    200224  switch (start_state) {
    201225    case SCHEDULER_SMP_NODE_SCHEDULED:
    202       _Thread_Change_priority(executing, 1, true);
     226      change_priority(executing, 1, true);
    203227      break;
    204228    case SCHEDULER_SMP_NODE_READY:
    205       _Thread_Change_priority(executing, 4, true);
     229      change_priority(executing, 4, true);
    206230      break;
    207231    default:
     
    267291  }
    268292
    269   _Thread_Change_priority(executing, 1, true);
     293  change_priority(executing, 1, true);
    270294  rtems_test_assert(executing_node->state == SCHEDULER_SMP_NODE_SCHEDULED);
    271295
     
    299323  Thread_Control *needs_help;
    300324
    301   _Thread_Change_priority(executing, 4, false);
    302   _Thread_Change_priority(other, 4, false);
     325  change_priority(executing, 4, false);
     326  change_priority(other, 4, false);
    303327
    304328  switch (start_state) {
     
    306330      switch (new_state) {
    307331        case SCHEDULER_SMP_NODE_SCHEDULED:
    308           _Thread_Change_priority(executing, 2, false);
    309           _Thread_Change_priority(other, 3, false);
     332          change_priority(executing, 2, false);
     333          change_priority(other, 3, false);
    310334          break;
    311335        case SCHEDULER_SMP_NODE_READY:
    312           _Thread_Change_priority(executing, 2, false);
    313           _Thread_Change_priority(other, 2, false);
     336          change_priority(executing, 2, false);
     337          change_priority(other, 2, false);
    314338          break;
    315339        default:
     
    324348          break;
    325349        case SCHEDULER_SMP_NODE_READY:
    326           _Thread_Change_priority(executing, 3, false);
    327           _Thread_Change_priority(other, 2, false);
     350          change_priority(executing, 3, false);
     351          change_priority(other, 2, false);
    328352          break;
    329353        default:
     
    394418  }
    395419
    396   _Thread_Change_priority(executing, 1, true);
     420  change_priority(executing, 1, true);
    397421  rtems_test_assert(executing_node->state == SCHEDULER_SMP_NODE_SCHEDULED);
    398422
     
    437461  switch (new_state) {
    438462    case SCHEDULER_SMP_NODE_SCHEDULED:
    439       _Thread_Change_priority(executing, 2, false);
     463      change_priority(executing, 2, false);
    440464      rtems_test_assert(executing_node->state == SCHEDULER_SMP_NODE_SCHEDULED);
    441465      break;
    442466    case SCHEDULER_SMP_NODE_READY:
    443       _Thread_Change_priority(executing, 4, false);
     467      change_priority(executing, 4, false);
    444468      rtems_test_assert(executing_node->state == SCHEDULER_SMP_NODE_READY);
    445469      break;
     
    495519  }
    496520
    497   _Thread_Change_priority(executing, 1, true);
     521  change_priority(executing, 1, true);
    498522  rtems_test_assert(executing_node->state == SCHEDULER_SMP_NODE_SCHEDULED);
    499523
Note: See TracChangeset for help on using the changeset viewer.