Changeset 300f6a48 in rtems


Ignore:
Timestamp:
Jun 22, 2016, 3:09:23 PM (3 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
master
Children:
5d6b211
Parents:
8c83cbc
git-author:
Sebastian Huber <sebastian.huber@…> (06/22/16 15:09:23)
git-committer:
Sebastian Huber <sebastian.huber@…> (09/21/16 06:59:26)
Message:

score: Rework thread priority management

Add priority nodes which contribute to the overall thread priority.

The actual priority of a thread is now an aggregation of priority nodes.
The thread priority aggregation for the home scheduler instance of a
thread consists of at least one priority node, which is normally the
real priority of the thread. The locking protocols (e.g. priority
ceiling and priority inheritance), rate-monotonic period objects and the
POSIX sporadic server add, change and remove priority nodes.

A thread changes its priority now immediately, e.g. priority changes are
not deferred until the thread releases its last resource.

Replace the _Thread_Change_priority() function with

  • _Thread_Priority_perform_actions(),
  • _Thread_Priority_add(),
  • _Thread_Priority_remove(),
  • _Thread_Priority_change(), and
  • _Thread_Priority_update().

Update #2412.
Update #2556.

Files:
1 added
1 deleted
66 edited

Legend:

Unmodified
Added
Removed
  • cpukit/libmisc/capture/capture.h

    r8c83cbc r300f6a48  
    889889rtems_capture_task_real_priority (rtems_tcb* tcb)
    890890{
    891   return tcb->real_priority;
     891  return tcb->Real_priority.priority;
    892892}
    893893
  • cpukit/libmisc/cpuuse/cpuusagetop.c

    r8c83cbc r300f6a48  
    262262            continue;
    263263        case RTEMS_TOP_SORT_REAL_PRI:
    264           if (thread->real_priority > data->tasks[j]->real_priority)
     264          if (thread->Real_priority.priority > data->tasks[j]->Real_priority.priority)
    265265            continue;
    266266        case RTEMS_TOP_SORT_CURRENT_PRI:
     
    479479
    480480      rtems_printf(data->printer,
    481                    " 0x%08" PRIx32 " | %-19s |  %3" PRId32 " |  %3" PRId32 "   | ",
     481                   " 0x%08" PRIx32 " | %-19s |  %3" PRId64 " |  %3" PRId64 "   | ",
    482482                   thread->Object.id,
    483483                   name,
    484                    thread->real_priority,
     484                   thread->Real_priority.priority,
    485485                   _Thread_Get_priority(thread));
    486486
  • cpukit/posix/include/rtems/posix/pthreadimpl.h

    r8c83cbc r300f6a48  
    6868  );
    6969}
     70
     71void _POSIX_Threads_Sporadic_timer( Watchdog_Control *watchdog );
    7072
    7173/**
  • cpukit/posix/include/rtems/posix/threadsup.h

    r8c83cbc r300f6a48  
    6161     * policy.
    6262     */
    63     Priority_Control low_priority;
    64 
    65     /**
    66      * @brief The high priority when using the sporadic server scheduling
    67      * policy.
    68      */
    69     Priority_Control high_priority;
     63    Priority_Node Low_priority;
    7064  } Sporadic;
    7165
  • cpukit/posix/src/killinfo.c

    r8c83cbc r300f6a48  
    154154      Scheduler_Node *scheduler_node;
    155155
    156       scheduler_node = SCHEDULER_NODE_OF_WAIT_CHAIN_NODE( the_node );
     156      scheduler_node = SCHEDULER_NODE_OF_WAIT_PRIORITY_NODE( the_node );
    157157      the_thread = _Scheduler_Node_get_owner( scheduler_node );
    158158      api = the_thread->API_Extensions[ THREAD_API_POSIX ];
  • cpukit/posix/src/mutexsetprioceiling.c

    r8c83cbc r300f6a48  
    6565    new_priority = _POSIX_Priority_To_core( scheduler, prioceiling, &valid );
    6666    if ( valid ) {
    67       _CORE_ceiling_mutex_Set_priority( &the_mutex->Mutex, new_priority );
     67      Thread_queue_Context  queue_context;
     68      Per_CPU_Control      *cpu_self;
     69
     70      _Thread_queue_Context_clear_priority_updates( &queue_context );
     71      _CORE_ceiling_mutex_Set_priority(
     72        &the_mutex->Mutex,
     73        new_priority,
     74        &queue_context
     75      );
     76      cpu_self = _Thread_Dispatch_disable();
     77      _Thread_Priority_update( &queue_context );
     78      _Thread_Dispatch_enable( cpu_self );
    6879      error = 0;
    6980    } else {
  • cpukit/posix/src/pthread.c

    r8c83cbc r300f6a48  
    8383};
    8484
    85 static bool _POSIX_Threads_Sporadic_timer_filter(
    86   Thread_Control   *the_thread,
    87   Priority_Control *new_priority_p,
    88   void             *arg
    89 )
    90 {
    91   POSIX_API_Control *api;
    92   Priority_Control   current_priority;
    93   Priority_Control   new_priority;
    94 
    95   api = arg;
    96 
    97   new_priority = api->Sporadic.high_priority;
    98   *new_priority_p = new_priority;
    99 
    100   current_priority = _Thread_Get_priority( the_thread );
    101   the_thread->real_priority = new_priority;
     85void _POSIX_Threads_Sporadic_timer( Watchdog_Control *watchdog )
     86{
     87  POSIX_API_Control    *api;
     88  Thread_Control       *the_thread;
     89  Thread_queue_Context  queue_context;
     90
     91  api = RTEMS_CONTAINER_OF( watchdog, POSIX_API_Control, Sporadic.Timer );
     92  the_thread = api->thread;
     93
     94  _Thread_queue_Context_clear_priority_updates( &queue_context );
     95  _Thread_Wait_acquire( the_thread, &queue_context );
     96
     97  if ( _Priority_Node_is_active( &api->Sporadic.Low_priority ) ) {
     98    _Thread_Priority_add(
     99      the_thread,
     100      &the_thread->Real_priority,
     101      &queue_context
     102    );
     103    _Thread_Priority_remove(
     104      the_thread,
     105      &api->Sporadic.Low_priority,
     106      &queue_context
     107    );
     108    _Priority_Node_set_inactive( &api->Sporadic.Low_priority );
     109  }
    102110
    103111  _Watchdog_Per_CPU_remove_relative( &api->Sporadic.Timer );
    104112  _POSIX_Threads_Sporadic_timer_insert( the_thread, api );
    105113
    106   return _Thread_Priority_less_than( current_priority, new_priority )
    107     || !_Thread_Owns_resources( the_thread );
    108 }
    109 
    110 static void _POSIX_Threads_Sporadic_timer( Watchdog_Control *watchdog )
    111 {
    112   POSIX_API_Control *api;
    113   Thread_Control    *the_thread;
    114 
    115   api = RTEMS_CONTAINER_OF( watchdog, POSIX_API_Control, Sporadic.Timer );
    116   the_thread = api->thread;
    117 
    118   _Thread_Change_priority(
    119     the_thread,
    120     0,
    121     api,
    122     _POSIX_Threads_Sporadic_timer_filter,
    123     true
    124   );
    125 }
    126 
    127 static bool _POSIX_Threads_Sporadic_budget_callout_filter(
    128   Thread_Control   *the_thread,
    129   Priority_Control *new_priority_p,
    130   void             *arg
    131 )
    132 {
    133   POSIX_API_Control *api;
    134   Priority_Control   current_priority;
    135   Priority_Control   new_priority;
     114  _Thread_Wait_release( the_thread, &queue_context );
     115  _Thread_Priority_update( &queue_context );
     116}
     117
     118void _POSIX_Threads_Sporadic_budget_callout( Thread_Control *the_thread )
     119{
     120  POSIX_API_Control    *api;
     121  Thread_queue_Context  queue_context;
    136122
    137123  api = the_thread->API_Extensions[ THREAD_API_POSIX ];
     124
     125  _Thread_queue_Context_clear_priority_updates( &queue_context );
     126  _Thread_Wait_acquire( the_thread, &queue_context );
    138127
    139128  /*
     
    143132  the_thread->cpu_time_budget = UINT32_MAX;
    144133
    145   new_priority = api->Sporadic.low_priority;
    146   *new_priority_p = new_priority;
    147 
    148   current_priority = _Thread_Get_priority( the_thread );
    149   the_thread->real_priority = new_priority;
    150 
    151   return _Thread_Priority_less_than( current_priority, new_priority )
    152     || !_Thread_Owns_resources( the_thread );
    153 }
    154 
    155 void _POSIX_Threads_Sporadic_budget_callout( Thread_Control *the_thread )
    156 {
    157   _Thread_Change_priority(
    158     the_thread,
    159     0,
    160     NULL,
    161     _POSIX_Threads_Sporadic_budget_callout_filter,
    162     true
    163   );
     134  if ( !_Priority_Node_is_active( &api->Sporadic.Low_priority ) ) {
     135    _Thread_Priority_add(
     136      the_thread,
     137      &api->Sporadic.Low_priority,
     138      &queue_context
     139    );
     140    _Thread_Priority_remove(
     141      the_thread,
     142      &the_thread->Real_priority,
     143      &queue_context
     144    );
     145  }
     146
     147  _Thread_Wait_release( the_thread, &queue_context );
     148  _Thread_Priority_update( &queue_context );
    164149}
    165150
  • cpukit/posix/src/pthreadcreate.c

    r8c83cbc r300f6a48  
    6262  };
    6363  const pthread_attr_t               *the_attr;
     64  int                                 normal_prio;
    6465  int                                 low_prio;
    65   int                                 high_prio;
    6666  bool                                valid;
     67  Priority_Control                    core_normal_prio;
    6768  Priority_Control                    core_low_prio;
    68   Priority_Control                    core_high_prio;
    6969  Thread_CPU_budget_algorithms        budget_algorithm;
    7070  Thread_CPU_budget_algorithm_callout budget_callout;
     
    150150  }
    151151
     152  normal_prio = schedparam.sched_priority;
     153
     154  scheduler = _Scheduler_Get_own( executing );
     155
     156  core_normal_prio = _POSIX_Priority_To_core( scheduler, normal_prio, &valid );
     157  if ( !valid ) {
     158    return EINVAL;
     159  }
     160
    152161  if ( schedpolicy == SCHED_SPORADIC ) {
    153162    low_prio = schedparam.sched_ss_low_priority;
    154     high_prio = schedparam.sched_priority;
    155163  } else {
    156     low_prio = schedparam.sched_priority;
    157     high_prio = low_prio;
    158   }
    159 
    160   scheduler = _Scheduler_Get_own( executing );
     164    low_prio = normal_prio;
     165  }
    161166
    162167  core_low_prio = _POSIX_Priority_To_core( scheduler, low_prio, &valid );
    163   if ( !valid ) {
    164     return EINVAL;
    165   }
    166 
    167   core_high_prio = _POSIX_Priority_To_core( scheduler, high_prio, &valid );
    168168  if ( !valid ) {
    169169    return EINVAL;
     
    206206    _POSIX_Threads_Ensure_minimum_stack(the_attr->stacksize),
    207207    is_fp,
    208     core_high_prio,
     208    core_normal_prio,
    209209    true,                 /* preemptible */
    210210    budget_algorithm,
     
    246246
    247247  _POSIX_Threads_Copy_attributes( &api->Attributes, the_attr );
    248   api->Sporadic.low_priority = core_low_prio;
    249   api->Sporadic.high_priority = core_high_prio;
     248  _Priority_Node_initialize( &api->Sporadic.Low_priority, core_low_prio );
     249  _Priority_Node_set_inactive( &api->Sporadic.Low_priority );
    250250
    251251  if ( schedpolicy == SCHED_SPORADIC ) {
    252     _ISR_lock_ISR_disable( &lock_context );
    253     _POSIX_Threads_Sporadic_timer_insert( the_thread, api );
    254     _ISR_lock_ISR_enable( &lock_context );
     252    _POSIX_Threads_Sporadic_timer( &api->Sporadic.Timer );
    255253  }
    256254
  • cpukit/posix/src/pthreadgetschedparam.c

    r8c83cbc r300f6a48  
    6060
    6161  scheduler = _Scheduler_Get_own( the_thread );
    62   priority = the_thread->real_priority;
     62  priority = the_thread->Real_priority.priority;
    6363
    6464  _Thread_Wait_release( the_thread, &queue_context );
  • cpukit/posix/src/pthreadsetschedparam.c

    r8c83cbc r300f6a48  
    3131#include <rtems/score/schedulerimpl.h>
    3232
    33 typedef struct {
    34   int                                  policy;
    35   const struct sched_param            *param;
    36   Thread_CPU_budget_algorithms         budget_algorithm;
    37   Thread_CPU_budget_algorithm_callout  budget_callout;
    38   int                                  error;
    39 } POSIX_Set_sched_param_context;
    40 
    41 static bool _POSIX_Set_sched_param_filter(
    42   Thread_Control   *the_thread,
    43   Priority_Control *new_priority_p,
    44   void             *arg
     33static int _POSIX_Set_sched_param(
     34  Thread_Control                       *the_thread,
     35  int                                   policy,
     36  struct sched_param                   *param,
     37  Thread_CPU_budget_algorithms          budget_algorithm,
     38  Thread_CPU_budget_algorithm_callout   budget_callout,
     39  Thread_queue_Context                 *queue_context
    4540)
    4641{
    47   POSIX_Set_sched_param_context *context;
    48   const struct sched_param      *param;
    49   const Scheduler_Control       *scheduler;
    50   POSIX_API_Control             *api;
    51   int                            low_prio;
    52   int                            high_prio;
    53   bool                           valid;
    54   Priority_Control               core_low_prio;
    55   Priority_Control               core_high_prio;
    56   Priority_Control               current_priority;
     42  const Scheduler_Control *scheduler;
     43  POSIX_API_Control       *api;
     44  int                      low_prio;
     45  int                      high_prio;
     46  bool                     valid;
     47  Priority_Control         core_normal_prio;
     48  Priority_Control         core_low_prio;
    5749
    58   context = arg;
    59   param = context->param;
    60   scheduler = _Scheduler_Get_own( the_thread );
    61 
    62   if ( context->policy == SCHED_SPORADIC ) {
     50  if ( policy == SCHED_SPORADIC ) {
    6351    low_prio = param->sched_ss_low_priority;
    6452    high_prio = param->sched_priority;
     
    6856  }
    6957
    70   core_low_prio = _POSIX_Priority_To_core( scheduler, low_prio, &valid );
     58  scheduler = _Scheduler_Get_own( the_thread );
     59
     60  core_normal_prio = _POSIX_Priority_To_core( scheduler, low_prio, &valid );
    7161  if ( !valid ) {
    72     context->error = EINVAL;
    73     return false;
     62    return EINVAL;
    7463  }
    7564
    76   core_high_prio = _POSIX_Priority_To_core( scheduler, high_prio, &valid );
     65  core_low_prio = _POSIX_Priority_To_core( scheduler, high_prio, &valid );
    7766  if ( !valid ) {
    78     context->error = EINVAL;
    79     return false;
     67    return EINVAL;
    8068  }
    81 
    82   *new_priority_p = core_high_prio;
    83 
    84   current_priority = _Thread_Get_priority( the_thread );
    85   the_thread->real_priority = core_high_prio;
    8669
    8770  api = the_thread->API_Extensions[ THREAD_API_POSIX ];
     
    8972  _Watchdog_Per_CPU_remove_relative( &api->Sporadic.Timer );
    9073
    91   api->Attributes.schedpolicy = context->policy;
     74  _Priority_Node_set_priority( &the_thread->Real_priority, core_normal_prio );
     75
     76  if ( _Priority_Node_is_active( &api->Sporadic.Low_priority ) ) {
     77    _Thread_Priority_add(
     78      the_thread,
     79      &the_thread->Real_priority,
     80      queue_context
     81    );
     82    _Thread_Priority_remove(
     83      the_thread,
     84      &api->Sporadic.Low_priority,
     85      queue_context
     86    );
     87    _Priority_Node_set_inactive( &api->Sporadic.Low_priority );
     88  } else {
     89    _Thread_Priority_changed(
     90      the_thread,
     91      &the_thread->Real_priority,
     92      false,
     93      queue_context
     94    );
     95  }
     96
     97  api->Attributes.schedpolicy = policy;
    9298  api->Attributes.schedparam  = *param;
    93   api->Sporadic.low_priority  = core_low_prio;
    94   api->Sporadic.high_priority = core_high_prio;
    9599
    96   the_thread->budget_algorithm = context->budget_algorithm;
    97   the_thread->budget_callout   = context->budget_callout;
     100  the_thread->budget_algorithm = budget_algorithm;
     101  the_thread->budget_callout   = budget_callout;
    98102
    99   if ( context->policy == SCHED_SPORADIC ) {
     103  if ( policy == SCHED_SPORADIC ) {
     104    _Priority_Node_set_priority( &api->Sporadic.Low_priority, core_low_prio );
    100105    _POSIX_Threads_Sporadic_timer_insert( the_thread, api );
    101106  } else {
     
    104109  }
    105110
    106   context->error = 0;
    107   return _Thread_Priority_less_than( current_priority, core_high_prio )
    108     || !_Thread_Owns_resources( the_thread );
     111  return 0;
    109112}
    110113
     
    115118)
    116119{
    117   Thread_Control                *the_thread;
    118   Per_CPU_Control               *cpu_self;
    119   POSIX_Set_sched_param_context  context;
    120   ISR_lock_Context               lock_context;
    121   int                            error;
     120  Thread_CPU_budget_algorithms         budget_algorithm;
     121  Thread_CPU_budget_algorithm_callout  budget_callout;
     122  Thread_Control                      *the_thread;
     123  Per_CPU_Control                     *cpu_self;
     124  Thread_queue_Context                 queue_context;
     125  int                                  error;
    122126
    123127  if ( param == NULL ) {
     
    128132    policy,
    129133    param,
    130     &context.budget_algorithm,
    131     &context.budget_callout
     134    &budget_algorithm,
     135    &budget_callout
    132136  );
    133137  if ( error != 0 ) {
     
    135139  }
    136140
    137   context.policy = policy;
    138   context.param = param;
    139 
    140   the_thread = _Thread_Get( thread, &lock_context );
     141  the_thread = _Thread_Get( thread, &queue_context.Lock_context.Lock_context );
    141142
    142143  if ( the_thread == NULL ) {
     
    144145  }
    145146
    146   cpu_self = _Thread_Dispatch_disable_critical( &lock_context );
    147   _ISR_lock_ISR_enable( &lock_context );
    148 
    149   _Thread_Change_priority(
     147  _Thread_queue_Context_clear_priority_updates( &queue_context );
     148  _Thread_Wait_acquire_critical( the_thread, &queue_context );
     149  error = _POSIX_Set_sched_param(
    150150    the_thread,
    151     0,
    152     &context,
    153     _POSIX_Set_sched_param_filter,
    154     false
     151    policy,
     152    param,
     153    budget_algorithm,
     154    budget_callout,
     155    &queue_context
    155156  );
    156 
     157  cpu_self = _Thread_Dispatch_disable_critical(
     158    &queue_context.Lock_context.Lock_context
     159  );
     160  _Thread_Wait_release( the_thread, &queue_context );
     161  _Thread_Priority_update( &queue_context );
    157162  _Thread_Dispatch_enable( cpu_self );
    158   return context.error;
     163  return error;
    159164}
  • cpukit/posix/src/pthreadsetschedprio.c

    r8c83cbc r300f6a48  
    1919#include <rtems/score/schedulerimpl.h>
    2020
    21 typedef struct {
    22   int prio;
    23   int error;
    24 } POSIX_Set_sched_prio_context;
    25 
    26 static bool _POSIX_Set_sched_prio_filter(
    27   Thread_Control   *the_thread,
    28   Priority_Control *new_priority_p,
    29   void             *arg
    30 )
    31 {
    32   POSIX_Set_sched_prio_context *context;
    33   int                           prio;
    34   const Scheduler_Control      *scheduler;
    35   POSIX_API_Control            *api;
    36   bool                          valid;
    37   Priority_Control              current_priority;
    38   Priority_Control              new_priority;
    39 
    40   context = arg;
    41   prio = context->prio;
    42   scheduler = _Scheduler_Get_own( the_thread );
    43 
    44   new_priority = _POSIX_Priority_To_core( scheduler, prio, &valid );
    45   if ( !valid ) {
    46     context->error = EINVAL;
    47     return false;
    48   }
    49 
    50   *new_priority_p = new_priority;
    51 
    52   current_priority = _Thread_Get_priority( the_thread );
    53   the_thread->real_priority = new_priority;
    54 
    55   api = the_thread->API_Extensions[ THREAD_API_POSIX ];
    56 
    57   api->Sporadic.high_priority = new_priority;
    58 
    59   if ( api->Sporadic.low_priority < new_priority ) {
    60     api->Sporadic.low_priority  = new_priority;
    61   }
    62 
    63   context->error = 0;
    64   return _Thread_Priority_less_than( current_priority, new_priority )
    65     || !_Thread_Owns_resources( the_thread );
    66 }
    67 
    6821int pthread_setschedprio( pthread_t thread, int prio )
    6922{
    70   Thread_Control               *the_thread;
    71   Per_CPU_Control              *cpu_self;
    72   POSIX_Set_sched_prio_context  context;
    73   ISR_lock_Context              lock_context;
     23  Thread_Control          *the_thread;
     24  Per_CPU_Control         *cpu_self;
     25  Thread_queue_Context     queue_context;
     26  const Scheduler_Control *scheduler;
     27  Priority_Control         new_priority;
     28  bool                     valid;
    7429
    75   context.prio = prio;
    76 
    77   the_thread = _Thread_Get( thread, &lock_context );
     30  the_thread = _Thread_Get( thread, &queue_context.Lock_context.Lock_context );
    7831
    7932  if ( the_thread == NULL ) {
     
    8134  }
    8235
    83   cpu_self = _Thread_Dispatch_disable_critical( &lock_context );
    84   _ISR_lock_ISR_enable( &lock_context );
     36  _Thread_queue_Context_clear_priority_updates( &queue_context );
     37  _Thread_Wait_acquire_critical( the_thread, &queue_context );
    8538
    86   _Thread_Change_priority(
     39  scheduler = _Scheduler_Get_own( the_thread );
     40
     41  new_priority = _POSIX_Priority_To_core( scheduler, prio, &valid );
     42  if ( !valid ) {
     43    _Thread_Wait_release( the_thread, &queue_context );
     44    return EINVAL;
     45  }
     46
     47  _Thread_Priority_change(
    8748    the_thread,
    88     0,
    89     &context,
    90     _POSIX_Set_sched_prio_filter,
    91     true
     49    &the_thread->Real_priority,
     50    new_priority,
     51    true,
     52    &queue_context
    9253  );
    9354
     55  cpu_self = _Thread_Dispatch_disable_critical(
     56    &queue_context.Lock_context.Lock_context
     57  );
     58  _Thread_Wait_release( the_thread, &queue_context );
     59
     60  _Thread_Priority_update( &queue_context );
     61
    9462  _Thread_Dispatch_enable( cpu_self );
    95   return context.error;
     63  return 0;
    9664}
  • cpukit/rtems/include/rtems/rtems/ratemon.h

    r8c83cbc r300f6a48  
    207207
    208208  /**
     209   * @brief A priority node for use by the scheduler job release and cancel
     210   * operations.
     211   */
     212  Priority_Node                           Priority;
     213
     214  /**
    209215   * This field contains the length of the next period to be
    210216   * executed.
  • cpukit/rtems/src/ratemoncancel.c

    r8c83cbc r300f6a48  
    2828)
    2929{
    30   Per_CPU_Control *cpu_self;
    31   Thread_Control  *update_priority;
     30  Per_CPU_Control      *cpu_self;
     31  Thread_queue_Context  queue_context;
    3232
    3333  _Rate_monotonic_Acquire_critical( the_period, lock_context );
     
    3535  _Watchdog_Per_CPU_remove_relative( &the_period->Timer );
    3636  the_period->state = RATE_MONOTONIC_INACTIVE;
    37   update_priority = _Scheduler_Cancel_job( the_period->owner );
     37  _Scheduler_Cancel_job(
     38    the_period->owner,
     39    &the_period->Priority,
     40    &queue_context
     41  );
    3842
    3943  cpu_self = _Thread_Dispatch_disable_critical( lock_context );
    4044  _Rate_monotonic_Release( the_period, lock_context );
    41   _Thread_Update_priority( update_priority );
     45  _Thread_Priority_update( &queue_context );
    4246  _Thread_Dispatch_enable( cpu_self );
    4347}
  • cpukit/rtems/src/ratemoncreate.c

    r8c83cbc r300f6a48  
    6464
    6565  _ISR_lock_Initialize( &the_period->Lock, "Rate Monotonic Period" );
     66  _Priority_Node_initialize( &the_period->Priority, 0 );
     67  _Priority_Node_set_inactive( &the_period->Priority );
    6668
    6769  the_period->owner = _Thread_Get_executing();
  • cpukit/rtems/src/ratemonperiod.c

    r8c83cbc r300f6a48  
    7171)
    7272{
    73   Per_CPU_Control *cpu_self;
    74   Thread_Control  *update_priority;
    75   uint64_t         deadline;
     73  Per_CPU_Control      *cpu_self;
     74  Thread_queue_Context  queue_context;
     75  uint64_t              deadline;
    7676
    7777  cpu_self = _Thread_Dispatch_disable_critical( lock_context );
     
    8282    next_length
    8383  );
    84   update_priority = _Scheduler_Release_job( owner, deadline );
     84  _Scheduler_Release_job(
     85    owner,
     86    &the_period->Priority,
     87    deadline,
     88    &queue_context
     89  );
    8590
    8691  _Rate_monotonic_Release( the_period, lock_context );
    87   _Thread_Update_priority( update_priority );
     92  _Thread_Priority_update( &queue_context );
    8893  _Thread_Dispatch_enable( cpu_self );
    8994}
  • cpukit/rtems/src/semsetpriority.c

    r8c83cbc r300f6a48  
    4343)
    4444{
    45   rtems_status_code    sc;
    46   bool                 valid;
    47   Priority_Control     core_priority;
    48   Priority_Control     old_priority;
     45  rtems_status_code  sc;
     46  bool               valid;
     47  Priority_Control   core_priority;
     48  Priority_Control   old_priority;
     49  Per_CPU_Control   *cpu_self;
    4950
    5051  core_priority = _RTEMS_Priority_To_core( scheduler, new_priority, &valid );
     
    5354  }
    5455
     56  _Thread_queue_Context_clear_priority_updates( queue_context );
    5557  _Thread_queue_Acquire_critical(
    5658    &the_semaphore->Core_control.Wait_queue,
     
    7274        _CORE_ceiling_mutex_Set_priority(
    7375          &the_semaphore->Core_control.Mutex,
    74           core_priority
     76          core_priority,
     77          queue_context
    7578        );
    7679      }
     
    107110  }
    108111
     112  cpu_self = _Thread_Dispatch_disable_critical(
     113    &queue_context->Lock_context.Lock_context
     114  );
    109115  _Thread_queue_Release(
    110116    &the_semaphore->Core_control.Wait_queue,
    111117    queue_context
    112118  );
     119  _Thread_Priority_update( queue_context );
     120  _Thread_Dispatch_enable( cpu_self );
    113121
    114122  *old_priority_p = _RTEMS_Priority_From_core( scheduler, old_priority );
  • cpukit/rtems/src/tasksetpriority.c

    r8c83cbc r300f6a48  
    2323#include <rtems/score/threadimpl.h>
    2424
    25 typedef struct {
    26   const Scheduler_Control *scheduler;
    27   rtems_task_priority      new_priority;
    28   Priority_Control         old_priority;
    29   rtems_status_code        status;
    30 } RTEMS_tasks_Set_priority_context;
    31 
    32 static bool _RTEMS_tasks_Set_priority_filter(
    33   Thread_Control   *the_thread,
    34   Priority_Control *new_priority_p,
    35   void             *arg
     25static rtems_status_code _RTEMS_tasks_Set_priority(
     26  Thread_Control          *the_thread,
     27  const Scheduler_Control *scheduler,
     28  Priority_Control         new_priority,
     29  Thread_queue_Context    *queue_context
    3630)
    3731{
    38   RTEMS_tasks_Set_priority_context *context;
    39   const Scheduler_Control          *scheduler;
    40   bool                              valid;
    41   Priority_Control                  current_priority;
    42   Priority_Control                  new_priority;
     32  Priority_Control core_new_priority;
     33  bool             valid;
     34  Per_CPU_Control *cpu_self;
    4335
    44   context = arg;
    45   scheduler = _Scheduler_Get_own( the_thread );
    46   current_priority = _Thread_Get_priority( the_thread );
    47 
    48   context->scheduler = scheduler;
    49   context->old_priority = current_priority;
    50 
    51   new_priority = _RTEMS_Priority_To_core(
     36  core_new_priority = _RTEMS_Priority_To_core(
    5237    scheduler,
    53     context->new_priority,
     38    new_priority,
    5439    &valid
    5540  );
    5641
    57   *new_priority_p = new_priority;
    58 
    5942  if ( !valid ) {
    60     context->status = RTEMS_INVALID_PRIORITY;
    61     return false;
     43    _Thread_Wait_release( the_thread, queue_context );
     44    return RTEMS_INVALID_PRIORITY;
    6245  }
    6346
    64   the_thread->real_priority = new_priority;
    65   context->status = STATUS_SUCCESSFUL;
    66 
    67   return _Thread_Priority_less_than( current_priority, new_priority )
    68     || !_Thread_Owns_resources( the_thread );
     47  _Thread_queue_Context_clear_priority_updates( queue_context );
     48  _Thread_Priority_change(
     49    the_thread,
     50    &the_thread->Real_priority,
     51    core_new_priority,
     52    false,
     53    queue_context
     54  );
     55  cpu_self = _Thread_Dispatch_disable_critical(
     56    &queue_context->Lock_context.Lock_context
     57  );
     58  _Thread_Wait_release( the_thread, queue_context );
     59  _Thread_Priority_update( queue_context );
     60  _Thread_Dispatch_enable( cpu_self );
     61  return RTEMS_SUCCESSFUL;
    6962}
    7063
     
    7669{
    7770  Thread_Control          *the_thread;
    78   ISR_lock_Context         lock_context;
     71  Thread_queue_Context     queue_context;
    7972  const Scheduler_Control *scheduler;
    8073  Priority_Control         old_priority;
     
    8578  }
    8679
    87   the_thread = _Thread_Get( id, &lock_context );
     80  _Thread_queue_Context_initialize( &queue_context );
     81  the_thread = _Thread_Get( id, &queue_context.Lock_context.Lock_context );
    8882
    8983  if ( the_thread == NULL ) {
     
    9589  }
    9690
     91  _Thread_Wait_acquire_critical( the_thread, &queue_context );
     92
     93  scheduler = _Scheduler_Get_own( the_thread );
     94  old_priority = _Thread_Get_priority( the_thread );
     95
    9796  if ( new_priority != RTEMS_CURRENT_PRIORITY ) {
    98     RTEMS_tasks_Set_priority_context  context;
    99     Per_CPU_Control                  *cpu_self;
    100 
    101     cpu_self = _Thread_Dispatch_disable_critical( &lock_context );
    102     _ISR_lock_ISR_enable( &lock_context );
    103 
    104     context.new_priority = new_priority;
    105     _Thread_Change_priority(
     97    status = _RTEMS_tasks_Set_priority(
    10698      the_thread,
    107       0,
    108       &context,
    109       _RTEMS_tasks_Set_priority_filter,
    110       false
     99      scheduler,
     100      new_priority,
     101      &queue_context
    111102    );
    112 
    113     _Thread_Dispatch_enable( cpu_self );
    114     scheduler = context.scheduler;
    115     old_priority = context.old_priority;
    116     status = context.status;
    117103  } else {
    118     _Thread_State_acquire_critical( the_thread, &lock_context );
    119     scheduler = _Scheduler_Get_own( the_thread );
    120     old_priority = _Thread_Get_priority( the_thread );
    121     _Thread_State_release( the_thread, &lock_context );
     104    _Thread_Wait_release( the_thread, &queue_context );
    122105    status = RTEMS_SUCCESSFUL;
    123106  }
  • cpukit/score/Makefile.am

    r8c83cbc r300f6a48  
    5959include_rtems_score_HEADERS += include/rtems/score/percpu.h
    6060include_rtems_score_HEADERS += include/rtems/score/priority.h
     61include_rtems_score_HEADERS += include/rtems/score/priorityimpl.h
    6162include_rtems_score_HEADERS += include/rtems/score/prioritybitmap.h
    6263include_rtems_score_HEADERS += include/rtems/score/prioritybitmapimpl.h
     
    301302    src/threadget.c src/threadhandler.c src/threadinitialize.c \
    302303    src/threadloadenv.c \
    303     src/threadrestart.c src/threadsetpriority.c \
     304    src/threadrestart.c \
    304305    src/threadsetstate.c \
    305306    src/threadstackallocate.c src/threadstackfree.c src/threadstart.c \
  • cpukit/score/include/rtems/score/coremutex.h

    r8c83cbc r300f6a48  
    8383
    8484  /**
    85    * @brief The priority ceiling value for the mutex owner.
     85   * @brief The priority ceiling node for the mutex owner.
    8686   */
    87   Priority_Control priority_ceiling;
     87  Priority_Node Priority_ceiling;
    8888
    8989#if defined(RTEMS_SMP)
  • cpukit/score/include/rtems/score/coremuteximpl.h

    r8c83cbc r300f6a48  
    125125}
    126126
    127 RTEMS_INLINE_ROUTINE void _CORE_mutex_Restore_priority(
    128   Thread_Control *executing
    129 )
    130 {
    131   /*
    132    *  Whether or not someone is waiting for the mutex, an
    133    *  inherited priority must be lowered if this is the last
    134    *  mutex (i.e. resource) this task has.
    135    */
    136   if ( !_Thread_Owns_resources( executing ) ) {
    137     /*
    138      * Ensure that the executing resource count is visible to all other
    139      * processors and that we read the latest priority restore hint.
    140      */
    141     _Atomic_Fence( ATOMIC_ORDER_ACQ_REL );
    142 
    143     if ( executing->priority_restore_hint ) {
    144       Per_CPU_Control *cpu_self;
    145 
    146       cpu_self = _Thread_Dispatch_disable();
    147       _Thread_Restore_priority( executing );
    148       _Thread_Dispatch_enable( cpu_self );
    149     }
    150   }
    151 }
    152 
    153127RTEMS_INLINE_ROUTINE void _CORE_recursive_mutex_Initialize(
    154128  CORE_recursive_mutex_Control *the_mutex
     
    213187  unsigned int        nest_level;
    214188  Thread_queue_Heads *heads;
    215   bool                keep_priority;
    216189
    217190  _CORE_mutex_Acquire_critical( &the_mutex->Mutex, queue_context );
     
    233206  _CORE_mutex_Set_owner( &the_mutex->Mutex, NULL );
    234207
    235   /*
    236    * Ensure that the owner resource count is visible to all other
    237    * processors and that we read the latest priority restore
    238    * hint.
    239    */
    240   _Atomic_Fence( ATOMIC_ORDER_ACQ_REL );
    241 
    242208  heads = the_mutex->Mutex.Wait_queue.Queue.heads;
    243   keep_priority = _Thread_Owns_resources( executing )
    244     || !executing->priority_restore_hint;
    245 
    246   if ( heads == NULL && keep_priority ) {
     209
     210  if ( heads == NULL ) {
    247211    _CORE_mutex_Release( &the_mutex->Mutex, queue_context );
    248212    return STATUS_SUCCESSFUL;
     
    251215  _Thread_queue_Surrender(
    252216    &the_mutex->Mutex.Wait_queue.Queue,
    253     CORE_MUTEX_TQ_PRIORITY_INHERIT_OPERATIONS,
    254217    heads,
    255218    executing,
    256     keep_priority,
    257     queue_context
     219    queue_context,
     220    CORE_MUTEX_TQ_PRIORITY_INHERIT_OPERATIONS
    258221  );
    259222  return STATUS_SUCCESSFUL;
     
    350313{
    351314  _CORE_recursive_mutex_Initialize( &the_mutex->Recursive );
    352   the_mutex->priority_ceiling = priority_ceiling;
     315  _Priority_Node_initialize( &the_mutex->Priority_ceiling, priority_ceiling );
    353316#if defined(RTEMS_SMP)
    354317  the_mutex->scheduler = scheduler;
     
    370333RTEMS_INLINE_ROUTINE void _CORE_ceiling_mutex_Set_priority(
    371334  CORE_ceiling_mutex_Control *the_mutex,
    372   Priority_Control            priority_ceiling
    373 )
    374 {
    375   the_mutex->priority_ceiling = priority_ceiling;
     335  Priority_Control            priority_ceiling,
     336  Thread_queue_Context       *queue_context
     337)
     338{
     339  Thread_Control *owner;
     340
     341  owner = _CORE_mutex_Get_owner( &the_mutex->Recursive.Mutex );
     342
     343  if ( owner != NULL ) {
     344    _Thread_Wait_acquire( owner, queue_context );
     345    _Thread_Priority_change(
     346      owner,
     347      &the_mutex->Priority_ceiling,
     348      priority_ceiling,
     349      false,
     350      queue_context
     351    );
     352    _Thread_Wait_release( owner, queue_context );
     353  } else {
     354    the_mutex->Priority_ceiling.priority = priority_ceiling;
     355  }
    376356}
    377357
     
    380360)
    381361{
    382   return the_mutex->priority_ceiling;
     362  return the_mutex->Priority_ceiling.priority;
    383363}
    384364
     
    389369)
    390370{
    391   Priority_Control  priority_ceiling;
    392   Priority_Control  current_priority;
     371  ISR_lock_Context  lock_context;
     372  Scheduler_Node   *own_node;
    393373  Per_CPU_Control  *cpu_self;
    394374
    395   priority_ceiling = the_mutex->priority_ceiling;
    396   current_priority = _Thread_Get_priority( owner );
    397 
    398   if ( current_priority < priority_ceiling ) {
     375  _Thread_queue_Context_clear_priority_updates( queue_context );
     376  _Thread_Wait_acquire_default_critical( owner, &lock_context );
     377
     378  own_node = _Thread_Scheduler_get_own_node( owner );
     379
     380  if (
     381    own_node->Wait.Priority.Node.priority
     382      < the_mutex->Priority_ceiling.priority
     383  ) {
     384    _Thread_Wait_release_default_critical( owner, &lock_context );
    399385    _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context );
    400386    return STATUS_MUTEX_CEILING_VIOLATED;
     
    403389  _CORE_mutex_Set_owner( &the_mutex->Recursive.Mutex, owner );
    404390  ++owner->resource_count;
    405 
    406   if ( current_priority == priority_ceiling ) {
    407     _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context );
    408     return STATUS_SUCCESSFUL;
    409   }
     391  _Thread_Priority_add(
     392    owner,
     393    &the_mutex->Priority_ceiling,
     394    queue_context
     395  );
     396  _Thread_Wait_release_default_critical( owner, &lock_context );
    410397
    411398  cpu_self = _Thread_Dispatch_disable_critical(
     
    413400  );
    414401  _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context );
    415   _Thread_Raise_priority( owner, priority_ceiling );
     402  _Thread_Priority_update( queue_context );
    416403  _Thread_Dispatch_enable( cpu_self );
    417404  return STATUS_SUCCESSFUL;
     
    473460)
    474461{
    475   unsigned int    nest_level;
    476   Thread_Control *new_owner;
     462  unsigned int      nest_level;
     463  ISR_lock_Context  lock_context;
     464  Per_CPU_Control  *cpu_self;
     465  Thread_Control   *new_owner;
    477466
    478467  _CORE_mutex_Acquire_critical( &the_mutex->Recursive.Mutex, queue_context );
     
    493482  --executing->resource_count;
    494483
     484  _Thread_queue_Context_clear_priority_updates( queue_context );
     485  _Thread_Wait_acquire_default_critical( executing, &lock_context );
     486  _Thread_Priority_remove(
     487    executing,
     488    &the_mutex->Priority_ceiling,
     489    queue_context
     490  );
     491  _Thread_Wait_release_default_critical( executing, &lock_context );
     492
    495493  new_owner = _Thread_queue_First_locked(
    496494    &the_mutex->Recursive.Mutex.Wait_queue,
     
    499497  _CORE_mutex_Set_owner( &the_mutex->Recursive.Mutex, new_owner );
    500498
     499  cpu_self = _Thread_Dispatch_disable_critical(
     500    &queue_context->Lock_context.Lock_context
     501  );
     502
    501503  if ( new_owner != NULL ) {
    502     bool unblock;
    503 
    504     /*
    505      * We must extract the thread now since this will restore its default
    506      * thread lock.  This is necessary to avoid a deadlock in the
    507      * _Thread_Change_priority() below due to a recursive thread queue lock
    508      * acquire.
    509      */
    510     unblock = _Thread_queue_Extract_locked(
     504#if defined(RTEMS_MULTIPROCESSING)
     505    if ( _Objects_Is_local_id( new_owner->Object.id ) )
     506#endif
     507    {
     508      ++new_owner->resource_count;
     509      _Thread_Priority_add(
     510        new_owner,
     511        &the_mutex->Priority_ceiling,
     512        queue_context
     513      );
     514    }
     515
     516    _Thread_queue_Extract_critical(
    511517      &the_mutex->Recursive.Mutex.Wait_queue.Queue,
    512518      CORE_MUTEX_TQ_OPERATIONS,
     
    514520      queue_context
    515521    );
    516 
    517 #if defined(RTEMS_MULTIPROCESSING)
    518     if ( _Objects_Is_local_id( new_owner->Object.id ) )
    519 #endif
    520     {
    521       ++new_owner->resource_count;
    522       _Thread_Raise_priority( new_owner, the_mutex->priority_ceiling );
    523     }
    524 
    525     _Thread_queue_Unblock_critical(
    526       unblock,
    527       &the_mutex->Recursive.Mutex.Wait_queue.Queue,
    528       new_owner,
    529       &queue_context->Lock_context.Lock_context
    530     );
    531522  } else {
    532523    _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context );
    533524  }
    534525
    535   _CORE_mutex_Restore_priority( executing );
     526  _Thread_Priority_update( queue_context );
     527  _Thread_Dispatch_enable( cpu_self );
    536528  return STATUS_SUCCESSFUL;
    537529}
  • cpukit/score/include/rtems/score/mrsp.h

    r8c83cbc r300f6a48  
    8181
    8282  /**
    83    * @brief The initial priority of the thread at the begin of the resource
    84    * obtain sequence.
    85    *
    86    * Used to restore the priority after a release of this resource or timeout.
     83   * @brief The ceiling priority used by the rival thread.
    8784   */
    88   Priority_Control initial_priority;
     85  Priority_Node Ceiling_priority;
    8986
    9087  /**
     
    136133
    137134  /**
    138    * @brief The initial priority of the owner before it was elevated to the
    139    * ceiling priority.
     135   * @brief The ceiling priority used by the owner thread.
    140136   */
    141   Priority_Control initial_priority_of_owner;
     137  Priority_Node Ceiling_priority;
    142138
    143139  /**
  • cpukit/score/include/rtems/score/mrspimpl.h

    r8c83cbc r300f6a48  
    7878}
    7979
    80 RTEMS_INLINE_ROUTINE bool _MRSP_Restore_priority_filter(
    81   Thread_Control   *thread,
    82   Priority_Control *new_priority,
    83   void             *arg
    84 )
    85 {
    86   *new_priority = _Thread_Priority_highest(
    87     thread->real_priority,
    88     *new_priority
    89   );
    90 
    91   return *new_priority != _Thread_Get_priority( thread );
    92 }
    93 
    94 RTEMS_INLINE_ROUTINE void _MRSP_Restore_priority(
    95   Thread_Control   *thread,
    96   Priority_Control  initial_priority
    97 )
    98 {
    99   /*
    100    * The Thread_Control::resource_count is used by the normal priority ceiling
    101    * or priority inheritance semaphores.
    102    */
    103   if ( thread->resource_count == 0 ) {
    104     _Thread_Change_priority(
    105       thread,
    106       initial_priority,
    107       NULL,
    108       _MRSP_Restore_priority_filter,
    109       true
    110     );
    111   }
    112 }
    113 
    114 RTEMS_INLINE_ROUTINE void _MRSP_Claim_ownership(
     80RTEMS_INLINE_ROUTINE Priority_Control _MRSP_Get_priority(
     81  const MRSP_Control      *mrsp,
     82  const Scheduler_Control *scheduler
     83)
     84{
     85  uint32_t scheduler_index;
     86
     87  scheduler_index = _Scheduler_Get_index( scheduler );
     88  return mrsp->ceiling_priorities[ scheduler_index ];
     89}
     90
     91RTEMS_INLINE_ROUTINE void _MRSP_Set_priority(
     92  MRSP_Control            *mrsp,
     93  const Scheduler_Control *scheduler,
     94  Priority_Control         new_priority
     95)
     96{
     97  uint32_t scheduler_index;
     98
     99  scheduler_index = _Scheduler_Get_index( scheduler );
     100  mrsp->ceiling_priorities[ scheduler_index ] = new_priority;
     101}
     102
     103RTEMS_INLINE_ROUTINE Status_Control _MRSP_Raise_priority(
     104  MRSP_Control         *mrsp,
     105  Thread_Control       *thread,
     106  Priority_Node        *priority_node,
     107  Thread_queue_Context *queue_context
     108)
     109{
     110  Status_Control           status;
     111  ISR_lock_Context         lock_context;
     112  const Scheduler_Control *scheduler;
     113  Priority_Control         ceiling_priority;
     114  Scheduler_Node          *own_node;
     115
     116  _Thread_queue_Context_clear_priority_updates( queue_context );
     117  _Thread_Wait_acquire_default_critical( thread, &lock_context );
     118
     119  scheduler = _Scheduler_Get_own( thread );
     120  own_node = _Thread_Scheduler_get_own_node( thread );
     121  ceiling_priority = _MRSP_Get_priority( mrsp, scheduler );
     122
     123  if ( ceiling_priority <= own_node->Wait.Priority.Node.priority ) {
     124    _Priority_Node_initialize( priority_node, ceiling_priority );
     125    _Thread_Priority_add( thread, priority_node, queue_context );
     126    status = STATUS_SUCCESSFUL;
     127  } else {
     128    status = STATUS_MUTEX_CEILING_VIOLATED;
     129  }
     130
     131  _Thread_Wait_release_default_critical( thread, &lock_context );
     132  return status;
     133}
     134
     135RTEMS_INLINE_ROUTINE void _MRSP_Remove_priority(
     136  Thread_Control       *thread,
     137  Priority_Node        *priority_node,
     138  Thread_queue_Context *queue_context
     139)
     140{
     141  ISR_lock_Context  lock_context;
     142
     143  _Thread_queue_Context_clear_priority_updates( queue_context );
     144  _Thread_Wait_acquire_default_critical( thread, &lock_context );
     145  _Thread_Priority_remove( thread, priority_node, queue_context );
     146  _Thread_Wait_release_default_critical( thread, &lock_context );
     147}
     148
     149RTEMS_INLINE_ROUTINE void _MRSP_Replace_priority(
     150  MRSP_Control   *mrsp,
     151  Thread_Control *thread,
     152  MRSP_Rival     *rival
     153)
     154{
     155  ISR_lock_Context lock_context;
     156
     157  _Thread_Wait_acquire_default_critical( thread, &lock_context );
     158  _Thread_Priority_replace(
     159    thread,
     160    &rival->Ceiling_priority,
     161    &mrsp->Ceiling_priority
     162  );
     163  _Thread_Wait_release_default_critical( thread, &lock_context );
     164}
     165
     166RTEMS_INLINE_ROUTINE Status_Control _MRSP_Claim_ownership(
    115167  MRSP_Control         *mrsp,
    116168  Thread_Control       *new_owner,
    117   Priority_Control      initial_priority,
    118   Priority_Control      ceiling_priority,
    119   Thread_queue_Context *queue_context
    120 )
    121 {
     169  Thread_queue_Context *queue_context
     170)
     171{
     172  Status_Control   status;
    122173  Per_CPU_Control *cpu_self;
     174
     175  status = _MRSP_Raise_priority(
     176    mrsp,
     177    new_owner,
     178    &mrsp->Ceiling_priority,
     179    queue_context
     180  );
     181
     182  if ( status != STATUS_SUCCESSFUL ) {
     183    _MRSP_Release( mrsp, queue_context );
     184    return status;
     185  }
    123186
    124187  _Resource_Node_add_resource( &new_owner->Resource_node, &mrsp->Resource );
    125188  _Resource_Set_owner( &mrsp->Resource, &new_owner->Resource_node );
    126   mrsp->initial_priority_of_owner = initial_priority;
    127189  _Scheduler_Thread_change_help_state( new_owner, SCHEDULER_HELP_ACTIVE_OWNER );
    128190
     
    132194  _MRSP_Release( mrsp, queue_context );
    133195
    134   _Thread_Raise_priority( new_owner, ceiling_priority );
     196  _Thread_Priority_update( queue_context );
    135197
    136198  _Thread_Dispatch_enable( cpu_self );
     199  return STATUS_SUCCESSFUL;
    137200}
    138201
     
    179242}
    180243
    181 RTEMS_INLINE_ROUTINE Priority_Control _MRSP_Get_priority(
    182   const MRSP_Control      *mrsp,
    183   const Scheduler_Control *scheduler
    184 )
    185 {
    186   uint32_t scheduler_index;
    187 
    188   scheduler_index = _Scheduler_Get_index( scheduler );
    189   return mrsp->ceiling_priorities[ scheduler_index ];
    190 }
    191 
    192 RTEMS_INLINE_ROUTINE void _MRSP_Set_priority(
    193   MRSP_Control            *mrsp,
    194   const Scheduler_Control *scheduler,
    195   Priority_Control         new_priority
    196 )
    197 {
    198   uint32_t scheduler_index;
    199 
    200   scheduler_index = _Scheduler_Get_index( scheduler );
    201   mrsp->ceiling_priorities[ scheduler_index ] = new_priority;
    202 }
    203 
    204244RTEMS_INLINE_ROUTINE void _MRSP_Timeout( Watchdog_Control *watchdog )
    205245{
    206   MRSP_Rival *rival = RTEMS_CONTAINER_OF( watchdog, MRSP_Rival, Watchdog );
    207   MRSP_Control *mrsp = rival->resource;
    208   Thread_Control *thread = rival->thread;
    209   Thread_queue_Context queue_context;
     246  MRSP_Rival           *rival;
     247  MRSP_Control         *mrsp;
     248  Thread_Control       *thread;
     249  Thread_queue_Context  queue_context;
     250
     251  rival = RTEMS_CONTAINER_OF( watchdog, MRSP_Rival, Watchdog );
     252  mrsp = rival->resource;
     253  thread = rival->thread;
    210254
    211255  _Thread_queue_Context_initialize( &queue_context );
     
    215259  if ( rival->status == MRSP_WAIT_FOR_OWNERSHIP ) {
    216260    ISR_lock_Context giant_lock_context;
     261
     262    _MRSP_Remove_priority( thread, &rival->Ceiling_priority, &queue_context );
    217263
    218264    _MRSP_Giant_acquire( &giant_lock_context );
     
    229275
    230276    _MRSP_Release( mrsp, &queue_context );
     277
     278    _Thread_Priority_update( &queue_context );
    231279  } else {
    232280    _MRSP_Release( mrsp, &queue_context );
     
    238286  Resource_Node        *owner,
    239287  Thread_Control       *executing,
    240   Priority_Control      initial_priority,
    241   Priority_Control      ceiling_priority,
    242   Thread_queue_Context *queue_context
    243 )
    244 {
    245   Status_Control status;
    246   MRSP_Rival rival;
    247   Thread_Life_state life_state;
    248   Per_CPU_Control *cpu_self;
    249   ISR_lock_Context giant_lock_context;
    250   ISR_Level level;
    251   Watchdog_Interval timeout = queue_context->timeout;
     288  Thread_queue_Context *queue_context
     289)
     290{
     291  Status_Control     status;
     292  MRSP_Rival         rival;
     293  Thread_Life_state  life_state;
     294  Per_CPU_Control   *cpu_self;
     295  ISR_lock_Context   giant_lock_context;
     296  ISR_Level          level;
     297  Watchdog_Interval  timeout;
     298
    252299  _Assert( queue_context->timeout_discipline == WATCHDOG_RELATIVE );
     300
     301  status = _MRSP_Raise_priority(
     302    mrsp,
     303    executing,
     304    &rival.Ceiling_priority,
     305    queue_context
     306  );
     307
     308  if ( status != STATUS_SUCCESSFUL ) {
     309    _MRSP_Release( mrsp, queue_context );
     310    return status;
     311  }
    253312
    254313  rival.thread = executing;
    255314  rival.resource = mrsp;
    256   rival.initial_priority = initial_priority;
     315  _Chain_Initialize_node( &rival.Node );
    257316
    258317  _MRSP_Giant_acquire( &giant_lock_context );
     
    278337  _MRSP_Release( mrsp, queue_context );
    279338
    280   _Thread_Raise_priority( executing, ceiling_priority );
     339  _Thread_Priority_update( queue_context );
     340
     341  timeout = (Watchdog_Interval) queue_context->timeout;
    281342
    282343  if ( timeout > 0 ) {
     
    308369    );
    309370    _ISR_Local_enable( level );
    310 
    311     if ( status == STATUS_TIMEOUT ) {
    312       _MRSP_Restore_priority( executing, initial_priority );
    313     }
    314371  }
    315372
     
    324381)
    325382{
    326   Status_Control status;
    327   const Scheduler_Control *scheduler = _Scheduler_Get_own( executing );
    328   Priority_Control initial_priority = _Thread_Get_priority( executing );
    329   Priority_Control ceiling_priority = _MRSP_Get_priority( mrsp, scheduler );
    330   bool priority_ok = !_Thread_Priority_less_than(
    331     ceiling_priority,
    332     initial_priority
    333   );
    334   Resource_Node *owner;
    335 
    336   if ( !priority_ok) {
    337     _ISR_lock_ISR_enable( &queue_context->Lock_context.Lock_context );
    338     return STATUS_MUTEX_CEILING_VIOLATED;
    339   }
     383  Status_Control  status;
     384  Resource_Node  *owner;
    340385
    341386  _MRSP_Acquire_critical( mrsp, queue_context );
     387
    342388  owner = _Resource_Get_owner( &mrsp->Resource );
     389
    343390  if ( owner == NULL ) {
    344     _MRSP_Claim_ownership(
    345       mrsp,
    346       executing,
    347       initial_priority,
    348       ceiling_priority,
    349       queue_context
    350     );
    351     status = STATUS_SUCCESSFUL;
     391    status = _MRSP_Claim_ownership( mrsp, executing, queue_context );
    352392  } else if (
    353393    wait
    354394      && _Resource_Node_get_root( owner ) != &executing->Resource_node
    355395  ) {
    356     status = _MRSP_Wait_for_ownership(
    357       mrsp,
    358       owner,
    359       executing,
    360       initial_priority,
    361       ceiling_priority,
    362       queue_context
    363     );
     396    status = _MRSP_Wait_for_ownership( mrsp, owner, executing, queue_context );
    364397  } else {
    365398    _MRSP_Release( mrsp, queue_context );
     
    377410)
    378411{
    379   Priority_Control initial_priority;
    380   Per_CPU_Control *cpu_self;
    381   ISR_lock_Context giant_lock_context;
     412  ISR_lock_Context  giant_lock_context;
     413  Per_CPU_Control  *cpu_self;
    382414
    383415  if ( _Resource_Get_owner( &mrsp->Resource ) != &executing->Resource_node ) {
     
    396428  }
    397429
    398   initial_priority = mrsp->initial_priority_of_owner;
    399 
    400430  _MRSP_Acquire_critical( mrsp, queue_context );
    401 
     431  _MRSP_Remove_priority( executing, &mrsp->Ceiling_priority, queue_context );
    402432  _MRSP_Giant_acquire( &giant_lock_context );
    403433
     
    407437    _Resource_Set_owner( &mrsp->Resource, NULL );
    408438  } else {
    409     MRSP_Rival *rival = (MRSP_Rival *)
    410       _Chain_Get_first_unprotected( &mrsp->Rivals );
     439    MRSP_Rival     *rival;
    411440    Thread_Control *new_owner;
     441
     442    rival = (MRSP_Rival *) _Chain_Get_first_unprotected( &mrsp->Rivals );
    412443
    413444    /*
     
    418449
    419450    new_owner = rival->thread;
    420     mrsp->initial_priority_of_owner = rival->initial_priority;
     451
     452    _MRSP_Replace_priority( mrsp, new_owner, rival );
     453
    421454    _Resource_Node_extract( &new_owner->Resource_node );
    422455    _Resource_Node_set_dependency( &new_owner->Resource_node, NULL );
     
    438471  _MRSP_Release( mrsp, queue_context );
    439472
    440   _MRSP_Restore_priority( executing, initial_priority );
     473  _Thread_Priority_update( queue_context );
    441474
    442475  _Thread_Dispatch_enable( cpu_self );
  • cpukit/score/include/rtems/score/priority.h

    r8c83cbc r300f6a48  
    11/**
    2  * @file rtems/score/priority.h
     2 * @file
    33 *
    4  * @brief Thread Priority Manipulation Routines
    5  *
    6  * This include file contains all thread priority manipulation routines.
    7  * This Handler provides mechanisms which can be used to
    8  * initialize and manipulate thread priorities.
     4 * @brief Priority Handler API
    95 */
    106
     
    128 *  COPYRIGHT (c) 1989-2011.
    139 *  On-Line Applications Research Corporation (OAR).
     10 *
     11 *  Copyright (c) 2016 embedded brains GmbH.
    1412 *
    1513 *  The license and distribution terms for this file may be
     
    2119#define _RTEMS_SCORE_PRIORITY_H
    2220
    23 /**
    24  *  @defgroup ScorePriority Priority Handler
    25  *
    26  *  @ingroup Score
    27  *
    28  *  This handler encapsulates functionality which is used to manage
    29  *  thread priorities.  At the SuperCore level 256 priority levels
    30  *  are supported with lower numbers representing logically more important
    31  *  threads.  The priority level 0 is reserved for internal RTEMS use.
    32  *  Typically it is assigned to threads which defer internal RTEMS
    33  *  actions from an interrupt to thread level to improve interrupt response.
    34  *  Priority level 255 is assigned to the IDLE thread and really should not
    35  *  be used by application threads.  The default IDLE thread implementation
    36  *  is an infinite "branch to self" loop which never yields to other threads
    37  *  at the same priority.
    38  */
    39 /**@{*/
     21#include <rtems/score/chain.h>
     22#include <rtems/score/cpu.h>
     23#include <rtems/score/rbtree.h>
    4024
    41 /*
    42  * Processor specific information.
    43  */
    44 #include <rtems/score/cpu.h>
     25struct Scheduler_Control;
    4526
    4627#ifdef __cplusplus
     
    4930
    5031/**
    51  *  The following type defines the control block used to manage
    52  *  thread priorities.
     32 * @defgroup ScorePriority Priority Handler
    5333 *
    54  *  @note Priority 0 is reserved for internal threads only.
     34 * @ingroup Score
     35 *
     36 * This handler encapsulates functionality which is used to manage thread
     37 * priorities.  The actual priority of a thread is an aggregation of priority
     38 * nodes.  The thread priority aggregation for the home scheduler instance of a
     39 * thread consists of at least one priority node, which is normally the real
     40 * priority of the thread.  The locking protocols (e.g. priority ceiling and
     41 * priority inheritance), rate-monotonic period objects and the POSIX sporadic
     42 * server add, change and remove priority nodes.
     43 *
     44 * @{
     45 */
     46
     47/**
     48 * @brief A plain thread priority value.
     49 *
     50 * Lower values represent higher priorities.  So, a priority value of zero
     51 * represents the highest priority thread.  This value is reserved for internal
     52 * threads and the priority ceiling protocol.
    5553 */
    5654typedef uint64_t Priority_Control;
    5755
    58 /** This defines the highest (most important) thread priority. */
     56/**
     57 * @brief The highest (most important) thread priority value.
     58 */
    5959#define PRIORITY_MINIMUM      0
    6060
    6161/**
    62  * @brief This defines the priority of pseudo-ISR threads.
     62 * @brief The priority value of pseudo-ISR threads.
    6363 *
    6464 * Examples are the MPCI and timer server threads.
     
    6666#define PRIORITY_PSEUDO_ISR   PRIORITY_MINIMUM
    6767
    68 /** This defines the default lowest (least important) thread priority. */
     68/**
     69 * @brief The default lowest (least important) thread priority value.
     70 *
     71 * This value is CPU port dependent.
     72 */
    6973#if defined (CPU_PRIORITY_MAXIMUM)
    7074  #define PRIORITY_DEFAULT_MAXIMUM      CPU_PRIORITY_MAXIMUM
     
    7276  #define PRIORITY_DEFAULT_MAXIMUM      255
    7377#endif
     78
     79/**
     80 * @brief The priority node to build up a priority aggregation.
     81 */
     82typedef struct {
     83  /**
     84   * @brief Node component for a chain or red-black tree.
     85   */
     86  union {
     87    Chain_Node Chain;
     88    RBTree_Node RBTree;
     89  } Node;
     90
     91  /**
     92   * @brief The priority value of this node.
     93   */
     94  Priority_Control priority;
     95} Priority_Node;
     96
     97/**
     98 * @brief The priority action type.
     99 */
     100typedef enum {
     101  PRIORITY_ACTION_ADD,
     102  PRIORITY_ACTION_CHANGE,
     103  PRIORITY_ACTION_REMOVE,
     104  PRIORITY_ACTION_INVALID
     105} Priority_Action_type;
     106
     107typedef struct Priority_Aggregation Priority_Aggregation;
     108
     109/**
     110 * @brief The priority aggregation.
     111 *
     112 * This structure serves two purposes.  Firstly, it provides a place to
     113 * register priority nodes and reflects the overall priority of its
     114 * contributors.  Secondly, it provides an action block to signal addition,
     115 * change and removal of a priority node.
     116 */
     117struct Priority_Aggregation {
     118  /**
     119   * @brief This priority node reflects the overall priority of the aggregation.
     120   *
     121   * The overall priority of the aggregation is the minimum priority of the
     122   * priority nodes in the contributors tree.
     123   *
     124   * This priority node may be used to add this aggregation to another
     125   * aggregation to build up a recursive priority scheme.
     126   *
     127   * In case priority nodes of the contributors tree are added, changed or
     128   * removed the priority of this node may change.  To signal such changes to a
     129   * priority aggregation the action block may be used.
     130   */
     131  Priority_Node Node;
     132
     133  /**
     134   * @brief A red-black tree to contain priority nodes contributing to the
     135   * overall priority of this priority aggregation.
     136   */
     137  RBTree_Control Contributors;
     138
     139#if defined(RTEMS_SMP)
     140  /**
     141   * @brief The scheduler instance of this priority aggregation.
     142   */
     143  const struct Scheduler_Control *scheduler;
     144#endif
     145
     146  /**
     147   * @brief A priority action block to manage priority node additions, changes
     148   * and removals.
     149   */
     150  struct {
     151#if defined(RTEMS_SMP)
     152    /**
     153     * @brief The next priority aggregation in the action list.
     154     */
     155    Priority_Aggregation *next;
     156#endif
     157
     158    /**
     159     * @brief The priority node of the action.
     160     */
     161    Priority_Node *node;
     162
     163    /**
     164     * @brief The type of the action.
     165     */
     166    Priority_Action_type type;
     167  } Action;
     168};
     169
     170/**
     171 * @brief A list of priority actions.
     172 *
     173 * Actions are only added to the list.  The action lists reside on the stack
     174 * and have a short life-time.  They are moved, processed or destroyed as a
     175 * whole.
     176 */
     177typedef struct {
     178  /**
     179   * @brief The first action of a priority action list.
     180   */
     181  Priority_Aggregation *actions;
     182} Priority_Actions;
    74183
    75184#ifdef __cplusplus
  • cpukit/score/include/rtems/score/scheduler.h

    r8c83cbc r300f6a48  
    136136
    137137  /** @see _Scheduler_Release_job() */
    138   Thread_Control *( *release_job ) (
    139     const Scheduler_Control *,
    140     Thread_Control *,
    141     uint64_t
     138  void ( *release_job ) (
     139    const Scheduler_Control *,
     140    Thread_Control *,
     141    Priority_Node *,
     142    uint64_t,
     143    Thread_queue_Context *
    142144  );
    143145
    144146  /** @see _Scheduler_Cancel_job() */
    145   Thread_Control *( *cancel_job ) (
    146     const Scheduler_Control *,
    147     Thread_Control *
     147  void ( *cancel_job ) (
     148    const Scheduler_Control *,
     149    Thread_Control *,
     150    Priority_Node *,
     151    Thread_queue_Context *
    148152  );
    149153
     
    374378 * @param[in] scheduler Unused.
    375379 * @param[in] the_thread Unused.
     380 * @param[in] priority_node Unused.
    376381 * @param[in] deadline Unused.
     382 * @param[in] queue_context Unused.
    377383 *
    378384 * @retval NULL Always.
    379385 */
    380 Thread_Control *_Scheduler_default_Release_job(
     386void _Scheduler_default_Release_job(
    381387  const Scheduler_Control *scheduler,
    382388  Thread_Control          *the_thread,
    383   uint64_t                 deadline
     389  Priority_Node           *priority_node,
     390  uint64_t                 deadline,
     391  Thread_queue_Context    *queue_context
    384392);
    385393
     
    389397 * @param[in] scheduler Unused.
    390398 * @param[in] the_thread Unused.
     399 * @param[in] priority_node Unused.
     400 * @param[in] queue_context Unused.
    391401 *
    392402 * @retval NULL Always.
    393403 */
    394 Thread_Control *_Scheduler_default_Cancel_job(
    395   const Scheduler_Control *scheduler,
    396   Thread_Control          *the_thread
     404void _Scheduler_default_Cancel_job(
     405  const Scheduler_Control *scheduler,
     406  Thread_Control          *the_thread,
     407  Priority_Node           *priority_node,
     408  Thread_queue_Context    *queue_context
    397409);
    398410
  • cpukit/score/include/rtems/score/schedulercbs.h

    r8c83cbc r300f6a48  
    6262    _Scheduler_default_Node_destroy, /* node destroy entry point */ \
    6363    _Scheduler_CBS_Release_job,      /* new period of task */ \
    64     _Scheduler_EDF_Cancel_job,       /* cancel period of task */ \
     64    _Scheduler_CBS_Cancel_job,       /* cancel period of task */ \
    6565    _Scheduler_default_Tick,         /* tick entry point */ \
    6666    _Scheduler_default_Start_idle    /* start idle entry point */ \
     
    136136  /** CBS server specific data of a task. */
    137137  Scheduler_CBS_Server         *cbs_server;
     138
     139  Priority_Node                *deadline_node;
    138140} Scheduler_CBS_Node;
    139141
     
    164166);
    165167
    166 Thread_Control *_Scheduler_CBS_Release_job(
     168void _Scheduler_CBS_Release_job(
    167169  const Scheduler_Control *scheduler,
    168170  Thread_Control          *the_thread,
    169   uint64_t                 length
     171  Priority_Node           *priority_node,
     172  uint64_t                 deadline,
     173  Thread_queue_Context    *queue_context
     174);
     175
     176void _Scheduler_CBS_Cancel_job(
     177  const Scheduler_Control *scheduler,
     178  Thread_Control          *the_thread,
     179  Priority_Node           *priority_node,
     180  Thread_queue_Context    *queue_context
    170181);
    171182
  • cpukit/score/include/rtems/score/scheduleredf.h

    r8c83cbc r300f6a48  
    9090
    9191  /**
    92    * Pointer to corresponding Thread Control Block.
    93    */
    94   Thread_Control *thread;
    95   /**
    9692   * Rbtree node related to this thread.
    9793   */
     
    9995
    10096  /**
    101    * @brief The thread priority used by this scheduler instance in case no job
    102    * is released.
    103    */
    104   Priority_Control background_priority;
    105 
    106   /**
    107    * @brief The thread priority currently used by this scheduler instance.
    108    */
    109   Priority_Control current_priority;
     97   * @brief The thread priority currently used for this scheduler instance.
     98   */
     99  Priority_Control priority;
    110100} Scheduler_EDF_Node;
    111101
     
    216206);
    217207
    218 Thread_Control *_Scheduler_EDF_Release_job(
     208void _Scheduler_EDF_Release_job(
    219209  const Scheduler_Control *scheduler,
    220210  Thread_Control          *the_thread,
    221   uint64_t                 deadline
    222 );
    223 
    224 Thread_Control *_Scheduler_EDF_Cancel_job(
    225   const Scheduler_Control *scheduler,
    226   Thread_Control          *the_thread
     211  Priority_Node           *priority_node,
     212  uint64_t                 deadline,
     213  Thread_queue_Context    *queue_context
     214);
     215
     216void _Scheduler_EDF_Cancel_job(
     217  const Scheduler_Control *scheduler,
     218  Thread_Control          *the_thread,
     219  Priority_Node           *priority_node,
     220  Thread_queue_Context    *queue_context
    227221);
    228222
  • cpukit/score/include/rtems/score/scheduleredfimpl.h

    r8c83cbc r300f6a48  
    7575
    7676  prio_left = *the_left;
    77   prio_right = the_right->current_priority;
     77  prio_right = the_right->priority;
    7878
    7979  return prio_left < prio_right;
     
    9494
    9595  prio_left = *the_left;
    96   prio_right = the_right->current_priority;
     96  prio_right = the_right->priority;
    9797
    9898  return prio_left <= prio_right;
     
    102102  Scheduler_EDF_Context *context,
    103103  Scheduler_EDF_Node    *node,
    104   Priority_Control       current_priority
     104  Priority_Control       priority
    105105)
    106106{
     
    108108    &context->Ready,
    109109    &node->Node,
    110     &current_priority,
     110    &priority,
    111111    _Scheduler_EDF_Less
    112112  );
     
    116116  Scheduler_EDF_Context *context,
    117117  Scheduler_EDF_Node    *node,
    118   Priority_Control       current_priority
     118  Priority_Control       priority
    119119)
    120120{
     
    122122    &context->Ready,
    123123    &node->Node,
    124     &current_priority,
     124    &priority,
    125125    _Scheduler_EDF_Less_or_equal
    126126  );
     
    165165  node = RTEMS_CONTAINER_OF( first, Scheduler_EDF_Node, Node );
    166166
    167   _Scheduler_Update_heir( node->thread, force_dispatch );
     167  _Scheduler_Update_heir( node->Base.owner, force_dispatch );
    168168}
    169169
  • cpukit/score/include/rtems/score/schedulerimpl.h

    r8c83cbc r300f6a48  
    2323#include <rtems/score/scheduler.h>
    2424#include <rtems/score/cpusetimpl.h>
     25#include <rtems/score/priorityimpl.h>
    2526#include <rtems/score/smpimpl.h>
    2627#include <rtems/score/status.h>
     
    9899
    99100  return _Scheduler_Get_by_CPU_index( cpu_index );
    100 }
    101 
    102 RTEMS_INLINE_ROUTINE Scheduler_Node *_Scheduler_Thread_get_own_node(
    103   const Thread_Control *the_thread
    104 )
    105 {
    106 #if defined(RTEMS_SMP)
    107   return the_thread->Scheduler.own_node;
    108 #else
    109   return the_thread->Scheduler.node;
    110 #endif
    111101}
    112102
     
    265255      && _Resource_Node_owns_resources( &needs_help->Resource_node )
    266256  ) {
    267     Scheduler_Node *node = _Scheduler_Thread_get_own_node( needs_help );
     257    Scheduler_Node *node = _Thread_Scheduler_get_own_node( needs_help );
    268258
    269259    if (
     
    487477 *
    488478 * @param[in] the_thread The thread.
     479 * @param[in] priority_node The priority node of the job.
    489480 * @param[in] deadline The deadline in watchdog ticks since boot.
    490  *
    491  * @return The thread to hand over to _Thread_Update_priority().
    492  */
    493 RTEMS_INLINE_ROUTINE Thread_Control *_Scheduler_Release_job(
    494   Thread_Control *the_thread,
    495   uint64_t        deadline
     481 * @param[in] queue_context The thread queue context to provide the set of
     482 *   threads for _Thread_Priority_update().
     483 */
     484RTEMS_INLINE_ROUTINE void _Scheduler_Release_job(
     485  Thread_Control       *the_thread,
     486  Priority_Node        *priority_node,
     487  uint64_t              deadline,
     488  Thread_queue_Context *queue_context
    496489)
    497490{
    498491  const Scheduler_Control *scheduler = _Scheduler_Get( the_thread );
    499492
    500   return ( *scheduler->Operations.release_job )(
     493  _Thread_queue_Context_clear_priority_updates( queue_context );
     494  ( *scheduler->Operations.release_job )(
    501495    scheduler,
    502496    the_thread,
    503     deadline
     497    priority_node,
     498    deadline,
     499    queue_context
    504500  );
    505501}
     
    509505 *
    510506 * @param[in] the_thread The thread.
    511  *
    512  * @return The thread to hand over to _Thread_Update_priority().
    513  */
    514 RTEMS_INLINE_ROUTINE Thread_Control *_Scheduler_Cancel_job(
    515   Thread_Control *the_thread
     507 * @param[in] priority_node The priority node of the job.
     508 * @param[in] queue_context The thread queue context to provide the set of
     509 *   threads for _Thread_Priority_update().
     510 */
     511RTEMS_INLINE_ROUTINE void _Scheduler_Cancel_job(
     512  Thread_Control       *the_thread,
     513  Priority_Node        *priority_node,
     514  Thread_queue_Context *queue_context
    516515)
    517516{
    518517  const Scheduler_Control *scheduler = _Scheduler_Get( the_thread );
    519518
    520   return ( *scheduler->Operations.cancel_job )( scheduler, the_thread );
     519  _Thread_queue_Context_clear_priority_updates( queue_context );
     520  ( *scheduler->Operations.cancel_job )(
     521    scheduler,
     522    the_thread,
     523    priority_node,
     524    queue_context
     525  );
    521526}
    522527
     
    777782)
    778783{
    779   Scheduler_Node *own_node;
    780 
    781   own_node = _Scheduler_Thread_get_own_node( the_thread );
    782   _Scheduler_Node_set_priority( own_node, new_priority, prepend_it );
    783 
    784   the_thread->current_priority = new_priority;
     784  Scheduler_Node *scheduler_node;
     785
     786  scheduler_node = _Thread_Scheduler_get_own_node( the_thread );
     787  _Scheduler_Node_set_priority( scheduler_node, new_priority, prepend_it );
    785788}
    786789
     
    858861)
    859862{
    860   Scheduler_Node *node = _Scheduler_Thread_get_own_node( the_thread );
     863  Scheduler_Node *node = _Thread_Scheduler_get_own_node( the_thread );
    861864  Scheduler_Help_state previous_help_state = node->help_state;
    862865
     
    12951298    _Scheduler_Thread_set_scheduler_and_node(
    12961299      old_user,
    1297       _Scheduler_Thread_get_own_node( old_user ),
     1300      _Thread_Scheduler_get_own_node( old_user ),
    12981301      old_user
    12991302    );
     
    13841387  }
    13851388
    1386   the_thread->current_priority = priority;
    1387   the_thread->real_priority = priority;
     1389  own_node = _Thread_Scheduler_get_own_node( the_thread );
     1390  _Priority_Plain_extract( &own_node->Wait.Priority, &the_thread->Real_priority );
     1391
     1392  if ( !_Priority_Is_empty( &own_node->Wait.Priority ) ) {
     1393    _Priority_Plain_insert(
     1394      &own_node->Wait.Priority,
     1395      &the_thread->Real_priority,
     1396      the_thread->Real_priority.priority
     1397    );
     1398    return STATUS_RESOURCE_IN_USE;
     1399  }
     1400
    13881401  the_thread->Start.initial_priority = priority;
    1389 
    1390   own_node = _Scheduler_Thread_get_own_node( the_thread );
     1402  _Priority_Node_set_priority( &the_thread->Real_priority, priority );
     1403  _Priority_Initialize_one(
     1404    &own_node->Wait.Priority,
     1405    &the_thread->Real_priority
     1406  );
    13911407
    13921408#if defined(RTEMS_SMP)
  • cpukit/score/include/rtems/score/schedulernode.h

    r8c83cbc r300f6a48  
    9999 * @brief Scheduler node for per-thread data.
    100100 */
    101 typedef struct {
     101typedef struct Scheduler_Node {
    102102#if defined(RTEMS_SMP)
    103103  /**
     
    145145   */
    146146  struct {
    147     /**
    148      * @brief Node for thread queues.
    149      *
    150      * Each scheduler node can be enqueued on a thread queue on behalf of the
    151      * thread owning the scheduler node.  The scheduler node reflects the
    152      * priority of the thread within the corresponding scheduler instance.
    153      */
    154     union {
    155       /**
    156        * @brief A node for chains.
    157        */
    158       Chain_Node Chain;
    159 
    160       /**
    161        * @brief A node for red-black trees.
    162        */
    163       RBTree_Node RBTree;
    164     } Node;
     147    Priority_Aggregation Priority;
    165148  } Wait;
    166149
  • cpukit/score/include/rtems/score/schedulernodeimpl.h

    r8c83cbc r300f6a48  
    1818#include <rtems/score/schedulernode.h>
    1919
     20struct Scheduler_Control;
     21
    2022#ifdef __cplusplus
    2123extern "C" {
    2224#endif /* __cplusplus */
    2325
    24 #define SCHEDULER_NODE_OF_WAIT_CHAIN_NODE( node ) \
    25   RTEMS_CONTAINER_OF( node, Scheduler_Node, Wait.Node.Chain )
     26#define SCHEDULER_NODE_OF_WAIT_PRIORITY_NODE( node ) \
     27  RTEMS_CONTAINER_OF( node, Scheduler_Node, Wait.Priority.Node.Node.Chain )
    2628
    27 #define SCHEDULER_NODE_OF_WAIT_RBTREE_NODE( node ) \
    28   RTEMS_CONTAINER_OF( node, Scheduler_Node, Wait.Node.RBTree )
     29#define SCHEDULER_NODE_OF_WAIT_PRIORITY( node ) \
     30  RTEMS_CONTAINER_OF( node, Scheduler_Node, Wait.Priority )
    2931
    3032RTEMS_INLINE_ROUTINE void _Scheduler_Node_do_initialize(
    31   Scheduler_Node   *node,
    32   Thread_Control   *the_thread,
    33   Priority_Control  priority
     33  const struct Scheduler_Control *scheduler,
     34  Scheduler_Node                 *node,
     35  Thread_Control                 *the_thread,
     36  Priority_Control                priority
    3437)
    3538{
     
    4043
    4144#if defined(RTEMS_SMP)
     45  node->Wait.Priority.scheduler = scheduler;
    4246  node->user = the_thread;
    4347  node->help_state = SCHEDULER_HELP_YOURSELF;
     
    4650  _SMP_sequence_lock_Initialize( &node->Priority.Lock );
    4751#else
     52  (void) scheduler;
    4853  (void) the_thread;
    4954#endif
  • cpukit/score/include/rtems/score/schedulersmpimpl.h

    r8c83cbc r300f6a48  
    376376)
    377377{
    378   return (Scheduler_SMP_Node *) _Scheduler_Thread_get_own_node( thread );
     378  return (Scheduler_SMP_Node *) _Thread_Scheduler_get_own_node( thread );
    379379}
    380380
     
    387387
    388388static inline void _Scheduler_SMP_Node_initialize(
    389   Scheduler_SMP_Node *node,
    390   Thread_Control     *thread,
    391   Priority_Control    priority
    392 )
    393 {
    394   _Scheduler_Node_do_initialize( &node->Base, thread, priority );
     389  const Scheduler_Control *scheduler,
     390  Scheduler_SMP_Node      *node,
     391  Thread_Control          *thread,
     392  Priority_Control         priority
     393)
     394{
     395  _Scheduler_Node_do_initialize( scheduler, &node->Base, thread, priority );
    395396  node->state = SCHEDULER_SMP_NODE_BLOCKED;
    396397  node->priority = priority;
  • cpukit/score/include/rtems/score/thread.h

    r8c83cbc r300f6a48  
    374374   * The thread wait lock mechanism protects the following thread variables
    375375   *  - POSIX_API_Control::Attributes,
    376    *  - Thread_Control::current_priority,
     376   *  - Scheduler_Node::Wait,
    377377   *  - Thread_Control::Wait::Lock::Pending_requests,
    378378   *  - Thread_Control::Wait::queue, and
     
    462462  /** This field is the current execution state of this proxy. */
    463463  States_Control           current_state;
    464   /**
    465    * @brief This field is the current priority state of this thread.
    466    *
    467    * Writes to this field are only allowed in _Thread_Initialize() or via
    468    * _Thread_Change_priority().
    469    */
    470   Priority_Control         current_priority;
    471 
    472   /**
    473    * @brief This field is the base priority of this thread.
    474    *
    475    * Writes to this field are only allowed in _Thread_Initialize() or via
    476    * _Thread_Change_priority().
    477    */
    478   Priority_Control         real_priority;
    479 
    480   /**
    481    * @brief Hints if a priority restore is necessary once the resource count
    482    * changes from one to zero.
    483    *
    484    * This is an optimization to speed up the mutex surrender sequence in case
    485    * no attempt to change the priority was made during the mutex ownership.  On
    486    * SMP configurations atomic fences must synchronize writes to
    487    * Thread_Control::priority_restore_hint and Thread_Control::resource_count.
    488    */
    489   bool                     priority_restore_hint;
     464
     465  /**
     466   * @brief The base priority of this thread in its home scheduler instance.
     467   */
     468  Priority_Node            Real_priority;
    490469
    491470  /** This field is the number of mutexes currently held by this proxy. */
     
    709688
    710689  /**
    711    * @brief This field is the current priority state of this thread.
    712    *
    713    * Writes to this field are only allowed in _Thread_Initialize() or via
    714    * _Thread_Change_priority().
    715    */
    716   Priority_Control         current_priority;
    717 
    718   /**
    719    * @brief This field is the base priority of this thread.
    720    *
    721    * Writes to this field are only allowed in _Thread_Initialize() or via
    722    * _Thread_Change_priority().
    723    */
    724   Priority_Control         real_priority;
    725 
    726   /**
    727    * @brief Hints if a priority restore is necessary once the resource count
    728    * changes from one to zero.
    729    *
    730    * This is an optimization to speed up the mutex surrender sequence in case
    731    * no attempt to change the priority was made during the mutex ownership.  On
    732    * SMP configurations atomic fences must synchronize writes to
    733    * Thread_Control::priority_restore_hint and Thread_Control::resource_count.
    734    */
    735   bool                     priority_restore_hint;
     690   * @brief The base priority of this thread in its home scheduler instance.
     691   */
     692  Priority_Node            Real_priority;
    736693
    737694  /** This field is the number of mutexes currently held by this thread. */
  • cpukit/score/include/rtems/score/threadimpl.h

    r8c83cbc r300f6a48  
    416416
    417417/**
     418 * @brief Performs the priority actions specified by the thread queue context
     419 * along the thread queue path.
     420 *
     421 * The caller must be the owner of the thread wait lock.
     422 *
     423 * @param start_of_path The start thread of the thread queue path.
     424 * @param queue_context The thread queue context specifying the thread queue
     425 *   path and initial thread priority actions.
     426 *
     427 * @see _Thread_queue_Path_acquire_critical().
     428 */
     429void _Thread_Priority_perform_actions(
     430  Thread_Control       *start_of_path,
     431  Thread_queue_Context *queue_context
     432);
     433
     434/**
     435 * @brief Adds the specified thread priority node to the corresponding thread
     436 * priority aggregation.
     437 *
     438 * The caller must be the owner of the thread wait lock.
     439 *
     440 * @param the_thread The thread.
     441 * @param priority_node The thread priority node to add.
     442 * @param queue_context The thread queue context to return an updated set of
     443 *   threads for _Thread_Priority_update().  The thread queue context must be
     444 *   initialized via _Thread_queue_Context_clear_priority_updates() before a
     445 *   call of this function.
     446 *
     447 * @see _Thread_Wait_acquire().
     448 */
     449void _Thread_Priority_add(
     450  Thread_Control       *the_thread,
     451  Priority_Node        *priority_node,
     452  Thread_queue_Context *queue_context
     453);
     454
     455/**
     456 * @brief Removes the specified thread priority node from the corresponding
     457 * thread priority aggregation.
     458 *
     459 * The caller must be the owner of the thread wait lock.
     460 *
     461 * @param the_thread The thread.
     462 * @param priority_node The thread priority node to remove.
     463 * @param queue_context The thread queue context to return an updated set of
     464 *   threads for _Thread_Priority_update().  The thread queue context must be
     465 *   initialized via _Thread_queue_Context_clear_priority_updates() before a
     466 *   call of this function.
     467 *
     468 * @see _Thread_Wait_acquire().
     469 */
     470void _Thread_Priority_remove(
     471  Thread_Control       *the_thread,
     472  Priority_Node        *priority_node,
     473  Thread_queue_Context *queue_context
     474);
     475
     476/**
     477 * @brief Propagates a thread priority value change in the specified thread
     478 * priority node to the corresponding thread priority aggregation.
     479 *
     480 * The caller must be the owner of the thread wait lock.
     481 *
     482 * @param the_thread The thread.
     483 * @param priority_node The thread priority node to change.
     484 * @param prepend_it In case this is true, then the thread is prepended to
     485 *   its priority group in its home scheduler instance, otherwise it is
     486 *   appended.
     487 * @param queue_context The thread queue context to return an updated set of
     488 *   threads for _Thread_Priority_update().  The thread queue context must be
     489 *   initialized via _Thread_queue_Context_clear_priority_updates() before a
     490 *   call of this function.
     491 *
     492 * @see _Thread_Wait_acquire().
     493 */
     494void _Thread_Priority_changed(
     495  Thread_Control       *the_thread,
     496  Priority_Node        *priority_node,
     497  bool                  prepend_it,
     498  Thread_queue_Context *queue_context
     499);
     500
     501/**
     502 * @brief Changes the thread priority value of the specified thread priority
     503 * node in the corresponding thread priority aggregation.
     504 *
     505 * The caller must be the owner of the thread wait lock.
     506 *
     507 * @param the_thread The thread.
     508 * @param priority_node The thread priority node to change.
     509 * @param new_priority The new thread priority value of the thread priority
     510 *   node to change.
     511 * @param prepend_it In case this is true, then the thread is prepended to
     512 *   its priority group in its home scheduler instance, otherwise it is
     513 *   appended.
     514 * @param queue_context The thread queue context to return an updated set of
     515 *   threads for _Thread_Priority_update().  The thread queue context must be
     516 *   initialized via _Thread_queue_Context_clear_priority_updates() before a
     517 *   call of this function.
     518 *
     519 * @see _Thread_Wait_acquire().
     520 */
     521RTEMS_INLINE_ROUTINE void _Thread_Priority_change(
     522  Thread_Control       *the_thread,
     523  Priority_Node        *priority_node,
     524  Priority_Control      new_priority,
     525  bool                  prepend_it,
     526  Thread_queue_Context *queue_context
     527)
     528{
     529  _Priority_Node_set_priority( priority_node, new_priority );
     530  _Thread_Priority_changed(
     531    the_thread,
     532    priority_node,
     533    prepend_it,
     534    queue_context
     535  );
     536}
     537
     538/**
     539 * @brief Replaces the victim priority node with the replacement priority node
     540 * in the corresponding thread priority aggregation.
     541 *
     542 * The caller must be the owner of the thread wait lock.
     543 *
     544 * @param the_thread The thread.
     545 * @param victim_node The victim thread priority node.
     546 * @param replacement_node The replacement thread priority node.
     547 *
     548 * @see _Thread_Wait_acquire().
     549 */
     550void _Thread_Priority_replace(
     551  Thread_Control *the_thread,
     552  Priority_Node  *victim_node,
     553  Priority_Node  *replacement_node
     554);
     555
     556/**
     557 * @brief Adds a priority node to the corresponding thread priority
     558 * aggregation.
     559 *
     560 * The caller must be the owner of the thread wait lock.
     561 *
     562 * @param the_thread The thread.
     563 * @param priority_node The thread priority node to add.
     564 * @param queue_context The thread queue context to return an updated set of
     565 *   threads for _Thread_Priority_update().  The thread queue context must be
     566 *   initialized via _Thread_queue_Context_clear_priority_updates() before a
     567 *   call of this function.
     568 *
     569 * @see _Thread_Priority_add(), _Thread_Priority_change(),
     570 *   _Thread_Priority_changed() and _Thread_Priority_remove().
     571 */
     572void _Thread_Priority_update( Thread_queue_Context *queue_context );
     573
     574/**
    418575 * @brief Returns true if the left thread priority is less than the right
    419576 * thread priority in the intuitive sense of priority and false otherwise.
     
    438595  return _Thread_Priority_less_than( left, right ) ? right : left;
    439596}
    440 
    441 /**
    442  * @brief Filters a thread priority change.
    443  *
    444  * Called by _Thread_Change_priority() under the protection of the thread lock.
    445  *
    446  * @param[in] the_thread The thread.
    447  * @param[in, out] new_priority The new priority of the thread.  The filter may
    448  * alter this value.
    449  * @param[in] arg The argument passed to _Thread_Change_priority().
    450  *
    451  * @retval true Change the current priority.
    452  * @retval false Otherwise.
    453  */
    454 typedef bool ( *Thread_Change_priority_filter )(
    455   Thread_Control   *the_thread,
    456   Priority_Control *new_priority,
    457   void             *arg
    458 );
    459 
    460 Thread_Control *_Thread_Apply_priority(
    461   Thread_Control                *the_thread,
    462   Priority_Control               new_priority,
    463   void                          *arg,
    464   Thread_Change_priority_filter  filter,
    465   bool                           prepend_it
    466 );
    467 
    468 void _Thread_Update_priority( Thread_Control *the_thread );
    469 
    470 /**
    471  * @brief Changes the priority of a thread if allowed by the filter function.
    472  *
    473  * It changes current priority of the thread to the new priority in case the
    474  * filter function returns true.  In this case the scheduler is notified of the
    475  * priority change as well.
    476  *
    477  * @param[in] the_thread The thread.
    478  * @param[in] new_priority The new priority of the thread.
    479  * @param[in] arg The argument for the filter function.
    480  * @param[in] filter The filter function to determine if a priority change is
    481  * allowed and optionally perform other actions under the protection of the
    482  * thread lock simultaneously with the update of the current priority.
    483  * @param[in] prepend_it In case this is true, then the thread is prepended to
    484  * its priority group in its scheduler instance, otherwise it is appended.
    485  */
    486 void _Thread_Change_priority(
    487   Thread_Control                *the_thread,
    488   Priority_Control               new_priority,
    489   void                          *arg,
    490   Thread_Change_priority_filter  filter,
    491   bool                           prepend_it
    492 );
    493 
    494 /**
    495  * @brief Raises the priority of a thread.
    496  *
    497  * It changes the current priority of the thread to the new priority if the new
    498  * priority is higher than the current priority.  In this case the thread is
    499  * appended to its new priority group in its scheduler instance.
    500  *
    501  * @param[in] the_thread The thread.
    502  * @param[in] new_priority The new priority of the thread.
    503  *
    504  * @see _Thread_Change_priority().
    505  */
    506 void _Thread_Raise_priority(
    507   Thread_Control   *the_thread,
    508   Priority_Control  new_priority
    509 );
    510 
    511 /**
    512  * @brief Sets the current to the real priority of a thread.
    513  *
    514  * Sets the priority restore hint to false.
    515  */
    516 void _Thread_Restore_priority( Thread_Control *the_thread );
    517 
    518 /**
    519  * @brief Sets the priority of a thread.
    520  *
    521  * It sets the real priority of the thread.  In addition it changes the current
    522  * priority of the thread if the new priority is higher than the current
    523  * priority or the thread owns no resources.
    524  *
    525  * @param[in] the_thread The thread.
    526  * @param[in] new_priority The new priority of the thread.
    527  * @param[out] old_priority The old real priority of the thread.  This pointer
    528  * must not be @c NULL.
    529  * @param[in] prepend_it In case this is true, then the thread is prepended to
    530  * its priority group in its scheduler instance, otherwise it is appended.
    531  *
    532  * @see _Thread_Change_priority().
    533  */
    534 void _Thread_Set_priority(
    535   Thread_Control   *the_thread,
    536   Priority_Control  new_priority,
    537   Priority_Control *old_priority,
    538   bool              prepend_it
    539 );
    540597
    541598RTEMS_INLINE_ROUTINE Objects_Information *_Thread_Get_objects_information(
     
    930987}
    931988
     989RTEMS_INLINE_ROUTINE Scheduler_Node *_Thread_Scheduler_get_own_node(
     990  const Thread_Control *the_thread
     991)
     992{
     993#if defined(RTEMS_SMP)
     994  return the_thread->Scheduler.own_node;
     995#else
     996  return the_thread->Scheduler.node;
     997#endif
     998}
     999
    9321000/**
    9331001 * @brief Returns the priority of the thread.
     
    9381006 *
    9391007 * @return The priority of the thread.
    940  *
    941  * @see _Scheduler_Node_get_priority().
    9421008 */
    9431009RTEMS_INLINE_ROUTINE Priority_Control _Thread_Get_priority(
     
    9451011)
    9461012{
    947   return the_thread->current_priority;
     1013  Scheduler_Node *scheduler_node;
     1014
     1015  scheduler_node = _Thread_Scheduler_get_own_node( the_thread );
     1016  return _Priority_Get_priority( &scheduler_node->Wait.Priority );
    9481017}
    9491018
     
    13901459#endif
    13911460
    1392     ( *the_thread->Wait.operations->extract )( queue, the_thread );
     1461    ( *the_thread->Wait.operations->extract )(
     1462      queue,
     1463      the_thread,
     1464      queue_context
     1465    );
    13931466    _Thread_Wait_restore_default( the_thread );
    13941467
  • cpukit/score/include/rtems/score/threadq.h

    r8c83cbc r300f6a48  
    3131#endif
    3232
     33struct Scheduler_Node;
     34
    3335/**
    3436 *  @defgroup ScoreThreadQueue Thread Queue Handler
     
    4749
    4850typedef struct Thread_queue_Operations Thread_queue_Operations;
    49 
    50 typedef struct Thread_queue_Path Thread_queue_Path;
    5151
    5252/**
     
    196196  uint64_t timeout;
    197197
     198#if defined(RTEMS_SMP)
     199  /**
     200   * @brief Representation of a thread queue path from a start thread queue to
     201   * the terminal thread queue.
     202   *
     203   * The start thread queue is determined by the object on which a thread intends
     204   * to block.  The terminal thread queue is the thread queue reachable via
     205   * thread queue links whose owner is not blocked on a thread queue.  The thread
     206   * queue links are determined by the thread queue owner and thread wait queue
     207   * relationships.
     208   */
     209  struct {
     210    /**
     211     * @brief The chain of thread queue links defining the thread queue path.
     212     */
     213    Chain_Control Links;
     214
     215    /**
     216     * @brief The start of a thread queue path.
     217     */
     218    Thread_queue_Link Start;
     219  } Path;
     220#endif
     221
     222  /**
     223   * @brief Block to manage thread priority changes due to a thread queue
     224   * operation.
     225   */
     226  struct {
     227    /**
     228     * @brief A priority action list.
     229     */
     230    Priority_Actions Actions;
     231
     232    /**
     233     * @brief Count of threads to update the priority via
     234     * _Thread_Priority_update().
     235     */
     236    size_t update_count;
     237
     238    /**
     239     * @brief Threads to update the priority via _Thread_Priority_update().
     240     *
     241     * Currently, a maximum of two threads need an update in one rush, for
     242     * example the thread of the thread queue operation and the owner of the
     243     * thread queue.
     244     */
     245    Thread_Control *update[ 2 ];
     246  } Priority;
     247
    198248  /**
    199249   * @brief Invoked in case of a detected deadlock.
     
    238288   * @brief The actual thread priority queue.
    239289   */
    240   RBTree_Control Queue;
     290  Priority_Aggregation Queue;
     291
     292  /**
     293   * @brief This priority queue is added to a scheduler node of the owner in
     294   * case of priority inheritance.
     295   */
     296  struct Scheduler_Node *scheduler_node;
    241297} Thread_queue_Priority_queue;
    242298
     
    290346#if defined(RTEMS_SMP)
    291347  /**
     348   * @brief Boost priority.
     349   */
     350  Priority_Node Boost_priority;
     351
     352  /**
    292353   * @brief One priority queue per scheduler instance.
    293354   */
     
    338399
    339400/**
    340  * @brief Thread queue priority change operation.
     401 * @brief Thread queue action operation.
    341402 *
    342403 * @param[in] queue The actual thread queue.
    343404 * @param[in] the_thread The thread.
    344  * @param[in] new_priority The new priority value.
    345  *
    346  * @see Thread_queue_Operations.
    347  */
    348 typedef void ( *Thread_queue_Priority_change_operation )(
    349   Thread_queue_Queue *queue,
    350   Thread_Control     *the_thread,
    351   Priority_Control    new_priority
     405 * @param[in] queue_context The thread queue context providing the thread queue
     406 *   action set to perform.  Returns the thread queue action set to perform on
     407 *   the thread queue owner or the empty set in case there is nothing to do.
     408 */
     409typedef void ( *Thread_queue_Priority_actions_operation )(
     410  Thread_queue_Queue   *queue,
     411  Priority_Actions     *priority_actions
    352412);
    353413
     
    356416 *
    357417 * A potential thread to update the priority due to priority inheritance is
    358  * returned via the thread queue path.  This thread is handed over to
    359  * _Thread_Update_priority().
     418 * returned via the thread queue context.  This thread is handed over to
     419 * _Thread_Priority_update().
    360420 *
    361421 * @param[in] queue The actual thread queue.
     
    363423 */
    364424typedef void ( *Thread_queue_Enqueue_operation )(
    365   Thread_queue_Queue *queue,
    366   Thread_Control     *the_thread,
    367   Thread_queue_Path  *path
     425  Thread_queue_Queue   *queue,
     426  Thread_Control       *the_thread,
     427  Thread_queue_Context *queue_context
    368428);
    369429
     
    375435 */
    376436typedef void ( *Thread_queue_Extract_operation )(
    377   Thread_queue_Queue *queue,
    378   Thread_Control     *the_thread
     437  Thread_queue_Queue   *queue,
     438  Thread_Control       *the_thread,
     439  Thread_queue_Context *queue_context
    379440);
    380441
     
    391452 */
    392453typedef Thread_Control *( *Thread_queue_Surrender_operation )(
    393   Thread_queue_Queue *queue,
    394   Thread_queue_Heads *heads,
    395   Thread_Control     *previous_owner
     454  Thread_queue_Queue   *queue,
     455  Thread_queue_Heads   *heads,
     456  Thread_Control       *previous_owner,
     457  Thread_queue_Context *queue_context
    396458);
    397459
     
    416478struct Thread_queue_Operations {
    417479  /**
    418    * @brief Thread queue priority change operation.
    419    *
    420    * Called by _Thread_Change_priority() to notify a thread about a priority
    421    * change.  In case this thread waits currently for a resource the handler
    422    * may adjust its data structures according to the new priority value.  This
    423    * handler must not be NULL, instead the default handler
    424    * _Thread_Do_nothing_priority_change() should be used in case nothing needs
    425    * to be done during a priority change.
    426    */
    427   Thread_queue_Priority_change_operation priority_change;
     480   * @brief Thread queue priority actions operation.
     481   */
     482  Thread_queue_Priority_actions_operation priority_actions;
    428483
    429484  /**
  • cpukit/score/include/rtems/score/threadqimpl.h

    r8c83cbc r300f6a48  
    2222#include <rtems/score/threadq.h>
    2323#include <rtems/score/chainimpl.h>
    24 #include <rtems/score/rbtreeimpl.h>
     24#include <rtems/score/priorityimpl.h>
    2525#include <rtems/score/scheduler.h>
    2626#include <rtems/score/smp.h>
     
    4040/**@{*/
    4141
    42 /**
    43  * @brief Representation of a thread queue path from a start thread queue to
    44  * the terminal thread queue.
    45  *
    46  * The start thread queue is determined by the object on which a thread intends
    47  * to block.  The terminal thread queue is the thread queue reachable via
    48  * thread queue links those owner is not blocked on a thread queue.  The thread
    49  * queue links are determined by the thread queue owner and thread wait queue
    50  * relationships.
    51  */
    52 struct Thread_queue_Path {
    53 #if defined(RTEMS_SMP)
    54   /**
    55    * @brief The chain of thread queue links defining the thread queue path.
    56    */
    57   Chain_Control Links;
    58 
    59   /**
    60    * @brief The start of a thread queue path.
    61    */
    62   Thread_queue_Link Start;
    63 #endif
    64 
    65   /**
    66    * @brief A potential thread to update the priority via
    67    * _Thread_Update_priority().
    68    *
    69    * This thread is determined by thread queues which support priority
    70    * inheritance.
    71    */
    72   Thread_Control *update_priority;
    73 };
     42#define THREAD_QUEUE_LINK_OF_PATH_NODE( node ) \
     43  RTEMS_CONTAINER_OF( node, Thread_queue_Link, Path_node );
    7444
    7545/**
     
    211181}
    212182
     183RTEMS_INLINE_ROUTINE void _Thread_queue_Context_clear_priority_updates(
     184  Thread_queue_Context *queue_context
     185)
     186{
     187  queue_context->Priority.update_count = 0;
     188}
     189
     190RTEMS_INLINE_ROUTINE size_t _Thread_queue_Context_save_priority_updates(
     191  Thread_queue_Context *queue_context
     192)
     193{
     194  return queue_context->Priority.update_count;
     195}
     196
     197RTEMS_INLINE_ROUTINE void _Thread_queue_Context_restore_priority_updates(
     198  Thread_queue_Context *queue_context,
     199  size_t                update_count
     200)
     201{
     202  queue_context->Priority.update_count = update_count;
     203}
     204
     205RTEMS_INLINE_ROUTINE void _Thread_queue_Context_add_priority_update(
     206  Thread_queue_Context *queue_context,
     207  Thread_Control       *the_thread
     208)
     209{
     210  size_t n;
     211
     212  n = queue_context->Priority.update_count;
     213  _Assert( n < RTEMS_ARRAY_SIZE( queue_context->Priority.update ) );
     214
     215  queue_context->Priority.update_count = n + 1;
     216  queue_context->Priority.update[ n ] = the_thread;
     217}
     218
    213219/**
    214220 * @brief Sets the MP callout in the thread queue context.
     
    275281  size_t i;
    276282
     283  _Priority_Node_initialize( &heads->Boost_priority, 0 );
     284  _Priority_Node_set_inactive( &heads->Boost_priority );
     285
    277286  for ( i = 0; i < _Scheduler_Count; ++i ) {
    278287    _Chain_Initialize_node( &heads->Priority[ i ].Node );
    279     _RBTree_Initialize_empty( &heads->Priority[ i ].Queue );
     288    _Priority_Initialize_empty( &heads->Priority[ i ].Queue );
    280289  }
    281290#endif
     
    580589}
    581590
    582 bool _Thread_queue_Do_extract_locked(
    583   Thread_queue_Queue            *queue,
    584   const Thread_queue_Operations *operations,
    585   Thread_Control                *the_thread
    586 #if defined(RTEMS_MULTIPROCESSING)
    587   ,
    588   const Thread_queue_Context    *queue_context
    589 #endif
    590 );
    591 
    592591/**
    593592 * @brief Extracts the thread from the thread queue, restores the default wait
     
    600599 * @param[in] operations The thread queue operations.
    601600 * @param[in] the_thread The thread to extract.
    602  * @param[in] queue_context The thread queue context.  This parameter is only
    603  *   used on multiprocessing configurations.
     601 * @param[in] queue_context The thread queue context.
    604602 *
    605603 * @return Returns the unblock indicator for _Thread_queue_Unblock_critical().
     
    611609 * configuration.
    612610 */
    613 #if defined(RTEMS_MULTIPROCESSING)
    614   #define _Thread_queue_Extract_locked( \
    615     unblock, \
    616     queue, \
    617     the_thread, \
    618     queue_context \
    619   ) \
    620     _Thread_queue_Do_extract_locked( \
    621       unblock, \
    622       queue, \
    623       the_thread, \
    624       queue_context \
    625     )
    626 #else
    627   #define _Thread_queue_Extract_locked( \
    628     unblock, \
    629     queue, \
    630     the_thread, \
    631     queue_context \
    632   ) \
    633     _Thread_queue_Do_extract_locked( \
    634       unblock, \
    635       queue, \
    636       the_thread \
    637     )
    638 #endif
     611bool _Thread_queue_Extract_locked(
     612  Thread_queue_Queue            *queue,
     613  const Thread_queue_Operations *operations,
     614  Thread_Control                *the_thread,
     615  Thread_queue_Context          *queue_context
     616);
    639617
    640618/**
     
    736714/**
    737715 * @brief Surrenders the thread queue previously owned by the thread to the
    738  * first enqueued thread if it exists.
     716 * first enqueued thread.
    739717 *
    740718 * The owner of the thread queue must be set to NULL by the caller.
     
    744722 *
    745723 * @param[in] queue The actual thread queue.
    746  * @param[in] operations The thread queue operations.
    747  * @param[in] heads The thread queue heads.
     724 * @param[in] heads The thread queue heads.  It must not be NULL.
    748725 * @param[in] previous_owner The previous owner thread surrendering the thread
    749726 *   queue.
    750  * @param[in] keep_priority Indicates if the previous owner thread should keep
    751  *   its current priority.
    752727 * @param[in] queue_context The thread queue context of the lock acquire.
     728 * @param[in] operations The thread queue operations.
    753729 */
    754730void _Thread_queue_Surrender(
    755731  Thread_queue_Queue            *queue,
    756   const Thread_queue_Operations *operations,
    757732  Thread_queue_Heads            *heads,
    758733  Thread_Control                *previous_owner,
    759   bool                           keep_priority,
    760   Thread_queue_Context          *queue_context
     734  Thread_queue_Context          *queue_context,
     735  const Thread_queue_Operations *operations
    761736);
    762737
     
    981956#endif
    982957
     958bool _Thread_queue_Path_acquire_critical(
     959  Thread_queue_Queue   *queue,
     960  Thread_Control       *the_thread,
     961  Thread_queue_Context *queue_context
     962);
     963
     964void _Thread_queue_Path_release_critical(
     965  Thread_queue_Context *queue_context
     966);
     967
    983968/**
    984969 * @brief Helper structure to ensure that all objects containing a thread queue
  • cpukit/score/preinstall.am

    r8c83cbc r300f6a48  
    200200        $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/priority.h
    201201PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/priority.h
     202
     203$(PROJECT_INCLUDE)/rtems/score/priorityimpl.h: include/rtems/score/priorityimpl.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
     204        $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/priorityimpl.h
     205PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/priorityimpl.h
    202206
    203207$(PROJECT_INCLUDE)/rtems/score/prioritybitmap.h: include/rtems/score/prioritybitmap.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
  • cpukit/score/src/mutex.c

    r8c83cbc r300f6a48  
    129129{
    130130  Thread_queue_Heads *heads;
    131   bool keep_priority;
    132 
     131
     132  heads = mutex->Queue.Queue.heads;
    133133  mutex->Queue.Queue.owner = NULL;
    134 
    135134  --executing->resource_count;
    136135
    137   /*
    138    * Ensure that the owner resource count is visible to all other
    139    * processors and that we read the latest priority restore
    140    * hint.
    141    */
    142   _Atomic_Fence( ATOMIC_ORDER_ACQ_REL );
    143 
    144   heads = mutex->Queue.Queue.heads;
    145   keep_priority = _Thread_Owns_resources( executing )
    146     || !executing->priority_restore_hint;
    147 
    148   if ( __predict_true( heads == NULL && keep_priority ) ) {
     136  if ( __predict_true( heads == NULL ) ) {
    149137    _Mutex_Queue_release( mutex, queue_context );
    150138  } else {
    151139    _Thread_queue_Surrender(
    152140      &mutex->Queue.Queue,
    153       MUTEX_TQ_OPERATIONS,
    154141      heads,
    155142      executing,
    156       keep_priority,
    157       queue_context
     143      queue_context,
     144      MUTEX_TQ_OPERATIONS
    158145    );
    159146  }
  • cpukit/score/src/schedulercbs.c

    r8c83cbc r300f6a48  
    2020
    2121#include <rtems/score/schedulercbsimpl.h>
    22 #include <rtems/score/threadimpl.h>
    23 #include <rtems/score/wkspace.h>
    2422
    2523void _Scheduler_CBS_Budget_callout(
     
    2725)
    2826{
    29   Priority_Control          new_priority;
    30   Priority_Control          unused;
    31   Scheduler_CBS_Node       *node;
    32   Scheduler_CBS_Server_id   server_id;
     27  Scheduler_CBS_Node      *node;
     28  Scheduler_CBS_Server_id  server_id;
     29  Thread_queue_Context     queue_context;
     30
     31  node = _Scheduler_CBS_Thread_get_node( the_thread );
    3332
    3433  /* Put violating task to background until the end of period. */
    35   new_priority = the_thread->Start.initial_priority;
    36   _Thread_Set_priority( the_thread, new_priority, &unused, true );
     34  _Thread_queue_Context_clear_priority_updates( &queue_context );
     35  _Scheduler_CBS_Cancel_job(
     36    NULL,
     37    the_thread,
     38    node->deadline_node,
     39    &queue_context
     40  );
     41  _Thread_Priority_update( &queue_context );
    3742
    3843  /* Invoke callback function if any. */
    39   node = _Scheduler_CBS_Thread_get_node( the_thread );
    4044  if ( node->cbs_server->cbs_budget_overrun ) {
    4145    _Scheduler_CBS_Get_server_id(
  • cpukit/score/src/schedulercbsnodeinit.c

    r8c83cbc r300f6a48  
    3434  the_node = _Scheduler_CBS_Node_downcast( node );
    3535  the_node->cbs_server = NULL;
     36  the_node->deadline_node = NULL;
    3637}
  • cpukit/score/src/schedulercbsreleasejob.c

    r8c83cbc r300f6a48  
    2222#include <rtems/score/schedulercbsimpl.h>
    2323
    24 Thread_Control *_Scheduler_CBS_Release_job(
     24void _Scheduler_CBS_Release_job(
    2525  const Scheduler_Control *scheduler,
    2626  Thread_Control          *the_thread,
    27   uint64_t                 deadline
     27  Priority_Node           *priority_node,
     28  uint64_t                 deadline,
     29  Thread_queue_Context    *queue_context
    2830)
    2931{
     
    3941  }
    4042
    41   return _Scheduler_EDF_Release_job( scheduler, the_thread, deadline );
     43  node->deadline_node = priority_node;
     44
     45  _Scheduler_EDF_Release_job(
     46    scheduler,
     47    the_thread,
     48    priority_node,
     49    deadline,
     50    queue_context
     51  );
    4252}
     53
     54void _Scheduler_CBS_Cancel_job(
     55  const Scheduler_Control *scheduler,
     56  Thread_Control          *the_thread,
     57  Priority_Node           *priority_node,
     58  Thread_queue_Context    *queue_context
     59)
     60{
     61  Scheduler_CBS_Node *node;
     62
     63  node = _Scheduler_CBS_Thread_get_node( the_thread );
     64
     65  if ( node->deadline_node != NULL ) {
     66    _Assert( node->deadline_node == priority_node );
     67    node->deadline_node = NULL;
     68
     69    _Scheduler_EDF_Cancel_job(
     70      scheduler,
     71      the_thread,
     72      priority_node,
     73      queue_context
     74    );
     75  }
     76}
  • cpukit/score/src/schedulercbsunblock.c

    r8c83cbc r300f6a48  
    3131)
    3232{
    33   Scheduler_EDF_Context *context;
    34   Scheduler_CBS_Node    *node;
    35   Scheduler_CBS_Server  *serv_info;
    36   Priority_Control       priority;
    37   bool                   prepend_it;
     33  Scheduler_CBS_Node   *node;
     34  Scheduler_CBS_Server *serv_info;
     35  Priority_Control      priority;
     36  bool                  prepend_it;
    3837
    39   context = _Scheduler_EDF_Get_context( scheduler );
    4038  node = _Scheduler_CBS_Thread_get_node( the_thread );
    4139  serv_info = node->cbs_server;
     
    5654
    5755    if ( deadline * budget_left > budget * deadline_left ) {
     56      Thread_queue_Context queue_context;
     57
    5858      /* Put late unblocked task to background until the end of period. */
    59 
    60       priority = node->Base.background_priority;
    61       the_thread->real_priority = priority;
    62 
    63       if (
    64         _Thread_Priority_less_than(
    65           _Thread_Get_priority( the_thread ),
    66           priority
    67         ) || !_Thread_Owns_resources( the_thread )
    68       ) {
    69         the_thread->current_priority = priority;
    70       }
     59      _Thread_queue_Context_clear_priority_updates( &queue_context );
     60      _Scheduler_CBS_Cancel_job(
     61        scheduler,
     62        the_thread,
     63        node->deadline_node,
     64        &queue_context
     65      );
    7166    }
    7267  }
    7368
    74   node->Base.current_priority = priority;
    75   _Scheduler_EDF_Enqueue( context, &node->Base, priority );
    76 
    77   /*
    78    *  If the thread that was unblocked is more important than the heir,
    79    *  then we have a new heir.  This may or may not result in a
    80    *  context switch.
    81    *
    82    *  Normal case:
    83    *    If the current thread is preemptible, then we need to do
    84    *    a context switch.
    85    *  Pseudo-ISR case:
    86    *    Even if the thread isn't preemptible, if the new heir is
    87    *    a pseudo-ISR system task, we need to do a context switch.
    88    */
    89   if ( priority < _Thread_Get_priority( _Thread_Heir ) ) {
    90     _Scheduler_Update_heir( the_thread, priority == PRIORITY_PSEUDO_ISR );
    91   }
    92 
     69  _Scheduler_EDF_Unblock( scheduler, the_thread );
    9370  SCHEDULER_RETURN_VOID_OR_NULL;
    9471}
  • cpukit/score/src/schedulerdefaultnodeinit.c

    r8c83cbc r300f6a48  
    2929)
    3030{
    31   (void) scheduler;
    32 
    33   _Scheduler_Node_do_initialize( node, the_thread, priority );
     31  _Scheduler_Node_do_initialize( scheduler, node, the_thread, priority );
    3432}
  • cpukit/score/src/schedulerdefaultreleasejob.c

    r8c83cbc r300f6a48  
    2222#include <rtems/score/scheduler.h>
    2323
    24 Thread_Control *_Scheduler_default_Release_job(
     24void _Scheduler_default_Release_job(
    2525  const Scheduler_Control *scheduler,
    2626  Thread_Control          *the_thread,
    27   uint64_t                 deadline
     27  Priority_Node           *priority_node,
     28  uint64_t                 deadline,
     29  Thread_queue_Context    *queue_context
    2830)
    2931{
    3032  (void) scheduler;
    3133  (void) the_thread;
     34  (void) priority_node;
    3235  (void) deadline;
    33 
    34   return NULL;
     36  (void) queue_context;
    3537}
    3638
    37 Thread_Control *_Scheduler_default_Cancel_job(
     39void _Scheduler_default_Cancel_job(
    3840  const Scheduler_Control *scheduler,
    39   Thread_Control          *the_thread
     41  Thread_Control          *the_thread,
     42  Priority_Node           *priority_node,
     43  Thread_queue_Context    *queue_context
    4044)
    4145{
    4246  (void) scheduler;
    4347  (void) the_thread;
    44 
    45   return NULL;
     48  (void) priority_node;
     49  (void) queue_context;
    4650}
  • cpukit/score/src/scheduleredfchangepriority.c

    r8c83cbc r300f6a48  
    5555  priority = _Scheduler_Node_get_priority( &node->Base, &prepend_it );
    5656
    57   if ( priority == node->current_priority ) {
     57  if ( priority == node->priority ) {
    5858    /* Nothing to do */
    5959    SCHEDULER_RETURN_VOID_OR_NULL;
    6060  }
    6161
    62   if ( ( priority & SCHEDULER_EDF_PRIO_MSB ) != 0 ) {
    63     node->background_priority = priority;
    64   }
    65 
    66   node->current_priority = priority;
     62  node->priority = priority;
    6763  context = _Scheduler_EDF_Get_context( scheduler );
    6864
  • cpukit/score/src/scheduleredfnodeinit.c

    r8c83cbc r300f6a48  
    3030  Scheduler_EDF_Node *the_node;
    3131
    32   (void) scheduler;
    33 
    34   _Scheduler_Node_do_initialize( node, the_thread, priority );
     32  _Scheduler_Node_do_initialize( scheduler, node, the_thread, priority );
    3533
    3634  the_node = _Scheduler_EDF_Node_downcast( node );
    37   the_node->thread = the_thread;
    3835  _RBTree_Initialize_node( &the_node->Node );
     36  the_node->priority = priority;
    3937}
  • cpukit/score/src/scheduleredfreleasejob.c

    r8c83cbc r300f6a48  
    2121#include <rtems/score/scheduleredfimpl.h>
    2222
    23 static bool _Scheduler_EDF_Release_job_filter(
    24   Thread_Control   *the_thread,
    25   Priority_Control *new_priority_p,
    26   void             *arg
     23void _Scheduler_EDF_Release_job(
     24  const Scheduler_Control *scheduler,
     25  Thread_Control          *the_thread,
     26  Priority_Node           *priority_node,
     27  uint64_t                 deadline,
     28  Thread_queue_Context    *queue_context
    2729)
    2830{
    29   Scheduler_EDF_Node *node;
    30   Priority_Control    current_priority;
    31   Priority_Control    new_priority;
     31  (void) scheduler;
    3232
    33   node = _Scheduler_EDF_Thread_get_node( the_thread );
     33  _Thread_Wait_acquire_critical( the_thread, queue_context );
    3434
    35   current_priority = _Thread_Get_priority( the_thread );
    36   new_priority = *new_priority_p;
     35  _Priority_Node_set_priority( priority_node, deadline );
    3736
    38   node->current_priority = new_priority;
    39   the_thread->real_priority = new_priority;
     37  if ( _Priority_Node_is_active( priority_node ) ) {
     38    _Thread_Priority_changed(
     39      the_thread,
     40      priority_node,
     41      false,
     42      queue_context
     43    );
     44  } else {
     45    _Thread_Priority_add( the_thread, priority_node, queue_context );
     46  }
    4047
    41   return _Thread_Priority_less_than( current_priority, new_priority )
    42     || !_Thread_Owns_resources( the_thread );
     48  _Thread_Wait_release_critical( the_thread, queue_context );
    4349}
    4450
    45 Thread_Control *_Scheduler_EDF_Release_job(
     51void _Scheduler_EDF_Cancel_job(
    4652  const Scheduler_Control *scheduler,
    4753  Thread_Control          *the_thread,
    48   uint64_t                 deadline
     54  Priority_Node           *priority_node,
     55  Thread_queue_Context    *queue_context
    4956)
    5057{
    51   return _Thread_Apply_priority(
    52     the_thread,
    53     deadline,
    54     NULL,
    55     _Scheduler_EDF_Release_job_filter,
    56     true
    57   );
     58  (void) scheduler;
     59
     60  _Thread_Wait_acquire_critical( the_thread, queue_context );
     61
     62  _Thread_Priority_remove( the_thread, priority_node, queue_context );
     63  _Priority_Node_set_inactive( priority_node );
     64
     65  _Thread_Wait_release_critical( the_thread, queue_context );
    5866}
    59 
    60 static bool _Scheduler_EDF_Cancel_job_filter(
    61   Thread_Control   *the_thread,
    62   Priority_Control *new_priority_p,
    63   void             *arg
    64 )
    65 {
    66   Scheduler_EDF_Node *node;
    67   Priority_Control    current_priority;
    68   Priority_Control    new_priority;
    69 
    70   node = _Scheduler_EDF_Thread_get_node( the_thread );
    71 
    72   current_priority = _Thread_Get_priority( the_thread );
    73   new_priority = node->background_priority;
    74 
    75   node->current_priority = new_priority;
    76   the_thread->real_priority = new_priority;
    77 
    78   return _Thread_Priority_less_than( current_priority, new_priority )
    79     || !_Thread_Owns_resources( the_thread );
    80 }
    81 
    82 Thread_Control *_Scheduler_EDF_Cancel_job(
    83   const Scheduler_Control *scheduler,
    84   Thread_Control          *the_thread
    85 )
    86 {
    87   return _Thread_Apply_priority(
    88     the_thread,
    89     0,
    90     NULL,
    91     _Scheduler_EDF_Cancel_job_filter,
    92     true
    93   );
    94 }
  • cpukit/score/src/scheduleredfunblock.c

    r8c83cbc r300f6a48  
    3838  (void) prepend_it;
    3939
    40   node->current_priority = priority;
     40  node->priority = priority;
    4141  _Scheduler_EDF_Enqueue( context, node, priority );
    4242
  • cpukit/score/src/scheduleredfyield.c

    r8c83cbc r300f6a48  
    3434
    3535  _Scheduler_EDF_Extract( context, node );
    36   _Scheduler_EDF_Enqueue( context, node, node->current_priority );
     36  _Scheduler_EDF_Enqueue( context, node, node->priority );
    3737  _Scheduler_EDF_Schedule_body( scheduler, the_thread, true );
    3838
  • cpukit/score/src/schedulerpriority.c

    r8c83cbc r300f6a48  
    4444  Scheduler_priority_Node    *the_node;
    4545
    46   _Scheduler_Node_do_initialize( node, the_thread, priority );
     46  _Scheduler_Node_do_initialize( scheduler, node, the_thread, priority );
    4747
    4848  context = _Scheduler_priority_Get_context( scheduler );
  • cpukit/score/src/schedulerprioritysmp.c

    r8c83cbc r300f6a48  
    5858
    5959  the_node = _Scheduler_priority_SMP_Node_downcast( node );
    60   _Scheduler_SMP_Node_initialize( &the_node->Base, the_thread, priority );
     60  _Scheduler_SMP_Node_initialize(
     61    scheduler,
     62    &the_node->Base,
     63    the_thread,
     64    priority
     65  );
    6166
    6267  context = _Scheduler_Get_context( scheduler );
  • cpukit/score/src/schedulersimplesmp.c

    r8c83cbc r300f6a48  
    5353
    5454  the_node = _Scheduler_SMP_Node_downcast( node );
    55   _Scheduler_SMP_Node_initialize( the_node, the_thread, priority );
     55  _Scheduler_SMP_Node_initialize( scheduler, the_node, the_thread, priority );
    5656}
    5757
  • cpukit/score/src/schedulerstrongapa.c

    r8c83cbc r300f6a48  
    184184
    185185  the_node = _Scheduler_strong_APA_Node_downcast( node );
    186   _Scheduler_SMP_Node_initialize( &the_node->Base, the_thread, priority );
     186  _Scheduler_SMP_Node_initialize(
     187    scheduler,
     188    &the_node->Base,
     189    the_thread,
     190    priority
     191  );
    187192
    188193  context = _Scheduler_Get_context( scheduler );
  • cpukit/score/src/thread.c

    r8c83cbc r300f6a48  
    3333THREAD_OFFSET_ASSERT( Join_queue );
    3434THREAD_OFFSET_ASSERT( current_state );
    35 THREAD_OFFSET_ASSERT( current_priority );
    36 THREAD_OFFSET_ASSERT( real_priority );
    37 THREAD_OFFSET_ASSERT( priority_restore_hint );
     35THREAD_OFFSET_ASSERT( Real_priority );
    3836THREAD_OFFSET_ASSERT( resource_count );
    3937THREAD_OFFSET_ASSERT( Scheduler );
  • cpukit/score/src/threadchangepriority.c

    r8c83cbc r300f6a48  
    1111 *  On-Line Applications Research Corporation (OAR).
    1212 *
     13 *  Copyright (c) 2013, 2016 embedded brains GmbH
     14 *
    1315 *  The license and distribution terms for this file may be
    1416 *  found in the file LICENSE in this distribution or at
     
    2123
    2224#include <rtems/score/threadimpl.h>
     25#include <rtems/score/assert.h>
    2326#include <rtems/score/schedulerimpl.h>
    2427
    25 static Thread_Control *_Thread_Apply_priority_locked(
     28static void _Thread_Set_scheduler_node_priority(
     29  Priority_Aggregation *priority_aggregation,
     30  bool                  prepend_it
     31)
     32{
     33  _Scheduler_Node_set_priority(
     34    SCHEDULER_NODE_OF_WAIT_PRIORITY_NODE( priority_aggregation ),
     35    _Priority_Get_priority( priority_aggregation ),
     36    prepend_it
     37  );
     38}
     39
     40#if defined(RTEMS_SMP)
     41static void _Thread_Priority_action_add(
     42  Priority_Aggregation *priority_aggregation,
     43  Priority_Actions     *priority_actions,
     44  void                 *arg
     45)
     46{
     47  _Thread_Set_scheduler_node_priority( priority_aggregation, false );
     48  _Priority_Set_action_type( priority_aggregation, PRIORITY_ACTION_ADD );
     49  _Priority_Actions_add( priority_actions, priority_aggregation );
     50}
     51
     52static void _Thread_Priority_action_remove(
     53  Priority_Aggregation *priority_aggregation,
     54  Priority_Actions     *priority_actions,
     55  void                 *arg
     56)
     57{
     58  _Thread_Set_scheduler_node_priority( priority_aggregation, true );
     59  _Priority_Set_action_type( priority_aggregation, PRIORITY_ACTION_REMOVE );
     60  _Priority_Actions_add( priority_actions, priority_aggregation );
     61}
     62#endif
     63
     64static void _Thread_Priority_action_change(
     65  Priority_Aggregation *priority_aggregation,
     66  bool                  prepend_it,
     67  Priority_Actions     *priority_actions,
     68  void                 *arg
     69)
     70{
     71  _Thread_Set_scheduler_node_priority( priority_aggregation, prepend_it );
     72#if defined(RTEMS_SMP) || defined(RTEMS_DEBUG)
     73  _Priority_Set_action_type( priority_aggregation, PRIORITY_ACTION_CHANGE );
     74#endif
     75  _Priority_Actions_add( priority_actions, priority_aggregation );
     76}
     77
     78static void _Thread_Priority_do_perform_actions(
    2679  Thread_Control                *the_thread,
    27   Priority_Control               new_priority,
    28   void                          *arg,
    29   Thread_Change_priority_filter  filter,
     80  Thread_queue_Queue            *queue,
     81  const Thread_queue_Operations *operations,
    3082  bool                           prepend_it,
    3183  Thread_queue_Context          *queue_context
    3284)
    3385{
     86  Priority_Aggregation *priority_aggregation;
     87
     88  _Assert( !_Priority_Actions_is_empty( &queue_context->Priority.Actions ) );
     89  priority_aggregation = _Priority_Actions_move( &queue_context->Priority.Actions );
     90
     91  do {
     92    Priority_Aggregation *next_aggregation;
     93    Priority_Node        *priority_action_node;
     94    Priority_Action_type  priority_action_type;
     95
     96    next_aggregation = _Priority_Get_next_action( priority_aggregation );
     97
     98    priority_action_node = priority_aggregation->Action.node;
     99    priority_action_type = priority_aggregation->Action.type;
     100
     101    switch ( priority_action_type ) {
     102      case PRIORITY_ACTION_ADD:
     103#if defined(RTEMS_SMP)
     104        _Priority_Insert(
     105          priority_aggregation,
     106          priority_action_node,
     107          &queue_context->Priority.Actions,
     108          _Thread_Priority_action_add,
     109          _Thread_Priority_action_change,
     110          NULL
     111        );
     112#else
     113        _Priority_Non_empty_insert(
     114          priority_aggregation,
     115          priority_action_node,
     116          &queue_context->Priority.Actions,
     117          _Thread_Priority_action_change,
     118          NULL
     119        );
     120#endif
     121        break;
     122      case PRIORITY_ACTION_REMOVE:
     123#if defined(RTEMS_SMP)
     124        _Priority_Extract(
     125          priority_aggregation,
     126          priority_action_node,
     127          &queue_context->Priority.Actions,
     128          _Thread_Priority_action_remove,
     129          _Thread_Priority_action_change,
     130          NULL
     131        );
     132#else
     133        _Priority_Extract_non_empty(
     134          priority_aggregation,
     135          priority_action_node,
     136          &queue_context->Priority.Actions,
     137          _Thread_Priority_action_change,
     138          NULL
     139        );
     140#endif
     141        break;
     142      default:
     143        _Assert( priority_action_type == PRIORITY_ACTION_CHANGE );
     144        _Priority_Changed(
     145          priority_aggregation,
     146          priority_action_node,
     147          prepend_it,
     148          &queue_context->Priority.Actions,
     149          _Thread_Priority_action_change,
     150          NULL
     151        );
     152        break;
     153    }
     154
     155    priority_aggregation = next_aggregation;
     156  } while ( _Priority_Actions_is_valid( priority_aggregation ) );
     157
     158  if ( !_Priority_Actions_is_empty( &queue_context->Priority.Actions ) ) {
     159    _Thread_queue_Context_add_priority_update( queue_context, the_thread );
     160    ( *operations->priority_actions )(
     161      queue,
     162      &queue_context->Priority.Actions
     163    );
     164  }
     165}
     166
     167void _Thread_Priority_perform_actions(
     168  Thread_Control       *start_of_path,
     169  Thread_queue_Context *queue_context
     170)
     171{
     172#if defined(RTEMS_SMP)
     173  Thread_queue_Link *link;
     174#endif
     175  Thread_Control    *the_thread;
     176  size_t             update_count;
     177
     178  _Assert( start_of_path != NULL );
     179
     180#if defined(RTEMS_SMP)
     181  link = &queue_context->Path.Start;
     182#endif
     183  the_thread = start_of_path;
     184  update_count = _Thread_queue_Context_save_priority_updates( queue_context );
     185
     186  while ( true ) {
     187    Thread_queue_Queue *queue;
     188
     189#if defined(RTEMS_SMP)
     190    _Assert( link->owner == the_thread );
     191    queue = link->Lock_context.Wait.queue;
     192#else
     193    queue = the_thread->Wait.queue;
     194#endif
     195
     196    _Thread_Priority_do_perform_actions(
     197      the_thread,
     198      queue,
     199      the_thread->Wait.operations,
     200      false,
     201      queue_context
     202    );
     203
     204    if ( _Priority_Actions_is_empty( &queue_context->Priority.Actions ) ) {
     205      return;
     206    }
     207
     208    _Assert( queue != NULL );
     209    the_thread = queue->owner;
     210    _Assert( the_thread != NULL );
     211
     212#if defined(RTEMS_SMP)
     213    link = THREAD_QUEUE_LINK_OF_PATH_NODE( _Chain_Next( &link->Path_node ) );
     214#endif
     215
     216    /*
     217     * In case the priority action list is non-empty, then the current thread
     218     * is enqueued on a thread queue.  There is no need to notify the scheduler
     219     * about a priority change, since it will pick up the new priority once it
     220     * is unblocked.  Restore the previous set of threads bound to update the
     221     * priority.
     222     */
     223    _Thread_queue_Context_restore_priority_updates(
     224      queue_context,
     225      update_count
     226    );
     227  }
     228}
     229
     230static void _Thread_Priority_apply(
     231  Thread_Control       *the_thread,
     232  Priority_Node        *priority_action_node,
     233  Thread_queue_Context *queue_context,
     234  bool                  prepend_it,
     235  Priority_Action_type  priority_action_type
     236)
     237{
     238  Scheduler_Node     *own_node;
     239  Thread_queue_Queue *queue;
     240
     241  own_node = _Thread_Scheduler_get_own_node( the_thread );
     242  _Priority_Actions_initialize_one(
     243    &queue_context->Priority.Actions,
     244    &own_node->Wait.Priority,
     245    priority_action_node,
     246    priority_action_type
     247  );
     248  queue = the_thread->Wait.queue;
     249  _Thread_Priority_do_perform_actions(
     250    the_thread,
     251    queue,
     252    the_thread->Wait.operations,
     253    prepend_it,
     254    queue_context
     255  );
     256
     257  if ( !_Priority_Actions_is_empty( &queue_context->Priority.Actions ) ) {
     258    _Thread_queue_Path_acquire_critical( queue, the_thread, queue_context );
     259    _Thread_Priority_perform_actions( queue->owner, queue_context );
     260    _Thread_queue_Path_release_critical( queue_context );
     261  }
     262}
     263
     264void _Thread_Priority_add(
     265  Thread_Control       *the_thread,
     266  Priority_Node        *priority_node,
     267  Thread_queue_Context *queue_context
     268)
     269{
     270  _Thread_Priority_apply(
     271    the_thread,
     272    priority_node,
     273    queue_context,
     274    false,
     275    PRIORITY_ACTION_ADD
     276  );
     277}
     278
     279void _Thread_Priority_remove(
     280  Thread_Control       *the_thread,
     281  Priority_Node        *priority_node,
     282  Thread_queue_Context *queue_context
     283)
     284{
     285  _Thread_Priority_apply(
     286    the_thread,
     287    priority_node,
     288    queue_context,
     289    true,
     290    PRIORITY_ACTION_REMOVE
     291  );
     292}
     293
     294void _Thread_Priority_changed(
     295  Thread_Control       *the_thread,
     296  Priority_Node        *priority_node,
     297  bool                  prepend_it,
     298  Thread_queue_Context *queue_context
     299)
     300{
     301  _Thread_Priority_apply(
     302    the_thread,
     303    priority_node,
     304    queue_context,
     305    prepend_it,
     306    PRIORITY_ACTION_CHANGE
     307  );
     308}
     309
     310void _Thread_Priority_replace(
     311  Thread_Control *the_thread,
     312  Priority_Node  *victim_node,
     313  Priority_Node  *replacement_node
     314)
     315{
     316  Scheduler_Node *own_node;
     317
     318  own_node = _Thread_Scheduler_get_own_node( the_thread );
     319  _Priority_Replace( &own_node->Wait.Priority, victim_node, replacement_node );
     320}
     321
     322void _Thread_Priority_update( Thread_queue_Context *queue_context )
     323{
     324  size_t i;
     325  size_t n;
     326
     327  n = queue_context->Priority.update_count;
     328
    34329  /*
    35    * For simplicity set the priority restore hint unconditionally since this is
    36    * an average case optimization.  Otherwise complicated atomic operations
    37    * would be necessary.  Synchronize with a potential read of the resource
    38    * count in the filter function.  See also _CORE_mutex_Surrender(),
    39    * _Thread_Set_priority_filter() and _Thread_Restore_priority_filter().
     330   * Update the priority of all threads of the set.  Do not care to clear the
     331   * set, since the thread queue context will soon get destroyed anyway.
    40332   */
    41   the_thread->priority_restore_hint = true;
    42   _Atomic_Fence( ATOMIC_ORDER_ACQ_REL );
    43 
    44   /*
    45    *  Do not bother recomputing all the priority related information if
    46    *  we are not REALLY changing priority.
    47    */
    48   if ( ( *filter )( the_thread, &new_priority, arg ) ) {
    49     _Scheduler_Thread_set_priority( the_thread, new_priority, prepend_it );
    50 
    51     ( *the_thread->Wait.operations->priority_change )(
    52       the_thread->Wait.queue,
    53       the_thread,
    54       new_priority
    55     );
    56   } else {
    57     the_thread = NULL;
    58   }
    59 
    60   return the_thread;
    61 }
    62 
    63 Thread_Control *_Thread_Apply_priority(
    64   Thread_Control                *the_thread,
    65   Priority_Control               new_priority,
    66   void                          *arg,
    67   Thread_Change_priority_filter  filter,
    68   bool                           prepend_it
    69 )
    70 {
    71   Thread_queue_Context  queue_context;
    72   Thread_Control       *the_thread_to_update;
    73 
    74   _Thread_Wait_acquire( the_thread, &queue_context );
    75   the_thread_to_update = _Thread_Apply_priority_locked(
    76     the_thread,
    77     new_priority,
    78     arg,
    79     filter,
    80     prepend_it,
    81     &queue_context
    82   );
    83   _Thread_Wait_release( the_thread, &queue_context );
    84   return the_thread_to_update;
    85 }
    86 
    87 void _Thread_Update_priority( Thread_Control *the_thread )
    88 {
    89   if ( the_thread != NULL ) {
    90     ISR_lock_Context lock_context;
    91 
     333  for ( i = 0; i < n ; ++i ) {
     334    Thread_Control   *the_thread;
     335    ISR_lock_Context  lock_context;
     336
     337    the_thread = queue_context->Priority.update[ i ];
    92338    _Thread_State_acquire( the_thread, &lock_context );
    93339    _Scheduler_Update_priority( the_thread );
     
    95341  }
    96342}
    97 
    98 void _Thread_Change_priority(
    99   Thread_Control                *the_thread,
    100   Priority_Control               new_priority,
    101   void                          *arg,
    102   Thread_Change_priority_filter  filter,
    103   bool                           prepend_it
    104 )
    105 {
    106   the_thread = _Thread_Apply_priority(
    107     the_thread,
    108     new_priority,
    109     arg,
    110     filter,
    111     prepend_it
    112   );
    113   _Thread_Update_priority( the_thread );
    114 }
    115 
    116 static bool _Thread_Raise_priority_filter(
    117   Thread_Control   *the_thread,
    118   Priority_Control *new_priority,
    119   void             *arg
    120 )
    121 {
    122   return _Thread_Priority_less_than(
    123     _Thread_Get_priority( the_thread ),
    124     *new_priority
    125   );
    126 }
    127 
    128 void _Thread_Raise_priority(
    129   Thread_Control   *the_thread,
    130   Priority_Control  new_priority
    131 )
    132 {
    133   _Thread_Change_priority(
    134     the_thread,
    135     new_priority,
    136     NULL,
    137     _Thread_Raise_priority_filter,
    138     false
    139   );
    140 }
    141 
    142 static bool _Thread_Restore_priority_filter(
    143   Thread_Control   *the_thread,
    144   Priority_Control *new_priority,
    145   void             *arg
    146 )
    147 {
    148   *new_priority = the_thread->real_priority;
    149 
    150   the_thread->priority_restore_hint = false;
    151 
    152   return *new_priority != _Thread_Get_priority( the_thread );
    153 }
    154 
    155 void _Thread_Restore_priority( Thread_Control *the_thread )
    156 {
    157   _Thread_Change_priority(
    158     the_thread,
    159     0,
    160     NULL,
    161     _Thread_Restore_priority_filter,
    162     true
    163   );
    164 }
  • cpukit/score/src/threadinitialize.c

    r8c83cbc r300f6a48  
    199199  the_thread->current_state           = STATES_DORMANT;
    200200  the_thread->Wait.operations         = &_Thread_queue_Operations_default;
    201   the_thread->current_priority        = priority;
    202   the_thread->real_priority           = priority;
    203201  the_thread->Start.initial_priority  = priority;
    204202
    205203  RTEMS_STATIC_ASSERT( THREAD_WAIT_FLAGS_INITIAL == 0, Wait_flags );
    206204
     205  _Priority_Node_initialize( &the_thread->Real_priority, priority );
     206  _Priority_Initialize_one(
     207    &scheduler_node->Wait.Priority,
     208    &the_thread->Real_priority
     209  );
    207210  _Scheduler_Node_initialize( scheduler, scheduler_node, the_thread, priority );
    208211  scheduler_node_initialized = true;
  • cpukit/score/src/threadmp.c

    r8c83cbc r300f6a48  
    8181    proxy->Scheduler.node = &proxy->Scheduler_node;
    8282    _Scheduler_Node_do_initialize(
     83      _Scheduler_Get_by_CPU_index( 0 ),
    8384      &proxy->Scheduler_node,
    8485      (Thread_Control *) proxy,
     
    151152    the_proxy->receive_packet = receive_packet;
    152153    the_proxy->Object.id = source_tid;
    153     the_proxy->current_priority = receive_packet->source_priority;
     154    the_proxy->Real_priority.priority = receive_packet->source_priority;
    154155    the_proxy->current_state = _States_Set( STATES_DORMANT, the_state );
    155156
  • cpukit/score/src/threadqenqueue.c

    r8c83cbc r300f6a48  
    163163#endif
    164164
    165 #define THREAD_QUEUE_LINK_OF_PATH_NODE( node ) \
    166   RTEMS_CONTAINER_OF( node, Thread_queue_Link, Path_node );
    167 
    168 static void _Thread_queue_Path_release( Thread_queue_Path *path )
     165void _Thread_queue_Path_release_critical(
     166  Thread_queue_Context *queue_context
     167)
    169168{
    170169#if defined(RTEMS_SMP)
     
    172171  Chain_Node *node;
    173172
    174   head = _Chain_Head( &path->Links );
    175   node = _Chain_Last( &path->Links );
     173  head = _Chain_Head( &queue_context->Path.Links );
     174  node = _Chain_Last( &queue_context->Path.Links );
    176175
    177176  if ( head != node ) {
     
    216215  }
    217216#else
    218   (void) path;
    219 #endif
    220 }
    221 
    222 static bool _Thread_queue_Path_acquire(
    223   Thread_Control     *the_thread,
    224   Thread_queue_Queue *queue,
    225   Thread_queue_Path  *path
     217  (void) queue_context;
     218#endif
     219}
     220
     221bool _Thread_queue_Path_acquire_critical(
     222  Thread_queue_Queue   *queue,
     223  Thread_Control       *the_thread,
     224  Thread_queue_Context *queue_context
    226225)
    227226{
    228227  Thread_Control     *owner;
    229 
    230228#if defined(RTEMS_SMP)
    231229  Thread_queue_Link  *link;
     
    240238   */
    241239
    242   _Chain_Initialize_empty( &path->Links );
     240  _Chain_Initialize_empty( &queue_context->Path.Links );
    243241
    244242  owner = queue->owner;
     
    252250  }
    253251
    254   _RBTree_Initialize_node( &path->Start.Registry_node );
    255   _Chain_Initialize_node( &path->Start.Path_node );
    256   _Chain_Initialize_node( &path->Start.Lock_context.Wait.Gate.Node );
    257   link = &path->Start;
     252  _RBTree_Initialize_node( &queue_context->Path.Start.Registry_node );
     253  _Chain_Initialize_node( &queue_context->Path.Start.Path_node );
     254  _Chain_Initialize_node(
     255    &queue_context->Path.Start.Lock_context.Wait.Gate.Node
     256  );
     257  link = &queue_context->Path.Start;
    258258
    259259  do {
    260     _Chain_Append_unprotected( &path->Links, &link->Path_node );
     260    _Chain_Append_unprotected( &queue_context->Path.Links, &link->Path_node );
    261261    link->owner = owner;
    262262
     
    294294      } else {
    295295        link->Lock_context.Wait.queue = NULL;
    296         _Thread_queue_Path_release( path );
    297296        return false;
    298297      }
     
    346345)
    347346{
    348   Thread_queue_Path  path;
    349   Per_CPU_Control   *cpu_self;
    350   bool               success;
     347  Per_CPU_Control *cpu_self;
     348  bool             success;
    351349
    352350#if defined(RTEMS_MULTIPROCESSING)
     
    358356  _Thread_Wait_claim( the_thread, queue, operations );
    359357
    360   if ( !_Thread_queue_Path_acquire( the_thread, queue, &path ) ) {
     358  if ( !_Thread_queue_Path_acquire_critical( queue, the_thread, queue_context ) ) {
     359    _Thread_queue_Path_release_critical( queue_context );
    361360    _Thread_Wait_restore_default( the_thread );
    362361    _Thread_queue_Queue_release( queue, &queue_context->Lock_context.Lock_context );
     
    366365  }
    367366
    368   ( *operations->enqueue )( queue, the_thread, &path );
    369 
    370   _Thread_queue_Path_release( &path );
     367  _Thread_queue_Context_clear_priority_updates( queue_context );
     368  ( *operations->enqueue )( queue, the_thread, queue_context );
     369
     370  _Thread_queue_Path_release_critical( queue_context );
    371371
    372372  the_thread->Wait.return_code = STATUS_SUCCESSFUL;
     
    438438  }
    439439
    440   _Thread_Update_priority( path.update_priority );
     440  _Thread_Priority_update( queue_context );
    441441  _Thread_Dispatch_enable( cpu_self );
    442442}
     
    489489}
    490490
    491 bool _Thread_queue_Do_extract_locked(
     491bool _Thread_queue_Extract_locked(
    492492  Thread_queue_Queue            *queue,
    493493  const Thread_queue_Operations *operations,
    494   Thread_Control                *the_thread
    495 #if defined(RTEMS_MULTIPROCESSING)
    496   ,
    497   const Thread_queue_Context    *queue_context
    498 #endif
     494  Thread_Control                *the_thread,
     495  Thread_queue_Context          *queue_context
    499496)
    500497{
     
    502499  _Thread_queue_MP_set_callout( the_thread, queue_context );
    503500#endif
    504   ( *operations->extract )( queue, the_thread );
     501  ( *operations->extract )( queue, the_thread, queue_context );
    505502  return _Thread_queue_Make_ready_again( the_thread );
    506503}
     
    588585void _Thread_queue_Surrender(
    589586  Thread_queue_Queue            *queue,
    590   const Thread_queue_Operations *operations,
    591587  Thread_queue_Heads            *heads,
    592588  Thread_Control                *previous_owner,
    593   bool                           keep_priority,
    594   Thread_queue_Context          *queue_context
    595 )
    596 {
    597   if ( heads != NULL ) {
    598     Thread_Control *new_owner;
    599     bool            unblock;
    600 
    601     new_owner = ( *operations->surrender )( queue, heads, previous_owner );
    602     queue->owner = new_owner;
     589  Thread_queue_Context          *queue_context,
     590  const Thread_queue_Operations *operations
     591)
     592{
     593  Thread_Control  *new_owner;
     594  bool             unblock;
     595  Per_CPU_Control *cpu_self;
     596
     597  _Assert( heads != NULL );
     598
     599  _Thread_queue_Context_clear_priority_updates( queue_context );
     600  new_owner = ( *operations->surrender )(
     601    queue,
     602    heads,
     603    previous_owner,
     604    queue_context
     605  );
     606  queue->owner = new_owner;
    603607
    604608#if defined(RTEMS_MULTIPROCESSING)
    605     if ( !_Thread_queue_MP_set_callout( new_owner, queue_context ) )
    606 #endif
    607     {
    608       ++new_owner->resource_count;
    609     }
    610 
    611     unblock = _Thread_queue_Make_ready_again( new_owner );
    612 
    613     _Thread_queue_Unblock_critical(
    614       unblock,
    615       queue,
    616       new_owner,
    617       &queue_context->Lock_context.Lock_context
    618     );
    619   } else {
    620     _Thread_queue_Queue_release( queue, &queue_context->Lock_context.Lock_context );
    621   }
    622 
    623   if ( !keep_priority ) {
    624     Per_CPU_Control *cpu_self;
    625 
    626     cpu_self = _Thread_Dispatch_disable();
    627     _Thread_Restore_priority( previous_owner );
    628     _Thread_Dispatch_enable( cpu_self );
    629   }
     609  if ( !_Thread_queue_MP_set_callout( new_owner, queue_context ) )
     610#endif
     611  {
     612    ++new_owner->resource_count;
     613  }
     614
     615  unblock = _Thread_queue_Make_ready_again( new_owner );
     616
     617  cpu_self = _Thread_Dispatch_disable_critical(
     618    &queue_context->Lock_context.Lock_context
     619  );
     620  _Thread_queue_Queue_release(
     621    queue,
     622    &queue_context->Lock_context.Lock_context
     623  );
     624
     625  _Thread_Priority_update( queue_context );
     626
     627  if ( unblock ) {
     628    _Thread_Remove_timer_and_unblock( new_owner, queue );
     629  }
     630
     631  _Thread_Dispatch_enable( cpu_self );
    630632}
    631633
  • cpukit/score/src/threadqflush.c

    r8c83cbc r300f6a48  
    100100      Scheduler_Node *scheduler_node;
    101101
    102       scheduler_node = _Scheduler_Thread_get_own_node( first );
    103       _Chain_Append_unprotected( &unblock, &scheduler_node->Wait.Node.Chain );
     102      scheduler_node = _Thread_Scheduler_get_own_node( first );
     103      _Chain_Append_unprotected(
     104        &unblock,
     105        &scheduler_node->Wait.Priority.Node.Node.Chain
     106      );
    104107    }
    105108
     
    124127
    125128      next = _Chain_Next( node );
    126       scheduler_node = SCHEDULER_NODE_OF_WAIT_CHAIN_NODE( node );
     129      scheduler_node = SCHEDULER_NODE_OF_WAIT_PRIORITY_NODE( node );
    127130      the_thread = _Scheduler_Node_get_owner( scheduler_node );
    128131      _Thread_Remove_timer_and_unblock( the_thread, queue );
  • cpukit/score/src/threadqops.c

    r8c83cbc r300f6a48  
    2323#include <rtems/score/schedulerimpl.h>
    2424
    25 static void _Thread_queue_Do_nothing_priority_change(
     25#define THREAD_QUEUE_CONTEXT_OF_PRIORITY_ACTIONS( priority_actions ) \
     26  RTEMS_CONTAINER_OF( \
     27    priority_actions, \
     28    Thread_queue_Context, \
     29    Priority.Actions \
     30  )
     31
     32#define THREAD_QUEUE_PRIORITY_QUEUE_OF_PRIORITY_AGGREGATION( \
     33  priority_aggregation \
     34) \
     35  RTEMS_CONTAINER_OF( \
     36    priority_aggregation, \
     37    Thread_queue_Priority_queue, \
     38    Queue \
     39  )
     40
     41static void _Thread_queue_Do_nothing_priority_actions(
    2642  Thread_queue_Queue *queue,
    27   Thread_Control     *the_thread,
    28   Priority_Control    new_priority
     43  Priority_Actions   *priority_actions
     44)
     45{
     46  (void) queue;
     47  _Priority_Actions_initialize_empty( priority_actions );
     48}
     49
     50static void _Thread_queue_Do_nothing_extract(
     51  Thread_queue_Queue   *queue,
     52  Thread_Control       *the_thread,
     53  Thread_queue_Context *queue_context
    2954)
    3055{
    3156  (void) queue;
    3257  (void) the_thread;
    33   (void) new_priority;
    34 }
    35 
    36 static void _Thread_queue_Do_nothing_extract(
    37   Thread_queue_Queue *queue,
    38   Thread_Control     *the_thread
    39 )
    40 {
    41   (void) queue;
    42   (void) the_thread;
    43 }
    44 
    45 static Thread_queue_Heads *_Thread_queue_Queue_enqueue(
    46   Thread_queue_Queue *queue,
    47   Thread_Control     *the_thread,
    48   void             ( *initialize )( Thread_queue_Heads *, Thread_Control * ),
    49   void             ( *enqueue )( Thread_queue_Heads *, Thread_Control * )
     58  (void) queue_context;
     59}
     60
     61static void _Thread_queue_Queue_enqueue(
     62  Thread_queue_Queue   *queue,
     63  Thread_Control       *the_thread,
     64  Thread_queue_Context *queue_context,
     65  void               ( *initialize )(
     66    Thread_queue_Queue *,
     67    Thread_Control *,
     68    Thread_queue_Context *,
     69    Thread_queue_Heads *
     70  ),
     71  void               ( *enqueue )(
     72    Thread_queue_Queue *,
     73    Thread_Control *,
     74    Thread_queue_Context *,
     75    Thread_queue_Heads *
     76  )
    5077)
    5178{
     
    6491    queue->heads = heads;
    6592    _Chain_Prepend_unprotected( &heads->Free_chain, &spare_heads->Free_node );
    66     ( *initialize )( heads, the_thread );
     93    ( *initialize )( queue, the_thread, queue_context, heads );
    6794  } else {
    6895    _Chain_Prepend_unprotected( &heads->Free_chain, &spare_heads->Free_node );
    69     ( *enqueue )( heads, the_thread );
    70   }
    71 
    72   return heads;
     96    ( *enqueue )( queue, the_thread, queue_context, heads );
     97  }
    7398}
    7499
    75100static void _Thread_queue_Queue_extract(
    76   Thread_queue_Queue *queue,
    77   Thread_queue_Heads *heads,
    78   Thread_Control     *the_thread,
    79   void             ( *extract )( Thread_queue_Heads *, Thread_Control * )
     101  Thread_queue_Queue   *queue,
     102  Thread_queue_Heads   *heads,
     103  Thread_Control       *current_or_previous_owner,
     104  Thread_queue_Context *queue_context,
     105  Thread_Control       *the_thread,
     106  void               ( *extract )(
     107    Thread_queue_Queue *,
     108    Thread_queue_Heads *,
     109    Thread_Control *,
     110    Thread_queue_Context *,
     111    Thread_Control *
     112  )
    80113)
    81114{
     
    92125  }
    93126
    94   ( *extract )( heads, the_thread );
     127  ( *extract )(
     128    queue,
     129    heads,
     130    current_or_previous_owner,
     131    queue_context,
     132    the_thread
     133  );
    95134}
    96135
    97136static void _Thread_queue_FIFO_do_initialize(
    98   Thread_queue_Heads *heads,
    99   Thread_Control     *the_thread
     137  Thread_queue_Queue   *queue,
     138  Thread_Control       *the_thread,
     139  Thread_queue_Context *queue_context,
     140  Thread_queue_Heads   *heads
    100141)
    101142{
    102143  Scheduler_Node *scheduler_node;
    103144
    104   scheduler_node = _Scheduler_Thread_get_own_node( the_thread );
    105 
    106   _Chain_Initialize_node( &scheduler_node->Wait.Node.Chain );
     145  scheduler_node = _Thread_Scheduler_get_own_node( the_thread );
     146
     147  _Chain_Initialize_node( &scheduler_node->Wait.Priority.Node.Node.Chain );
    107148  _Chain_Initialize_one(
    108149    &heads->Heads.Fifo,
    109     &scheduler_node->Wait.Node.Chain
     150    &scheduler_node->Wait.Priority.Node.Node.Chain
    110151  );
    111152}
    112153
    113154static void _Thread_queue_FIFO_do_enqueue(
    114   Thread_queue_Heads *heads,
    115   Thread_Control     *the_thread
     155  Thread_queue_Queue   *queue,
     156  Thread_Control       *the_thread,
     157  Thread_queue_Context *queue_context,
     158  Thread_queue_Heads   *heads
    116159)
    117160{
    118161  Scheduler_Node *scheduler_node;
    119162
    120   scheduler_node = _Scheduler_Thread_get_own_node( the_thread );
    121 
    122   _Chain_Initialize_node( &scheduler_node->Wait.Node.Chain );
     163  scheduler_node = _Thread_Scheduler_get_own_node( the_thread );
     164
     165  _Chain_Initialize_node( &scheduler_node->Wait.Priority.Node.Node.Chain );
    123166  _Chain_Append_unprotected(
    124167    &heads->Heads.Fifo,
    125     &scheduler_node->Wait.Node.Chain
     168    &scheduler_node->Wait.Priority.Node.Node.Chain
    126169  );
    127170}
    128171
    129172static void _Thread_queue_FIFO_do_extract(
    130   Thread_queue_Heads *heads,
    131   Thread_Control     *the_thread
     173  Thread_queue_Queue   *queue,
     174  Thread_queue_Heads   *heads,
     175  Thread_Control       *current_or_previous_owner,
     176  Thread_queue_Context *queue_context,
     177  Thread_Control       *the_thread
    132178)
    133179{
    134180  Scheduler_Node *scheduler_node;
    135181
    136   scheduler_node = _Scheduler_Thread_get_own_node( the_thread );
    137   _Chain_Extract_unprotected( &scheduler_node->Wait.Node.Chain );
     182  (void) current_or_previous_owner;
     183  (void) queue_context;
     184
     185  scheduler_node = _Thread_Scheduler_get_own_node( the_thread );
     186
     187  _Chain_Extract_unprotected( &scheduler_node->Wait.Priority.Node.Node.Chain );
    138188}
    139189
    140190static void _Thread_queue_FIFO_enqueue(
    141   Thread_queue_Queue *queue,
    142   Thread_Control     *the_thread,
    143   Thread_queue_Path  *path
    144 )
    145 {
    146   path->update_priority = NULL;
    147 
     191  Thread_queue_Queue   *queue,
     192  Thread_Control       *the_thread,
     193  Thread_queue_Context *queue_context
     194)
     195{
    148196  _Thread_queue_Queue_enqueue(
    149197    queue,
    150198    the_thread,
     199    queue_context,
    151200    _Thread_queue_FIFO_do_initialize,
    152201    _Thread_queue_FIFO_do_enqueue
     
    155204
    156205static void _Thread_queue_FIFO_extract(
    157   Thread_queue_Queue *queue,
    158   Thread_Control     *the_thread
     206  Thread_queue_Queue   *queue,
     207  Thread_Control       *the_thread,
     208  Thread_queue_Context *queue_context
    159209)
    160210{
     
    162212    queue,
    163213    queue->heads,
     214    NULL,
     215    queue_context,
    164216    the_thread,
    165217    _Thread_queue_FIFO_do_extract
     
    178230  _Assert( !_Chain_Is_empty( fifo ) );
    179231  first = _Chain_First( fifo );
    180   scheduler_node = SCHEDULER_NODE_OF_WAIT_CHAIN_NODE( first );
     232  scheduler_node = SCHEDULER_NODE_OF_WAIT_PRIORITY_NODE( first );
    181233
    182234  return _Scheduler_Node_get_owner( scheduler_node );
     
    184236
    185237static Thread_Control *_Thread_queue_FIFO_surrender(
    186   Thread_queue_Queue *queue,
    187   Thread_queue_Heads *heads,
    188   Thread_Control     *previous_owner
     238  Thread_queue_Queue   *queue,
     239  Thread_queue_Heads   *heads,
     240  Thread_Control       *previous_owner,
     241  Thread_queue_Context *queue_context
    189242)
    190243{
     
    195248    queue,
    196249    heads,
     250    NULL,
     251    queue_context,
    197252    first,
    198253    _Thread_queue_FIFO_do_extract
     
    204259static Thread_queue_Priority_queue *_Thread_queue_Priority_queue(
    205260  Thread_queue_Heads   *heads,
    206   const Thread_Control *the_thread
     261  const Scheduler_Node *scheduler_node
    207262)
    208263{
    209264#if defined(RTEMS_SMP)
    210   return &heads->Priority[
    211     _Scheduler_Get_index( _Scheduler_Get_own( the_thread ) )
    212   ];
     265  const Scheduler_Control *scheduler;
     266
     267  scheduler = _Priority_Get_scheduler( &scheduler_node->Wait.Priority );
     268  return &heads->Priority[ _Scheduler_Get_index( scheduler ) ];
    213269#else
    214   (void) the_thread;
    215 
     270  (void) scheduler_node;
    216271  return &heads->Heads.Priority;
    217272#endif
    218273}
    219274
    220 static bool _Thread_queue_Priority_less(
    221   const void        *left,
    222   const RBTree_Node *right
    223 )
    224 {
    225   const Priority_Control *the_left;
    226   const Scheduler_Node   *scheduler_node;
    227   const Thread_Control   *the_right;
    228 
    229   the_left = left;
    230   scheduler_node = SCHEDULER_NODE_OF_WAIT_RBTREE_NODE( right );
    231   the_right = _Scheduler_Node_get_owner( scheduler_node );
    232 
    233   return *the_left < _Thread_Get_priority( the_right );
    234 }
    235 
    236 static void _Thread_queue_Priority_priority_change(
     275static void _Thread_queue_Priority_priority_actions(
    237276  Thread_queue_Queue *queue,
    238   Thread_Control     *the_thread,
    239   Priority_Control    new_priority
    240 )
    241 {
    242   Thread_queue_Heads          *heads;
    243   Thread_queue_Priority_queue *priority_queue;
    244   Scheduler_Node              *scheduler_node;
     277  Priority_Actions   *priority_actions
     278)
     279{
     280  Thread_queue_Heads   *heads;
     281  Priority_Aggregation *priority_aggregation;
    245282
    246283  heads = queue->heads;
    247284  _Assert( heads != NULL );
    248285
    249   priority_queue = _Thread_queue_Priority_queue( heads, the_thread );
    250   scheduler_node = _Scheduler_Thread_get_own_node( the_thread );
    251 
    252   _RBTree_Extract(
    253     &priority_queue->Queue,
    254     &scheduler_node->Wait.Node.RBTree
    255   );
    256   _RBTree_Insert_inline(
    257     &priority_queue->Queue,
    258     &scheduler_node->Wait.Node.RBTree,
    259     &new_priority,
    260     _Thread_queue_Priority_less
    261   );
     286  _Assert( !_Priority_Actions_is_empty( priority_actions ) );
     287  priority_aggregation = _Priority_Actions_move( priority_actions );
     288
     289  do {
     290    Scheduler_Node              *scheduler_node;
     291    Thread_queue_Priority_queue *priority_queue;
     292
     293    scheduler_node = SCHEDULER_NODE_OF_WAIT_PRIORITY( priority_aggregation );
     294    priority_queue = _Thread_queue_Priority_queue( heads, scheduler_node );
     295
     296    _Assert( priority_aggregation->Action.type == PRIORITY_ACTION_CHANGE );
     297    _Priority_Plain_changed(
     298      &priority_queue->Queue,
     299      &scheduler_node->Wait.Priority.Node
     300    );
     301
     302    priority_aggregation = _Priority_Get_next_action( priority_aggregation );
     303  } while ( _Priority_Actions_is_valid( priority_aggregation ) );
    262304}
    263305
    264306static void _Thread_queue_Priority_do_initialize(
    265   Thread_queue_Heads *heads,
    266   Thread_Control     *the_thread
    267 )
    268 {
     307  Thread_queue_Queue   *queue,
     308  Thread_Control       *the_thread,
     309  Thread_queue_Context *queue_context,
     310  Thread_queue_Heads   *heads
     311)
     312{
     313  Scheduler_Node              *scheduler_node;
    269314  Thread_queue_Priority_queue *priority_queue;
    270   Scheduler_Node              *scheduler_node;
    271 
    272   priority_queue = _Thread_queue_Priority_queue( heads, the_thread );
     315
     316  scheduler_node = _Thread_Scheduler_get_own_node( the_thread );
     317  priority_queue = _Thread_queue_Priority_queue( heads, scheduler_node );
    273318
    274319#if defined(RTEMS_SMP)
     
    276321#endif
    277322
    278   scheduler_node = _Scheduler_Thread_get_own_node( the_thread );
    279 
    280   _RBTree_Initialize_node( &scheduler_node->Wait.Node.RBTree );
    281   _RBTree_Initialize_one(
     323  _Priority_Initialize_one(
    282324    &priority_queue->Queue,
    283     &scheduler_node->Wait.Node.RBTree
     325    &scheduler_node->Wait.Priority.Node
    284326  );
    285327}
    286328
    287329static void _Thread_queue_Priority_do_enqueue(
    288   Thread_queue_Heads *heads,
    289   Thread_Control     *the_thread
    290 )
    291 {
     330  Thread_queue_Queue   *queue,
     331  Thread_Control       *the_thread,
     332  Thread_queue_Context *queue_context,
     333  Thread_queue_Heads   *heads
     334)
     335{
     336  Scheduler_Node              *scheduler_node;
    292337  Thread_queue_Priority_queue *priority_queue;
     338
     339  scheduler_node = _Thread_Scheduler_get_own_node( the_thread );
     340  priority_queue = _Thread_queue_Priority_queue( heads, scheduler_node );
     341
     342#if defined(RTEMS_SMP)
     343  if ( _Priority_Is_empty( &priority_queue->Queue ) ) {
     344    _Chain_Append_unprotected( &heads->Heads.Fifo, &priority_queue->Node );
     345    _Priority_Initialize_one(
     346      &priority_queue->Queue,
     347      &scheduler_node->Wait.Priority.Node
     348    );
     349    return;
     350  }
     351#endif
     352
     353  _Priority_Plain_insert(
     354    &priority_queue->Queue,
     355    &scheduler_node->Wait.Priority.Node,
     356    _Priority_Get_priority( &scheduler_node->Wait.Priority )
     357  );
     358}
     359
     360static void _Thread_queue_Priority_do_extract(
     361  Thread_queue_Queue   *queue,
     362  Thread_queue_Heads   *heads,
     363  Thread_Control       *current_or_previous_owner,
     364  Thread_queue_Context *queue_context,
     365  Thread_Control       *the_thread
     366)
     367{
    293368  Scheduler_Node              *scheduler_node;
    294   Priority_Control             current_priority;
    295 
    296   priority_queue = _Thread_queue_Priority_queue( heads, the_thread );
    297 
    298 #if defined(RTEMS_SMP)
    299   if ( _RBTree_Is_empty( &priority_queue->Queue ) ) {
    300     _Chain_Append_unprotected( &heads->Heads.Fifo, &priority_queue->Node );
    301   }
    302 #endif
    303 
    304   scheduler_node = _Scheduler_Thread_get_own_node( the_thread );
    305   current_priority = _Thread_Get_priority( the_thread );
    306 
    307   _RBTree_Initialize_node( &scheduler_node->Wait.Node.RBTree );
    308   _RBTree_Insert_inline(
     369  Thread_queue_Priority_queue *priority_queue;
     370
     371  (void) current_or_previous_owner;
     372  (void) queue_context;
     373
     374  scheduler_node = _Thread_Scheduler_get_own_node( the_thread );
     375  priority_queue = _Thread_queue_Priority_queue( heads, scheduler_node );
     376
     377  _Priority_Plain_extract(
    309378    &priority_queue->Queue,
    310     &scheduler_node->Wait.Node.RBTree,
    311     &current_priority,
    312     _Thread_queue_Priority_less
    313   );
    314 }
    315 
    316 static void _Thread_queue_Priority_do_extract(
    317   Thread_queue_Heads *heads,
    318   Thread_Control     *the_thread
    319 )
    320 {
    321   Thread_queue_Priority_queue *priority_queue;
    322   Scheduler_Node              *scheduler_node;
    323 
    324   priority_queue = _Thread_queue_Priority_queue( heads, the_thread );
    325   scheduler_node = _Scheduler_Thread_get_own_node( the_thread );
    326 
    327   _RBTree_Extract(
    328     &priority_queue->Queue,
    329     &scheduler_node->Wait.Node.RBTree
     379    &scheduler_node->Wait.Priority.Node
    330380  );
    331381
     
    333383  _Chain_Extract_unprotected( &priority_queue->Node );
    334384
    335   if ( !_RBTree_Is_empty( &priority_queue->Queue ) ) {
     385  if ( !_Priority_Is_empty( &priority_queue->Queue ) ) {
    336386    _Chain_Append_unprotected( &heads->Heads.Fifo, &priority_queue->Node );
    337387  }
     
    340390
    341391static void _Thread_queue_Priority_enqueue(
    342   Thread_queue_Queue *queue,
    343   Thread_Control     *the_thread,
    344   Thread_queue_Path  *path
    345 )
    346 {
    347   path->update_priority = NULL;
    348 
     392  Thread_queue_Queue   *queue,
     393  Thread_Control       *the_thread,
     394  Thread_queue_Context *queue_context
     395)
     396{
    349397  _Thread_queue_Queue_enqueue(
    350398    queue,
    351399    the_thread,
     400    queue_context,
    352401    _Thread_queue_Priority_do_initialize,
    353402    _Thread_queue_Priority_do_enqueue
     
    356405
    357406static void _Thread_queue_Priority_extract(
    358   Thread_queue_Queue *queue,
    359   Thread_Control     *the_thread
     407  Thread_queue_Queue   *queue,
     408  Thread_Control       *the_thread,
     409  Thread_queue_Context *queue_context
    360410)
    361411{
     
    363413    queue,
    364414    queue->heads,
     415    NULL,
     416    queue_context,
    365417    the_thread,
    366418    _Thread_queue_Priority_do_extract
     
    373425{
    374426  Thread_queue_Priority_queue *priority_queue;
    375   RBTree_Node                 *first;
     427  Priority_Node               *first;
    376428  Scheduler_Node              *scheduler_node;
    377429
     
    384436#endif
    385437
    386   _Assert( !_RBTree_Is_empty( &priority_queue->Queue ) );
    387   first = _RBTree_Minimum( &priority_queue->Queue );
    388   scheduler_node = SCHEDULER_NODE_OF_WAIT_RBTREE_NODE( first );
     438  _Assert( !_Priority_Is_empty( &priority_queue->Queue ) );
     439  first = _Priority_Get_minimum_node( &priority_queue->Queue );
     440  scheduler_node = SCHEDULER_NODE_OF_WAIT_PRIORITY_NODE( first );
    389441
    390442  return _Scheduler_Node_get_owner( scheduler_node );
     
    392444
    393445static Thread_Control *_Thread_queue_Priority_surrender(
    394   Thread_queue_Queue *queue,
    395   Thread_queue_Heads *heads,
    396   Thread_Control     *previous_owner
     446  Thread_queue_Queue   *queue,
     447  Thread_queue_Heads   *heads,
     448  Thread_Control       *previous_owner,
     449  Thread_queue_Context *queue_context
    397450)
    398451{
     
    403456    queue,
    404457    heads,
     458    NULL,
     459    queue_context,
    405460    first,
    406461    _Thread_queue_Priority_do_extract
     
    410465}
    411466
     467static void _Thread_queue_Priority_inherit_do_actions_change(
     468  Priority_Aggregation *priority_aggregation,
     469  bool                  prepend_it,
     470  Priority_Actions     *priority_actions,
     471  void                 *arg
     472)
     473{
     474  Thread_queue_Priority_queue *priority_queue;
     475  Scheduler_Node              *scheduler_node;
     476
     477  priority_queue = THREAD_QUEUE_PRIORITY_QUEUE_OF_PRIORITY_AGGREGATION(
     478    priority_aggregation
     479  );
     480  scheduler_node = priority_queue->scheduler_node;
     481
     482  _Priority_Set_action(
     483    &scheduler_node->Wait.Priority,
     484    &priority_aggregation->Node,
     485    PRIORITY_ACTION_CHANGE
     486  );
     487  _Priority_Actions_add( priority_actions, &scheduler_node->Wait.Priority );
     488}
     489
     490static void _Thread_queue_Priority_inherit_priority_actions(
     491  Thread_queue_Queue *queue,
     492  Priority_Actions   *priority_actions
     493)
     494{
     495  Thread_queue_Heads   *heads;
     496  Priority_Aggregation *priority_aggregation;
     497
     498  heads = queue->heads;
     499  _Assert( heads != NULL );
     500
     501  _Assert( !_Priority_Actions_is_empty( priority_actions ) );
     502  priority_aggregation = _Priority_Actions_move( priority_actions );
     503
     504  do {
     505    Priority_Aggregation        *next_aggregation;
     506    Scheduler_Node              *scheduler_node;
     507    Thread_queue_Priority_queue *priority_queue;
     508
     509    next_aggregation = _Priority_Get_next_action( priority_aggregation );
     510
     511    scheduler_node = SCHEDULER_NODE_OF_WAIT_PRIORITY( priority_aggregation );
     512    priority_queue = _Thread_queue_Priority_queue( heads, scheduler_node );
     513
     514    _Assert( priority_aggregation->Action.type == PRIORITY_ACTION_CHANGE );
     515    _Priority_Changed(
     516      &priority_queue->Queue,
     517      &scheduler_node->Wait.Priority.Node,
     518      false,
     519      priority_actions,
     520      _Thread_queue_Priority_inherit_do_actions_change,
     521      NULL
     522    );
     523
     524    priority_aggregation = next_aggregation;
     525  } while ( _Priority_Actions_is_valid( priority_aggregation ) );
     526}
     527
     528static void _Thread_queue_Boost_priority(
     529  Thread_queue_Heads   *heads,
     530  Thread_Control       *the_thread,
     531  Thread_Control       *owner,
     532  Thread_queue_Context *queue_context
     533)
     534{
     535#if defined(RTEMS_SMP)
     536  const Scheduler_Control *scheduler;
     537  const Scheduler_Control *scheduler_of_owner;
     538  Scheduler_Node          *scheduler_node_of_owner;
     539  Priority_Control         boost_priority;
     540
     541  if ( _Priority_Node_is_active( &heads->Boost_priority ) ) {
     542    return;
     543  }
     544
     545  scheduler = _Scheduler_Get_own( the_thread );
     546  scheduler_of_owner = _Scheduler_Get_own( owner );
     547
     548  if ( scheduler == scheduler_of_owner ) {
     549    return;
     550  }
     551
     552  scheduler_node_of_owner = _Thread_Scheduler_get_own_node( owner );
     553
     554  boost_priority = _Scheduler_Map_priority(
     555    scheduler_of_owner,
     556    PRIORITY_PSEUDO_ISR
     557  );
     558
     559  _Priority_Node_initialize( &heads->Boost_priority, boost_priority );
     560  _Priority_Actions_initialize_one(
     561    &queue_context->Priority.Actions,
     562    &scheduler_node_of_owner->Wait.Priority,
     563    &heads->Boost_priority,
     564    PRIORITY_ACTION_ADD
     565  );
     566  _Thread_Priority_perform_actions( owner, queue_context );
     567#else
     568  (void) heads;
     569  (void) the_thread;
     570  (void) owner;
     571  (void) queue_context;
     572#endif
     573}
     574
     575static void _Thread_queue_Priority_inherit_do_initialize(
     576  Thread_queue_Queue   *queue,
     577  Thread_Control       *the_thread,
     578  Thread_queue_Context *queue_context,
     579  Thread_queue_Heads   *heads
     580)
     581{
     582  Scheduler_Node              *scheduler_node;
     583  Thread_queue_Priority_queue *priority_queue;
     584  Thread_Control              *owner;
     585  Scheduler_Node              *scheduler_node_of_owner;
     586
     587  scheduler_node = _Thread_Scheduler_get_own_node( the_thread );
     588  priority_queue = _Thread_queue_Priority_queue( heads, scheduler_node );
     589
     590#if defined(RTEMS_SMP)
     591  _Chain_Initialize_one( &heads->Heads.Fifo, &priority_queue->Node );
     592#endif
     593
     594  _Priority_Initialize_one(
     595    &priority_queue->Queue,
     596    &scheduler_node->Wait.Priority.Node
     597  );
     598
     599  owner = queue->owner;
     600  scheduler_node_of_owner = _Thread_Scheduler_get_own_node( owner );
     601  priority_queue->scheduler_node = scheduler_node_of_owner;
     602
     603  _Priority_Actions_initialize_one(
     604    &queue_context->Priority.Actions,
     605    &scheduler_node_of_owner->Wait.Priority,
     606    &priority_queue->Queue.Node,
     607    PRIORITY_ACTION_ADD
     608  );
     609  _Thread_Priority_perform_actions( owner, queue_context );
     610  _Thread_queue_Boost_priority( heads, the_thread, owner, queue_context );
     611}
     612
     613static void _Thread_queue_Priority_inherit_do_enqueue_change(
     614  Priority_Aggregation *priority_aggregation,
     615  bool                  prepend_it,
     616  Priority_Actions     *priority_actions,
     617  void                 *arg
     618)
     619{
     620  Thread_queue_Queue   *queue;
     621  Thread_Control       *owner;
     622  Scheduler_Node       *scheduler_node_of_owner;
     623  Thread_queue_Context *queue_context;
     624
     625  queue = arg;
     626  owner = queue->owner;
     627  scheduler_node_of_owner = _Thread_Scheduler_get_own_node( owner );
     628  queue_context = THREAD_QUEUE_CONTEXT_OF_PRIORITY_ACTIONS( priority_actions );
     629
     630  _Priority_Actions_initialize_one(
     631    &queue_context->Priority.Actions,
     632    &scheduler_node_of_owner->Wait.Priority,
     633    &priority_aggregation->Node,
     634    PRIORITY_ACTION_CHANGE
     635  );
     636  _Thread_Priority_perform_actions( owner, queue_context );
     637}
     638
     639static void _Thread_queue_Priority_inherit_do_enqueue(
     640  Thread_queue_Queue   *queue,
     641  Thread_Control       *the_thread,
     642  Thread_queue_Context *queue_context,
     643  Thread_queue_Heads   *heads
     644)
     645{
     646  Scheduler_Node              *scheduler_node;
     647  Thread_queue_Priority_queue *priority_queue;
     648
     649  scheduler_node = _Thread_Scheduler_get_own_node( the_thread );
     650  priority_queue = _Thread_queue_Priority_queue( heads, scheduler_node );
     651
     652#if defined(RTEMS_SMP)
     653  if ( _Priority_Is_empty( &priority_queue->Queue ) ) {
     654    Thread_Control *owner;
     655    Scheduler_Node *scheduler_node_of_owner;
     656
     657    _Chain_Append_unprotected( &heads->Heads.Fifo, &priority_queue->Node );
     658    _Priority_Initialize_one(
     659      &priority_queue->Queue,
     660      &scheduler_node->Wait.Priority.Node
     661    );
     662
     663    owner = queue->owner;
     664    scheduler_node_of_owner = _Thread_Scheduler_get_own_node( owner );
     665    priority_queue->scheduler_node = scheduler_node_of_owner;
     666
     667    _Priority_Actions_initialize_one(
     668      &queue_context->Priority.Actions,
     669      &scheduler_node_of_owner->Wait.Priority,
     670      &priority_queue->Queue.Node,
     671      PRIORITY_ACTION_ADD
     672    );
     673    _Thread_Priority_perform_actions( owner, queue_context );
     674    _Thread_queue_Boost_priority( heads, the_thread, owner, queue_context );
     675    return;
     676  }
     677#endif
     678
     679  _Priority_Non_empty_insert(
     680    &priority_queue->Queue,
     681    &scheduler_node->Wait.Priority.Node,
     682    &queue_context->Priority.Actions,
     683    _Thread_queue_Priority_inherit_do_enqueue_change,
     684    queue
     685  );
     686  _Thread_queue_Boost_priority(
     687    heads,
     688    the_thread,
     689    queue->owner,
     690    queue_context
     691  );
     692}
     693
    412694static void _Thread_queue_Priority_inherit_enqueue(
    413   Thread_queue_Queue *queue,
    414   Thread_Control     *the_thread,
    415   Thread_queue_Path  *path
    416 )
    417 {
    418   Thread_queue_Heads *heads;
    419   Thread_Control     *owner;
    420   Priority_Control    priority;
    421 
    422   heads = _Thread_queue_Queue_enqueue(
     695  Thread_queue_Queue   *queue,
     696  Thread_Control       *the_thread,
     697  Thread_queue_Context *queue_context
     698)
     699{
     700  _Thread_queue_Queue_enqueue(
    423701    queue,
    424702    the_thread,
    425     _Thread_queue_Priority_do_initialize,
    426     _Thread_queue_Priority_do_enqueue
    427   );
    428 
    429   owner = queue->owner;
     703    queue_context,
     704    _Thread_queue_Priority_inherit_do_initialize,
     705    _Thread_queue_Priority_inherit_do_enqueue
     706  );
     707}
     708
     709static void _Thread_queue_Priority_inherit_do_extract_action(
     710  Priority_Actions     *priority_actions,
     711  Thread_Control       *owner,
     712  Priority_Node        *priority_action_node,
     713  Priority_Action_type  priority_action_type
     714)
     715{
     716  Thread_queue_Context *queue_context;
     717  Scheduler_Node       *scheduler_node_of_owner;
     718
     719  queue_context = THREAD_QUEUE_CONTEXT_OF_PRIORITY_ACTIONS( priority_actions );
     720  scheduler_node_of_owner = _Thread_Scheduler_get_own_node( owner );
     721
     722  _Priority_Actions_initialize_one(
     723    &queue_context->Priority.Actions,
     724    &scheduler_node_of_owner->Wait.Priority,
     725    priority_action_node,
     726    priority_action_type
     727  );
     728  _Thread_Priority_perform_actions( owner, queue_context );
     729}
     730
     731static void _Thread_queue_Priority_inherit_do_extract_remove(
     732  Priority_Aggregation *priority_aggregation,
     733  Priority_Actions     *priority_actions,
     734  void                 *arg
     735)
     736{
     737  _Thread_queue_Priority_inherit_do_extract_action(
     738    priority_actions,
     739    arg,
     740    &priority_aggregation->Node,
     741    PRIORITY_ACTION_REMOVE
     742  );
     743}
     744
     745static void _Thread_queue_Priority_inherit_do_extract_change(
     746  Priority_Aggregation *priority_aggregation,
     747  bool                  prepend_it,
     748  Priority_Actions     *priority_actions,
     749  void                 *arg
     750)
     751{
     752  _Thread_queue_Priority_inherit_do_extract_action(
     753    priority_actions,
     754    arg,
     755    &priority_aggregation->Node,
     756    PRIORITY_ACTION_CHANGE
     757  );
     758}
     759
     760static void _Thread_queue_Priority_inherit_do_extract(
     761  Thread_queue_Queue   *queue,
     762  Thread_queue_Heads   *heads,
     763  Thread_Control       *owner,
     764  Thread_queue_Context *queue_context,
     765  Thread_Control       *the_thread
     766)
     767{
     768  Scheduler_Node              *scheduler_node;
     769  Thread_queue_Priority_queue *priority_queue;
     770
     771  scheduler_node = _Thread_Scheduler_get_own_node( the_thread );
     772  priority_queue = _Thread_queue_Priority_queue( heads, scheduler_node );
     773
     774  _Thread_queue_Path_acquire_critical( queue, the_thread, queue_context );
     775
     776  _Priority_Extract(
     777    &priority_queue->Queue,
     778    &scheduler_node->Wait.Priority.Node,
     779    &queue_context->Priority.Actions,
     780    _Thread_queue_Priority_inherit_do_extract_remove,
     781    _Thread_queue_Priority_inherit_do_extract_change,
     782    owner
     783  );
    430784
    431785#if defined(RTEMS_SMP)
    432   if ( _Chain_Has_only_one_node( &heads->Heads.Fifo ) ) {
    433     priority = the_thread->current_priority;
    434   } else {
    435     priority = _Scheduler_Map_priority(
     786  _Chain_Extract_unprotected( &priority_queue->Node );
     787
     788  if ( !_Priority_Is_empty( &priority_queue->Queue ) ) {
     789    _Chain_Append_unprotected( &heads->Heads.Fifo, &priority_queue->Node );
     790  }
     791
     792  if (
     793    _Priority_Node_is_active( &heads->Boost_priority )
     794      && ( _Chain_Is_empty( &heads->Heads.Fifo )
     795        || _Chain_Has_only_one_node( &heads->Heads.Fifo ) )
     796  ) {
     797    _Thread_queue_Priority_inherit_do_extract_action(
     798      &queue_context->Priority.Actions,
     799      owner,
     800      &heads->Boost_priority,
     801      PRIORITY_ACTION_REMOVE
     802    );
     803    _Priority_Node_set_inactive( &heads->Boost_priority );
     804  }
     805#endif
     806
     807  _Thread_queue_Path_release_critical( queue_context );
     808}
     809
     810static void _Thread_queue_Priority_inherit_extract(
     811  Thread_queue_Queue   *queue,
     812  Thread_Control       *the_thread,
     813  Thread_queue_Context *queue_context
     814)
     815{
     816  _Thread_queue_Queue_extract(
     817    queue,
     818    queue->heads,
     819    queue->owner,
     820    queue_context,
     821    the_thread,
     822    _Thread_queue_Priority_inherit_do_extract
     823  );
     824}
     825
     826static void _Thread_queue_Priority_inherit_do_surrender_change(
     827  Priority_Aggregation *priority_aggregation,
     828  bool                  prepend_it,
     829  Priority_Actions     *priority_actions,
     830  void                 *arg
     831)
     832{
     833  _Thread_queue_Context_add_priority_update(
     834    THREAD_QUEUE_CONTEXT_OF_PRIORITY_ACTIONS( priority_actions ),
     835    arg
     836  );
     837  _Scheduler_Node_set_priority(
     838    SCHEDULER_NODE_OF_WAIT_PRIORITY( priority_aggregation ),
     839    _Priority_Get_priority( priority_aggregation ),
     840    prepend_it
     841  );
     842}
     843
     844static void _Thread_queue_Priority_add(
     845  Thread_Control       *the_thread,
     846  Priority_Aggregation *priority_aggregation,
     847  Priority_Node        *priority_node,
     848  Thread_queue_Context *queue_context
     849)
     850{
     851  _Priority_Non_empty_insert(
     852    priority_aggregation,
     853    priority_node,
     854    &queue_context->Priority.Actions,
     855    _Thread_queue_Priority_inherit_do_surrender_change,
     856    the_thread
     857  );
     858}
     859
     860static void _Thread_queue_Priority_remove(
     861  Thread_Control       *the_thread,
     862  Scheduler_Node       *scheduler_node,
     863  Priority_Node        *priority_node,
     864  Thread_queue_Context *queue_context
     865)
     866{
     867  _Priority_Extract_non_empty(
     868    &scheduler_node->Wait.Priority,
     869    priority_node,
     870    &queue_context->Priority.Actions,
     871    _Thread_queue_Priority_inherit_do_surrender_change,
     872    the_thread
     873  );
     874}
     875
     876static void _Thread_queue_Priority_inherit_do_surrender(
     877  Thread_queue_Queue   *queue,
     878  Thread_queue_Heads   *heads,
     879  Thread_Control       *previous_owner,
     880  Thread_queue_Context *queue_context,
     881  Thread_Control       *the_thread
     882)
     883{
     884  Scheduler_Node              *scheduler_node;
     885  Thread_queue_Priority_queue *priority_queue;
     886  ISR_lock_Context             lock_context;
     887
     888  scheduler_node = _Thread_Scheduler_get_own_node( the_thread );
     889  priority_queue = _Thread_queue_Priority_queue( heads, scheduler_node );
     890
     891  _Thread_Wait_acquire_default_critical( previous_owner, &lock_context );
     892
     893#if defined(RTEMS_SMP)
     894  if ( _Priority_Node_is_active( &heads->Boost_priority ) ) {
     895    _Thread_queue_Priority_remove(
     896      previous_owner,
     897      _Thread_Scheduler_get_own_node( previous_owner ),
     898      &heads->Boost_priority,
     899      queue_context
     900    );
     901    _Priority_Node_set_inactive( &heads->Boost_priority );
     902  }
     903#endif
     904
     905  _Thread_queue_Priority_remove(
     906    previous_owner,
     907    priority_queue->scheduler_node,
     908    &priority_queue->Queue.Node,
     909    queue_context
     910  );
     911
     912  _Thread_Wait_release_default_critical( previous_owner, &lock_context );
     913
     914  _Priority_Extract(
     915    &priority_queue->Queue,
     916    &scheduler_node->Wait.Priority.Node,
     917    NULL,
     918    _Priority_Remove_nothing,
     919    _Priority_Change_nothing,
     920    previous_owner
     921  );
     922
     923  if ( !_Priority_Is_empty( &priority_queue->Queue ) ) {
     924    priority_queue->scheduler_node = scheduler_node;
     925    _Thread_queue_Priority_add(
     926      the_thread,
     927      &scheduler_node->Wait.Priority,
     928      &priority_queue->Queue.Node,
     929      queue_context
     930    );
     931  }
     932
     933#if defined(RTEMS_SMP)
     934  _Chain_Extract_unprotected( &priority_queue->Node );
     935
     936  if ( !_Priority_Is_empty( &priority_queue->Queue ) ) {
     937    _Chain_Append_unprotected( &heads->Heads.Fifo, &priority_queue->Node );
     938  }
     939
     940  if (
     941    !_Chain_Is_empty( &heads->Heads.Fifo)
     942      && !_Chain_Has_only_one_node( &heads->Heads.Fifo)
     943  ) {
     944    Priority_Control boost_priority;
     945
     946    boost_priority = _Scheduler_Map_priority(
    436947      _Scheduler_Get_own( the_thread ),
    437948      PRIORITY_PSEUDO_ISR
    438949    );
    439   }
    440 #else
    441   (void) heads;
    442 
    443   priority = the_thread->current_priority;
    444 #endif
    445 
    446   if ( priority < owner->current_priority ) {
    447     path->update_priority = owner;
    448 
    449     owner->priority_restore_hint = true;
    450     _Atomic_Fence( ATOMIC_ORDER_ACQ_REL );
    451 
    452     _Scheduler_Thread_set_priority( owner, priority, false );
    453 
    454     ( *owner->Wait.operations->priority_change )(
    455       owner->Wait.queue,
    456       owner,
    457       priority
     950    _Priority_Node_initialize( &heads->Boost_priority, boost_priority );
     951    _Thread_queue_Priority_add(
     952      the_thread,
     953      &scheduler_node->Wait.Priority,
     954      &heads->Boost_priority,
     955      queue_context
    458956    );
    459   } else {
    460     path->update_priority = NULL;
    461   }
    462 }
    463 
    464 static void _Thread_queue_Boost_priority(
    465   Thread_queue_Heads *heads,
    466   Thread_Control     *the_thread
    467 )
    468 {
    469 #if defined(RTEMS_SMP)
    470   if ( !_Chain_Has_only_one_node( &heads->Heads.Fifo ) ) {
    471     const Scheduler_Control *scheduler;
    472     Priority_Control         boost_priority;
    473 
    474     the_thread->priority_restore_hint = true;
    475     _Atomic_Fence( ATOMIC_ORDER_ACQ_REL );
    476 
    477     scheduler = _Scheduler_Get_own( the_thread );
    478     boost_priority = _Scheduler_Map_priority( scheduler, PRIORITY_PSEUDO_ISR );
    479 
    480     _Scheduler_Thread_set_priority( the_thread, boost_priority, false );
    481   }
    482 #else
    483   (void) heads;
    484   (void) the_thread;
     957  }
    485958#endif
    486959}
    487960
    488961static Thread_Control *_Thread_queue_Priority_inherit_surrender(
    489   Thread_queue_Queue *queue,
    490   Thread_queue_Heads *heads,
    491   Thread_Control     *previous_owner
     962  Thread_queue_Queue   *queue,
     963  Thread_queue_Heads   *heads,
     964  Thread_Control       *previous_owner,
     965  Thread_queue_Context *queue_context
    492966)
    493967{
     
    495969
    496970  first = _Thread_queue_Priority_first( heads );
    497   _Thread_queue_Boost_priority( heads, first );
    498971  _Thread_queue_Queue_extract(
    499972    queue,
    500973    heads,
     974    previous_owner,
     975    queue_context,
    501976    first,
    502     _Thread_queue_Priority_do_extract
     977    _Thread_queue_Priority_inherit_do_surrender
    503978  );
    504979
     
    507982
    508983const Thread_queue_Operations _Thread_queue_Operations_default = {
    509   .priority_change = _Thread_queue_Do_nothing_priority_change,
     984  .priority_actions = _Thread_queue_Do_nothing_priority_actions,
    510985  .extract = _Thread_queue_Do_nothing_extract
    511986  /*
     
    517992
    518993const Thread_queue_Operations _Thread_queue_Operations_FIFO = {
    519   .priority_change = _Thread_queue_Do_nothing_priority_change,
     994  .priority_actions = _Thread_queue_Do_nothing_priority_actions,
    520995  .enqueue = _Thread_queue_FIFO_enqueue,
    521996  .extract = _Thread_queue_FIFO_extract,
     
    5251000
    5261001const Thread_queue_Operations _Thread_queue_Operations_priority = {
    527   .priority_change = _Thread_queue_Priority_priority_change,
     1002  .priority_actions = _Thread_queue_Priority_priority_actions,
    5281003  .enqueue = _Thread_queue_Priority_enqueue,
    5291004  .extract = _Thread_queue_Priority_extract,
     
    5331008
    5341009const Thread_queue_Operations _Thread_queue_Operations_priority_inherit = {
    535   .priority_change = _Thread_queue_Priority_priority_change,
     1010  .priority_actions = _Thread_queue_Priority_inherit_priority_actions,
    5361011  .enqueue = _Thread_queue_Priority_inherit_enqueue,
    537   .extract = _Thread_queue_Priority_extract,
     1012  .extract = _Thread_queue_Priority_inherit_extract,
    5381013  .surrender = _Thread_queue_Priority_inherit_surrender,
    5391014  .first = _Thread_queue_Priority_first
  • cpukit/score/src/threadrestart.c

    r8c83cbc r300f6a48  
    5151};
    5252
    53 static bool _Thread_Raise_real_priority_filter(
    54   Thread_Control   *the_thread,
    55   Priority_Control *new_priority_ptr,
    56   void             *arg
    57 )
    58 {
    59   Priority_Control real_priority;
    60   Priority_Control new_priority;
    61   Priority_Control current_priority;
    62 
    63   real_priority = the_thread->real_priority;
    64   new_priority = *new_priority_ptr;
    65   current_priority = _Thread_Get_priority( the_thread );
    66 
    67   new_priority = _Thread_Priority_highest( real_priority, new_priority );
    68   *new_priority_ptr = new_priority;
    69 
    70   the_thread->real_priority = new_priority;
    71 
    72   return _Thread_Priority_less_than( current_priority, new_priority );
    73 }
    74 
    7553static void _Thread_Raise_real_priority(
    7654  Thread_Control   *the_thread,
     
    7856)
    7957{
    80   _Thread_Change_priority(
    81     the_thread,
    82     priority,
    83     NULL,
    84     _Thread_Raise_real_priority_filter,
    85     false
    86   );
     58  Thread_queue_Context queue_context;
     59
     60  _Thread_queue_Context_clear_priority_updates( &queue_context );
     61  _Thread_Wait_acquire( the_thread, &queue_context );
     62
     63  if ( priority < the_thread->Real_priority.priority ) {
     64    _Thread_Priority_change(
     65      the_thread,
     66      &the_thread->Real_priority,
     67      priority,
     68      false,
     69      &queue_context
     70    );
     71  }
     72
     73  _Thread_Wait_release( the_thread, &queue_context );
     74  _Thread_Priority_update( &queue_context );
    8775}
    8876
     
    183171  _Scheduler_Node_destroy(
    184172    _Scheduler_Get( the_thread ),
    185     _Scheduler_Thread_get_own_node( the_thread )
     173    _Thread_Scheduler_get_own_node( the_thread )
    186174  );
    187175  _ISR_lock_Destroy( &the_thread->Timer.Lock );
     
    623611)
    624612{
    625   Per_CPU_Control  *cpu_self;
    626   Priority_Control  unused;
     613  Per_CPU_Control      *cpu_self;
     614  Thread_queue_Context  queue_context;
    627615
    628616  _Assert(
     
    647635  _Thread_State_release( executing, lock_context );
    648636
    649   _Thread_Set_priority(
     637  _Thread_queue_Context_clear_priority_updates( &queue_context );
     638  _Thread_Wait_acquire_default( executing, lock_context );
     639  _Thread_Priority_change(
    650640    executing,
     641    &executing->Real_priority,
    651642    executing->Start.initial_priority,
    652     &unused,
    653     true
    654   );
    655 
     643    false,
     644    &queue_context
     645  );
     646  _Thread_Wait_release_default( executing, lock_context );
     647
     648  _Thread_Priority_update( &queue_context );
    656649  _Thread_Dispatch_enable( cpu_self );
    657650  RTEMS_UNREACHABLE();
  • cpukit/score/src/threadtimeout.c

    r8c83cbc r300f6a48  
    3131
    3232  the_thread = RTEMS_CONTAINER_OF( watchdog, Thread_Control, Timer.Watchdog );
     33
     34  _Thread_queue_Context_clear_priority_updates( &queue_context );
    3335  _Thread_Wait_acquire( the_thread, &queue_context );
    3436
     
    6769
    6870  _Thread_Wait_release( the_thread, &queue_context );
     71  _Thread_Priority_update( &queue_context );
    6972
    7073  if ( unblock ) {
  • testsuites/smptests/smpmutex01/init.c

    r8c83cbc r300f6a48  
    316316  check_generations(ctx, B_5_0, A_2_1);
    317317  assert_prio(ctx, B_5_0, 5);
    318   assert_prio(ctx, A_2_1, 0);
     318  assert_prio(ctx, A_2_1, 2);
    319319  request(ctx, A_2_1, REQ_MTX_RELEASE);
    320320  check_generations(ctx, A_2_1, B_5_1);
    321   assert_prio(ctx, A_2_1, 2);
    322321  assert_prio(ctx, B_5_1, 5);
    323322  request(ctx, B_5_1, REQ_MTX_RELEASE);
  • testsuites/smptests/smpscheduler03/init.c

    r8c83cbc r300f6a48  
    4141static test_context test_instance;
    4242
    43 static bool change_priority_filter(
    44   Thread_Control   *thread,
    45   Priority_Control *new_priority,
    46   void             *arg
     43static void apply_priority(
     44  Thread_Control *thread,
     45  Priority_Control new_priority,
     46  bool prepend_it,
     47  Thread_queue_Context *queue_context
    4748)
    4849{
    49   return _Thread_Get_priority( thread ) != *new_priority;
     50  _Thread_queue_Context_clear_priority_updates(queue_context);
     51  _Thread_Wait_acquire(thread, queue_context);
     52  _Thread_Priority_change(
     53    thread,
     54    &thread->Real_priority,
     55    new_priority,
     56    prepend_it,
     57    queue_context
     58  );
     59  _Thread_Wait_release(thread, queue_context);
    5060}
    5161
    5262static void change_priority(
    53   Thread_Control   *thread,
    54   Priority_Control  new_priority,
    55   bool              prepend_it
     63  Thread_Control *thread,
     64  Priority_Control new_priority,
     65  bool prepend_it
    5666)
    5767{
    58   _Thread_Change_priority(
    59     thread,
    60     new_priority,
    61     NULL,
    62     change_priority_filter,
    63     prepend_it
    64   );
     68  Thread_queue_Context queue_context;
     69
     70  apply_priority(thread, new_priority, prepend_it, &queue_context);
     71  _Thread_Priority_update(&queue_context);
    6572}
    6673
     
    198205  ISR_lock_Context scheduler_lock_context;
    199206  Thread_Control *needs_help;
    200   Scheduler_Node *node;
    201 
    202   thread->current_priority = new_priority;
    203   node = _Scheduler_Thread_get_node(thread);
    204   _Scheduler_Node_set_priority(node, new_priority, prepend_it);
     207  Thread_queue_Context queue_context;
     208
     209  apply_priority(thread, new_priority, prepend_it, &queue_context);
    205210
    206211  _Thread_State_acquire( thread, &state_lock_context );
  • testsuites/sptests/spmutex01/init.c

    r8c83cbc r300f6a48  
    4242  REQ_MTX_0_RELEASE = RTEMS_EVENT_3,
    4343  REQ_MTX_1_OBTAIN = RTEMS_EVENT_4,
    44   REQ_MTX_1_RELEASE = RTEMS_EVENT_5,
    45   REQ_MTX_2_OBTAIN = RTEMS_EVENT_6,
    46   REQ_MTX_2_RELEASE = RTEMS_EVENT_7,
    47   REQ_MTX_C11_OBTAIN = RTEMS_EVENT_8,
    48   REQ_MTX_C11_RELEASE = RTEMS_EVENT_9,
    49   REQ_MTX_POSIX_OBTAIN = RTEMS_EVENT_10,
    50   REQ_MTX_POSIX_RELEASE = RTEMS_EVENT_11
     44  REQ_MTX_1_OBTAIN_TIMEOUT = RTEMS_EVENT_5,
     45  REQ_MTX_1_RELEASE = RTEMS_EVENT_6,
     46  REQ_MTX_2_OBTAIN = RTEMS_EVENT_7,
     47  REQ_MTX_2_RELEASE = RTEMS_EVENT_8,
     48  REQ_MTX_C11_OBTAIN = RTEMS_EVENT_9,
     49  REQ_MTX_C11_RELEASE = RTEMS_EVENT_10,
     50  REQ_MTX_POSIX_OBTAIN = RTEMS_EVENT_11,
     51  REQ_MTX_POSIX_RELEASE = RTEMS_EVENT_12
    5152} request_id;
    5253
     
    111112}
    112113
     114static void wait(void)
     115{
     116  rtems_status_code sc;
     117
     118  sc = rtems_task_wake_after(4);
     119  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
     120}
     121
    113122static rtems_event_set wait_for_events(void)
    114123{
     
    142151}
    143152
     153static void obtain_timeout(test_context *ctx, mutex_id id)
     154{
     155  rtems_status_code sc;
     156
     157  sc = rtems_semaphore_obtain(ctx->mtx[id], RTEMS_WAIT, 2);
     158  rtems_test_assert(sc == RTEMS_TIMEOUT);
     159}
     160
    144161static void obtain(test_context *ctx, mutex_id id)
    145162{
     
    250267}
    251268
     269static void change_prio(
     270  test_context *ctx,
     271  task_id id,
     272  rtems_task_priority prio
     273)
     274{
     275  rtems_status_code sc;
     276
     277  sc = rtems_task_set_priority(
     278    ctx->tasks[id],
     279    prio,
     280    &prio
     281  );
     282  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
     283}
     284
    252285static void helper(rtems_task_argument arg)
    253286{