[PATCH v2] score: Rework thread priority management

Sebastian Huber sebastian.huber at embedded-brains.de
Thu Sep 8 11:13:39 UTC 2016


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.
---
 cpukit/libmisc/capture/capture.h                   |   2 +-
 cpukit/libmisc/cpuuse/cpuusagetop.c                |   6 +-
 cpukit/posix/include/rtems/posix/pthreadimpl.h     |   2 +
 cpukit/posix/include/rtems/posix/threadsup.h       |   8 +-
 cpukit/posix/src/killinfo.c                        |   2 +-
 cpukit/posix/src/mutexsetprioceiling.c             |  13 +-
 cpukit/posix/src/pthread.c                         | 103 ++-
 cpukit/posix/src/pthreadcreate.c                   |  32 +-
 cpukit/posix/src/pthreadgetschedparam.c            |   2 +-
 cpukit/posix/src/pthreadsetschedparam.c            | 143 ++--
 cpukit/posix/src/pthreadsetschedprio.c             |  92 +--
 cpukit/rtems/include/rtems/rtems/ratemon.h         |   6 +
 cpukit/rtems/src/ratemoncancel.c                   |  12 +-
 cpukit/rtems/src/ratemoncreate.c                   |   2 +
 cpukit/rtems/src/ratemonperiod.c                   |  15 +-
 cpukit/rtems/src/semsetpriority.c                  |  18 +-
 cpukit/rtems/src/tasksetpriority.c                 |  95 +--
 cpukit/score/Makefile.am                           |   3 +-
 cpukit/score/include/rtems/score/coremutex.h       |   4 +-
 cpukit/score/include/rtems/score/coremuteximpl.h   | 148 ++--
 cpukit/score/include/rtems/score/mrsp.h            |  12 +-
 cpukit/score/include/rtems/score/mrspimpl.h        | 255 ++++---
 cpukit/score/include/rtems/score/priority.h        | 175 ++++-
 cpukit/score/include/rtems/score/priorityimpl.h    | 421 +++++++++++
 cpukit/score/include/rtems/score/scheduler.h       |  28 +-
 cpukit/score/include/rtems/score/schedulercbs.h    |  17 +-
 cpukit/score/include/rtems/score/scheduleredf.h    |  26 +-
 .../score/include/rtems/score/scheduleredfimpl.h   |  14 +-
 cpukit/score/include/rtems/score/schedulerimpl.h   |  86 ++-
 cpukit/score/include/rtems/score/schedulernode.h   |  19 +-
 .../score/include/rtems/score/schedulernodeimpl.h  |  18 +-
 .../score/include/rtems/score/schedulersmpimpl.h   |  11 +-
 cpukit/score/include/rtems/score/thread.h          |  53 +-
 cpukit/score/include/rtems/score/threadimpl.h      | 261 ++++---
 cpukit/score/include/rtems/score/threadq.h         | 109 ++-
 cpukit/score/include/rtems/score/threadqimpl.h     | 145 ++--
 cpukit/score/preinstall.am                         |   4 +
 cpukit/score/src/mutex.c                           |  21 +-
 cpukit/score/src/schedulercbs.c                    |  22 +-
 cpukit/score/src/schedulercbsnodeinit.c            |   1 +
 cpukit/score/src/schedulercbsreleasejob.c          |  40 +-
 cpukit/score/src/schedulercbsunblock.c             |  51 +-
 cpukit/score/src/schedulerdefaultnodeinit.c        |   4 +-
 cpukit/score/src/schedulerdefaultreleasejob.c      |  20 +-
 cpukit/score/src/scheduleredfchangepriority.c      |   8 +-
 cpukit/score/src/scheduleredfnodeinit.c            |   6 +-
 cpukit/score/src/scheduleredfreleasejob.c          |  84 +-
 cpukit/score/src/scheduleredfunblock.c             |   2 +-
 cpukit/score/src/scheduleredfyield.c               |   2 +-
 cpukit/score/src/schedulerpriority.c               |   2 +-
 cpukit/score/src/schedulerprioritysmp.c            |   7 +-
 cpukit/score/src/schedulersimplesmp.c              |   2 +-
 cpukit/score/src/schedulerstrongapa.c              |   7 +-
 cpukit/score/src/thread.c                          |   4 +-
 cpukit/score/src/threadchangepriority.c            | 373 ++++++---
 cpukit/score/src/threadinitialize.c                |   7 +-
 cpukit/score/src/threadmp.c                        |   3 +-
 cpukit/score/src/threadqenqueue.c                  | 120 +--
 cpukit/score/src/threadqflush.c                    |   9 +-
 cpukit/score/src/threadqops.c                      | 841 ++++++++++++++++-----
 cpukit/score/src/threadrestart.c                   |  61 +-
 cpukit/score/src/threadsetpriority.c               |  59 --
 cpukit/score/src/threadtimeout.c                   |   3 +
 testsuites/smptests/smpmutex01/init.c              |   3 +-
 testsuites/smptests/smpscheduler03/init.c          |  43 +-
 testsuites/sptests/spmutex01/init.c                | 141 +++-
 testsuites/sptests/spsem03/init.c                  |  30 +-
 testsuites/sptests/spsem03/spsem03.doc             |   4 +-
 68 files changed, 2834 insertions(+), 1508 deletions(-)
 create mode 100644 cpukit/score/include/rtems/score/priorityimpl.h
 delete mode 100644 cpukit/score/src/threadsetpriority.c

diff --git a/cpukit/libmisc/capture/capture.h b/cpukit/libmisc/capture/capture.h
index 0f3635c..5e3237d 100644
--- a/cpukit/libmisc/capture/capture.h
+++ b/cpukit/libmisc/capture/capture.h
@@ -888,7 +888,7 @@ rtems_capture_task_start_priority (rtems_tcb* tcb)
 static inline rtems_task_priority
 rtems_capture_task_real_priority (rtems_tcb* tcb)
 {
-  return tcb->real_priority;
+  return tcb->Real_priority.priority;
 }
 
 /**
diff --git a/cpukit/libmisc/cpuuse/cpuusagetop.c b/cpukit/libmisc/cpuuse/cpuusagetop.c
index ccf32de..38d5ca4 100644
--- a/cpukit/libmisc/cpuuse/cpuusagetop.c
+++ b/cpukit/libmisc/cpuuse/cpuusagetop.c
@@ -261,7 +261,7 @@ task_usage(Thread_Control* thread, void* arg)
               CPU_usage_Less_than(&usage, &data->usage[j]))
             continue;
         case RTEMS_TOP_SORT_REAL_PRI:
-          if (thread->real_priority > data->tasks[j]->real_priority)
+          if (thread->Real_priority.priority > data->tasks[j]->Real_priority.priority)
             continue;
         case RTEMS_TOP_SORT_CURRENT_PRI:
           if (
@@ -478,10 +478,10 @@ rtems_cpuusage_top_thread (rtems_task_argument arg)
         snprintf(name, sizeof(name) - 1, "(%p)", thread->Start.Entry.Kinds.Numeric.entry);
 
       rtems_printf(data->printer,
-                   " 0x%08" PRIx32 " | %-19s |  %3" PRId32 " |  %3" PRId32 "   | ",
+                   " 0x%08" PRIx32 " | %-19s |  %3" PRId64 " |  %3" PRId64 "   | ",
                    thread->Object.id,
                    name,
-                   thread->real_priority,
+                   thread->Real_priority.priority,
                    _Thread_Get_priority(thread));
 
       usage = data->usage[i];
diff --git a/cpukit/posix/include/rtems/posix/pthreadimpl.h b/cpukit/posix/include/rtems/posix/pthreadimpl.h
index 988246e..acf6682 100644
--- a/cpukit/posix/include/rtems/posix/pthreadimpl.h
+++ b/cpukit/posix/include/rtems/posix/pthreadimpl.h
@@ -68,6 +68,8 @@ RTEMS_INLINE_ROUTINE void _POSIX_Threads_Sporadic_timer_insert(
   );
 }
 
+void _POSIX_Threads_Sporadic_timer( Watchdog_Control *watchdog );
+
 /**
  * @brief POSIX threads sporadic budget callout.
  *
diff --git a/cpukit/posix/include/rtems/posix/threadsup.h b/cpukit/posix/include/rtems/posix/threadsup.h
index 21977be..3bb2210 100644
--- a/cpukit/posix/include/rtems/posix/threadsup.h
+++ b/cpukit/posix/include/rtems/posix/threadsup.h
@@ -60,13 +60,7 @@ typedef struct {
      * @brief The low priority when using the sporadic server scheduling
      * policy.
      */
-    Priority_Control low_priority;
-
-    /**
-     * @brief The high priority when using the sporadic server scheduling
-     * policy.
-     */
-    Priority_Control high_priority;
+    Priority_Node Low_priority;
   } Sporadic;
 
   /** This is the set of signals which are currently unblocked. */
diff --git a/cpukit/posix/src/killinfo.c b/cpukit/posix/src/killinfo.c
index 7cf74eb..6f45b29 100644
--- a/cpukit/posix/src/killinfo.c
+++ b/cpukit/posix/src/killinfo.c
@@ -153,7 +153,7 @@ int _POSIX_signals_Send(
           the_node = the_node->next ) {
       Scheduler_Node *scheduler_node;
 
-      scheduler_node = SCHEDULER_NODE_OF_WAIT_CHAIN_NODE( the_node );
+      scheduler_node = SCHEDULER_NODE_OF_WAIT_PRIORITY_NODE( the_node );
       the_thread = _Scheduler_Node_get_owner( scheduler_node );
       api = the_thread->API_Extensions[ THREAD_API_POSIX ];
 
diff --git a/cpukit/posix/src/mutexsetprioceiling.c b/cpukit/posix/src/mutexsetprioceiling.c
index 31e54c5..aaea57d 100644
--- a/cpukit/posix/src/mutexsetprioceiling.c
+++ b/cpukit/posix/src/mutexsetprioceiling.c
@@ -64,7 +64,18 @@ int pthread_mutex_setprioceiling(
 
     new_priority = _POSIX_Priority_To_core( scheduler, prioceiling, &valid );
     if ( valid ) {
-      _CORE_ceiling_mutex_Set_priority( &the_mutex->Mutex, new_priority );
+      Thread_queue_Context  queue_context;
+      Per_CPU_Control      *cpu_self;
+
+      _Thread_queue_Context_clear_priority_updates( &queue_context );
+      _CORE_ceiling_mutex_Set_priority(
+        &the_mutex->Mutex,
+        new_priority,
+        &queue_context
+      );
+      cpu_self = _Thread_Dispatch_disable();
+      _Thread_Priority_update( &queue_context );
+      _Thread_Dispatch_enable( cpu_self );
       error = 0;
     } else {
       error = EINVAL;
diff --git a/cpukit/posix/src/pthread.c b/cpukit/posix/src/pthread.c
index a1394a5..9cd730b 100644
--- a/cpukit/posix/src/pthread.c
+++ b/cpukit/posix/src/pthread.c
@@ -82,85 +82,70 @@ pthread_attr_t _POSIX_Threads_Default_attributes = {
   #endif
 };
 
-static bool _POSIX_Threads_Sporadic_timer_filter(
-  Thread_Control   *the_thread,
-  Priority_Control *new_priority_p,
-  void             *arg
-)
+void _POSIX_Threads_Sporadic_timer( Watchdog_Control *watchdog )
 {
-  POSIX_API_Control *api;
-  Priority_Control   current_priority;
-  Priority_Control   new_priority;
+  POSIX_API_Control    *api;
+  Thread_Control       *the_thread;
+  Thread_queue_Context  queue_context;
 
-  api = arg;
-
-  new_priority = api->Sporadic.high_priority;
-  *new_priority_p = new_priority;
+  api = RTEMS_CONTAINER_OF( watchdog, POSIX_API_Control, Sporadic.Timer );
+  the_thread = api->thread;
 
-  current_priority = _Thread_Get_priority( the_thread );
-  the_thread->real_priority = new_priority;
+  _Thread_queue_Context_clear_priority_updates( &queue_context );
+  _Thread_Wait_acquire( the_thread, &queue_context );
+
+  if ( _Priority_Node_is_active( &api->Sporadic.Low_priority ) ) {
+    _Thread_Priority_add(
+      the_thread,
+      &the_thread->Real_priority,
+      &queue_context
+    );
+    _Thread_Priority_remove(
+      the_thread,
+      &api->Sporadic.Low_priority,
+      &queue_context
+    );
+    _Priority_Node_set_inactive( &api->Sporadic.Low_priority );
+  }
 
   _Watchdog_Per_CPU_remove_relative( &api->Sporadic.Timer );
   _POSIX_Threads_Sporadic_timer_insert( the_thread, api );
 
-  return _Thread_Priority_less_than( current_priority, new_priority )
-    || !_Thread_Owns_resources( the_thread );
-}
-
-static void _POSIX_Threads_Sporadic_timer( Watchdog_Control *watchdog )
-{
-  POSIX_API_Control *api;
-  Thread_Control    *the_thread;
-
-  api = RTEMS_CONTAINER_OF( watchdog, POSIX_API_Control, Sporadic.Timer );
-  the_thread = api->thread;
-
-  _Thread_Change_priority(
-    the_thread,
-    0,
-    api,
-    _POSIX_Threads_Sporadic_timer_filter,
-    true
-  );
+  _Thread_Wait_release( the_thread, &queue_context );
+  _Thread_Priority_update( &queue_context );
 }
 
-static bool _POSIX_Threads_Sporadic_budget_callout_filter(
-  Thread_Control   *the_thread,
-  Priority_Control *new_priority_p,
-  void             *arg
-)
+void _POSIX_Threads_Sporadic_budget_callout( Thread_Control *the_thread )
 {
-  POSIX_API_Control *api;
-  Priority_Control   current_priority;
-  Priority_Control   new_priority;
+  POSIX_API_Control    *api;
+  Thread_queue_Context  queue_context;
 
   api = the_thread->API_Extensions[ THREAD_API_POSIX ];
 
+  _Thread_queue_Context_clear_priority_updates( &queue_context );
+  _Thread_Wait_acquire( the_thread, &queue_context );
+
   /*
    *  This will prevent the thread from consuming its entire "budget"
    *  while at low priority.
    */
   the_thread->cpu_time_budget = UINT32_MAX;
 
-  new_priority = api->Sporadic.low_priority;
-  *new_priority_p = new_priority;
-
-  current_priority = _Thread_Get_priority( the_thread );
-  the_thread->real_priority = new_priority;
-
-  return _Thread_Priority_less_than( current_priority, new_priority )
-    || !_Thread_Owns_resources( the_thread );
-}
+  if ( !_Priority_Node_is_active( &api->Sporadic.Low_priority ) ) {
+    _Thread_Priority_add(
+      the_thread,
+      &api->Sporadic.Low_priority,
+      &queue_context
+    );
+    _Thread_Priority_remove(
+      the_thread,
+      &the_thread->Real_priority,
+      &queue_context
+    );
+  }
 
-void _POSIX_Threads_Sporadic_budget_callout( Thread_Control *the_thread )
-{
-  _Thread_Change_priority(
-    the_thread,
-    0,
-    NULL,
-    _POSIX_Threads_Sporadic_budget_callout_filter,
-    true
-  );
+  _Thread_Wait_release( the_thread, &queue_context );
+  _Thread_Priority_update( &queue_context );
 }
 
 /*
diff --git a/cpukit/posix/src/pthreadcreate.c b/cpukit/posix/src/pthreadcreate.c
index 411882d..f1983ac 100644
--- a/cpukit/posix/src/pthreadcreate.c
+++ b/cpukit/posix/src/pthreadcreate.c
@@ -61,11 +61,11 @@ int pthread_create(
     }
   };
   const pthread_attr_t               *the_attr;
+  int                                 normal_prio;
   int                                 low_prio;
-  int                                 high_prio;
   bool                                valid;
+  Priority_Control                    core_normal_prio;
   Priority_Control                    core_low_prio;
-  Priority_Control                    core_high_prio;
   Thread_CPU_budget_algorithms        budget_algorithm;
   Thread_CPU_budget_algorithm_callout budget_callout;
   bool                                is_fp;
@@ -149,22 +149,22 @@ int pthread_create(
     return error;
   }
 
-  if ( schedpolicy == SCHED_SPORADIC ) {
-    low_prio = schedparam.sched_ss_low_priority;
-    high_prio = schedparam.sched_priority;
-  } else {
-    low_prio = schedparam.sched_priority;
-    high_prio = low_prio;
-  }
+  normal_prio = schedparam.sched_priority;
 
   scheduler = _Scheduler_Get_own( executing );
 
-  core_low_prio = _POSIX_Priority_To_core( scheduler, low_prio, &valid );
+  core_normal_prio = _POSIX_Priority_To_core( scheduler, normal_prio, &valid );
   if ( !valid ) {
     return EINVAL;
   }
 
-  core_high_prio = _POSIX_Priority_To_core( scheduler, high_prio, &valid );
+  if ( schedpolicy == SCHED_SPORADIC ) {
+    low_prio = schedparam.sched_ss_low_priority;
+  } else {
+    low_prio = normal_prio;
+  }
+
+  core_low_prio = _POSIX_Priority_To_core( scheduler, low_prio, &valid );
   if ( !valid ) {
     return EINVAL;
   }
@@ -205,7 +205,7 @@ int pthread_create(
     the_attr->stackaddr,
     _POSIX_Threads_Ensure_minimum_stack(the_attr->stacksize),
     is_fp,
-    core_high_prio,
+    core_normal_prio,
     true,                 /* preemptible */
     budget_algorithm,
     budget_callout,
@@ -245,13 +245,11 @@ int pthread_create(
   api = the_thread->API_Extensions[ THREAD_API_POSIX ];
 
   _POSIX_Threads_Copy_attributes( &api->Attributes, the_attr );
-  api->Sporadic.low_priority = core_low_prio;
-  api->Sporadic.high_priority = core_high_prio;
+  _Priority_Node_initialize( &api->Sporadic.Low_priority, core_low_prio );
+  _Priority_Node_set_inactive( &api->Sporadic.Low_priority );
 
   if ( schedpolicy == SCHED_SPORADIC ) {
-    _ISR_lock_ISR_disable( &lock_context );
-    _POSIX_Threads_Sporadic_timer_insert( the_thread, api );
-    _ISR_lock_ISR_enable( &lock_context );
+    _POSIX_Threads_Sporadic_timer( &api->Sporadic.Timer );
   }
 
   /*
diff --git a/cpukit/posix/src/pthreadgetschedparam.c b/cpukit/posix/src/pthreadgetschedparam.c
index 38e0b4f..1d4812c 100644
--- a/cpukit/posix/src/pthreadgetschedparam.c
+++ b/cpukit/posix/src/pthreadgetschedparam.c
@@ -59,7 +59,7 @@ int pthread_getschedparam(
   *param  = api->Attributes.schedparam;
 
   scheduler = _Scheduler_Get_own( the_thread );
-  priority = the_thread->real_priority;
+  priority = the_thread->Real_priority.priority;
 
   _Thread_Wait_release( the_thread, &queue_context );
 
diff --git a/cpukit/posix/src/pthreadsetschedparam.c b/cpukit/posix/src/pthreadsetschedparam.c
index e3711e3..9aa2122 100644
--- a/cpukit/posix/src/pthreadsetschedparam.c
+++ b/cpukit/posix/src/pthreadsetschedparam.c
@@ -30,36 +30,24 @@
 #include <rtems/score/threadimpl.h>
 #include <rtems/score/schedulerimpl.h>
 
-typedef struct {
-  int                                  policy;
-  const struct sched_param            *param;
-  Thread_CPU_budget_algorithms         budget_algorithm;
-  Thread_CPU_budget_algorithm_callout  budget_callout;
-  int                                  error;
-} POSIX_Set_sched_param_context;
-
-static bool _POSIX_Set_sched_param_filter(
-  Thread_Control   *the_thread,
-  Priority_Control *new_priority_p,
-  void             *arg
+static int _POSIX_Set_sched_param(
+  Thread_Control                       *the_thread,
+  int                                   policy,
+  struct sched_param                   *param,
+  Thread_CPU_budget_algorithms          budget_algorithm,
+  Thread_CPU_budget_algorithm_callout   budget_callout,
+  Thread_queue_Context                 *queue_context
 )
 {
-  POSIX_Set_sched_param_context *context;
-  const struct sched_param      *param;
-  const Scheduler_Control       *scheduler;
-  POSIX_API_Control             *api;
-  int                            low_prio;
-  int                            high_prio;
-  bool                           valid;
-  Priority_Control               core_low_prio;
-  Priority_Control               core_high_prio;
-  Priority_Control               current_priority;
-
-  context = arg;
-  param = context->param;
-  scheduler = _Scheduler_Get_own( the_thread );
-
-  if ( context->policy == SCHED_SPORADIC ) {
+  const Scheduler_Control *scheduler;
+  POSIX_API_Control       *api;
+  int                      low_prio;
+  int                      high_prio;
+  bool                     valid;
+  Priority_Control         core_normal_prio;
+  Priority_Control         core_low_prio;
+
+  if ( policy == SCHED_SPORADIC ) {
     low_prio = param->sched_ss_low_priority;
     high_prio = param->sched_priority;
   } else {
@@ -67,45 +55,60 @@ static bool _POSIX_Set_sched_param_filter(
     high_prio = low_prio;
   }
 
-  core_low_prio = _POSIX_Priority_To_core( scheduler, low_prio, &valid );
+  scheduler = _Scheduler_Get_own( the_thread );
+
+  core_normal_prio = _POSIX_Priority_To_core( scheduler, low_prio, &valid );
   if ( !valid ) {
-    context->error = EINVAL;
-    return false;
+    return EINVAL;
   }
 
-  core_high_prio = _POSIX_Priority_To_core( scheduler, high_prio, &valid );
+  core_low_prio = _POSIX_Priority_To_core( scheduler, high_prio, &valid );
   if ( !valid ) {
-    context->error = EINVAL;
-    return false;
+    return EINVAL;
   }
 
-  *new_priority_p = core_high_prio;
-
-  current_priority = _Thread_Get_priority( the_thread );
-  the_thread->real_priority = core_high_prio;
-
   api = the_thread->API_Extensions[ THREAD_API_POSIX ];
 
   _Watchdog_Per_CPU_remove_relative( &api->Sporadic.Timer );
 
-  api->Attributes.schedpolicy = context->policy;
+  _Priority_Node_set_priority( &the_thread->Real_priority, core_normal_prio );
+
+  if ( _Priority_Node_is_active( &api->Sporadic.Low_priority ) ) {
+    _Thread_Priority_add(
+      the_thread,
+      &the_thread->Real_priority,
+      queue_context
+    );
+    _Thread_Priority_remove(
+      the_thread,
+      &api->Sporadic.Low_priority,
+      queue_context
+    );
+    _Priority_Node_set_inactive( &api->Sporadic.Low_priority );
+  } else {
+    _Thread_Priority_changed(
+      the_thread,
+      &the_thread->Real_priority,
+      false,
+      queue_context
+    );
+  }
+
+  api->Attributes.schedpolicy = policy;
   api->Attributes.schedparam  = *param;
-  api->Sporadic.low_priority  = core_low_prio;
-  api->Sporadic.high_priority = core_high_prio;
 
-  the_thread->budget_algorithm = context->budget_algorithm;
-  the_thread->budget_callout   = context->budget_callout;
+  the_thread->budget_algorithm = budget_algorithm;
+  the_thread->budget_callout   = budget_callout;
 
-  if ( context->policy == SCHED_SPORADIC ) {
+  if ( policy == SCHED_SPORADIC ) {
+    _Priority_Node_set_priority( &api->Sporadic.Low_priority, core_low_prio );
     _POSIX_Threads_Sporadic_timer_insert( the_thread, api );
   } else {
     the_thread->cpu_time_budget =
       rtems_configuration_get_ticks_per_timeslice();
   }
 
-  context->error = 0;
-  return _Thread_Priority_less_than( current_priority, core_high_prio )
-    || !_Thread_Owns_resources( the_thread );
+  return 0;
 }
 
 int pthread_setschedparam(
@@ -114,11 +117,12 @@ int pthread_setschedparam(
   struct sched_param *param
 )
 {
-  Thread_Control                *the_thread;
-  Per_CPU_Control               *cpu_self;
-  POSIX_Set_sched_param_context  context;
-  ISR_lock_Context               lock_context;
-  int                            error;
+  Thread_CPU_budget_algorithms         budget_algorithm;
+  Thread_CPU_budget_algorithm_callout  budget_callout;
+  Thread_Control                      *the_thread;
+  Per_CPU_Control                     *cpu_self;
+  Thread_queue_Context                 queue_context;
+  int                                  error;
 
   if ( param == NULL ) {
     return EINVAL;
@@ -127,33 +131,34 @@ int pthread_setschedparam(
   error = _POSIX_Thread_Translate_sched_param(
     policy,
     param,
-    &context.budget_algorithm,
-    &context.budget_callout
+    &budget_algorithm,
+    &budget_callout
   );
   if ( error != 0 ) {
     return error;
   }
 
-  context.policy = policy;
-  context.param = param;
-
-  the_thread = _Thread_Get( thread, &lock_context );
+  the_thread = _Thread_Get( thread, &queue_context.Lock_context.Lock_context );
 
   if ( the_thread == NULL ) {
     return ESRCH;
   }
 
-  cpu_self = _Thread_Dispatch_disable_critical( &lock_context );
-  _ISR_lock_ISR_enable( &lock_context );
-
-  _Thread_Change_priority(
+  _Thread_queue_Context_clear_priority_updates( &queue_context );
+  _Thread_Wait_acquire_critical( the_thread, &queue_context );
+  error = _POSIX_Set_sched_param(
     the_thread,
-    0,
-    &context,
-    _POSIX_Set_sched_param_filter,
-    false
+    policy,
+    param,
+    budget_algorithm,
+    budget_callout,
+    &queue_context
   );
-
+  cpu_self = _Thread_Dispatch_disable_critical(
+    &queue_context.Lock_context.Lock_context
+  );
+  _Thread_Wait_release( the_thread, &queue_context );
+  _Thread_Priority_update( &queue_context );
   _Thread_Dispatch_enable( cpu_self );
-  return context.error;
+  return error;
 }
diff --git a/cpukit/posix/src/pthreadsetschedprio.c b/cpukit/posix/src/pthreadsetschedprio.c
index fac86d2..e3d9de0 100644
--- a/cpukit/posix/src/pthreadsetschedprio.c
+++ b/cpukit/posix/src/pthreadsetschedprio.c
@@ -18,79 +18,47 @@
 #include <rtems/score/threadimpl.h>
 #include <rtems/score/schedulerimpl.h>
 
-typedef struct {
-  int prio;
-  int error;
-} POSIX_Set_sched_prio_context;
-
-static bool _POSIX_Set_sched_prio_filter(
-  Thread_Control   *the_thread,
-  Priority_Control *new_priority_p,
-  void             *arg
-)
-{
-  POSIX_Set_sched_prio_context *context;
-  int                           prio;
-  const Scheduler_Control      *scheduler;
-  POSIX_API_Control            *api;
-  bool                          valid;
-  Priority_Control              current_priority;
-  Priority_Control              new_priority;
-
-  context = arg;
-  prio = context->prio;
-  scheduler = _Scheduler_Get_own( the_thread );
-
-  new_priority = _POSIX_Priority_To_core( scheduler, prio, &valid );
-  if ( !valid ) {
-    context->error = EINVAL;
-    return false;
-  }
-
-  *new_priority_p = new_priority;
-
-  current_priority = _Thread_Get_priority( the_thread );
-  the_thread->real_priority = new_priority;
-
-  api = the_thread->API_Extensions[ THREAD_API_POSIX ];
-
-  api->Sporadic.high_priority = new_priority;
-
-  if ( api->Sporadic.low_priority < new_priority ) {
-    api->Sporadic.low_priority  = new_priority;
-  }
-
-  context->error = 0;
-  return _Thread_Priority_less_than( current_priority, new_priority )
-    || !_Thread_Owns_resources( the_thread );
-}
-
 int pthread_setschedprio( pthread_t thread, int prio )
 {
-  Thread_Control               *the_thread;
-  Per_CPU_Control              *cpu_self;
-  POSIX_Set_sched_prio_context  context;
-  ISR_lock_Context              lock_context;
-
-  context.prio = prio;
+  Thread_Control          *the_thread;
+  Per_CPU_Control         *cpu_self;
+  Thread_queue_Context     queue_context;
+  const Scheduler_Control *scheduler;
+  Priority_Control         new_priority;
+  bool                     valid;
 
-  the_thread = _Thread_Get( thread, &lock_context );
+  the_thread = _Thread_Get( thread, &queue_context.Lock_context.Lock_context );
 
   if ( the_thread == NULL ) {
     return ESRCH;
   }
 
-  cpu_self = _Thread_Dispatch_disable_critical( &lock_context );
-  _ISR_lock_ISR_enable( &lock_context );
+  _Thread_queue_Context_clear_priority_updates( &queue_context );
+  _Thread_Wait_acquire_critical( the_thread, &queue_context );
 
-  _Thread_Change_priority(
+  scheduler = _Scheduler_Get_own( the_thread );
+
+  new_priority = _POSIX_Priority_To_core( scheduler, prio, &valid );
+  if ( !valid ) {
+    _Thread_Wait_release( the_thread, &queue_context );
+    return EINVAL;
+  }
+
+  _Thread_Priority_change(
     the_thread,
-    0,
-    &context,
-    _POSIX_Set_sched_prio_filter,
-    true
+    &the_thread->Real_priority,
+    new_priority,
+    true,
+    &queue_context
   );
 
+  cpu_self = _Thread_Dispatch_disable_critical(
+    &queue_context.Lock_context.Lock_context
+  );
+  _Thread_Wait_release( the_thread, &queue_context );
+
+  _Thread_Priority_update( &queue_context );
+
   _Thread_Dispatch_enable( cpu_self );
-  return context.error;
+  return 0;
 }
diff --git a/cpukit/rtems/include/rtems/rtems/ratemon.h b/cpukit/rtems/include/rtems/rtems/ratemon.h
index a2df13f..50b8478 100644
--- a/cpukit/rtems/include/rtems/rtems/ratemon.h
+++ b/cpukit/rtems/include/rtems/rtems/ratemon.h
@@ -206,6 +206,12 @@ typedef struct {
   rtems_rate_monotonic_period_states      state;
 
   /**
+   * @brief A priority node for use by the scheduler job release and cancel
+   * operations.
+   */
+  Priority_Node                           Priority;
+
+  /**
    * This field contains the length of the next period to be
    * executed.
    */
diff --git a/cpukit/rtems/src/ratemoncancel.c b/cpukit/rtems/src/ratemoncancel.c
index b4e899d..cb95f54 100644
--- a/cpukit/rtems/src/ratemoncancel.c
+++ b/cpukit/rtems/src/ratemoncancel.c
@@ -27,18 +27,22 @@ void _Rate_monotonic_Cancel(
   ISR_lock_Context       *lock_context
 )
 {
-  Per_CPU_Control *cpu_self;
-  Thread_Control  *update_priority;
+  Per_CPU_Control      *cpu_self;
+  Thread_queue_Context  queue_context;
 
   _Rate_monotonic_Acquire_critical( the_period, lock_context );
 
   _Watchdog_Per_CPU_remove_relative( &the_period->Timer );
   the_period->state = RATE_MONOTONIC_INACTIVE;
-  update_priority = _Scheduler_Cancel_job( the_period->owner );
+  _Scheduler_Cancel_job(
+    the_period->owner,
+    &the_period->Priority,
+    &queue_context
+  );
 
   cpu_self = _Thread_Dispatch_disable_critical( lock_context );
   _Rate_monotonic_Release( the_period, lock_context );
-  _Thread_Update_priority( update_priority );
+  _Thread_Priority_update( &queue_context );
   _Thread_Dispatch_enable( cpu_self );
 }
 
diff --git a/cpukit/rtems/src/ratemoncreate.c b/cpukit/rtems/src/ratemoncreate.c
index a86c6a1..1232729 100644
--- a/cpukit/rtems/src/ratemoncreate.c
+++ b/cpukit/rtems/src/ratemoncreate.c
@@ -63,6 +63,8 @@ rtems_status_code rtems_rate_monotonic_create(
   }
 
   _ISR_lock_Initialize( &the_period->Lock, "Rate Monotonic Period" );
+  _Priority_Node_initialize( &the_period->Priority, 0 );
+  _Priority_Node_set_inactive( &the_period->Priority );
 
   the_period->owner = _Thread_Get_executing();
   the_period->state = RATE_MONOTONIC_INACTIVE;
diff --git a/cpukit/rtems/src/ratemonperiod.c b/cpukit/rtems/src/ratemonperiod.c
index 75a80d8..77bd996 100644
--- a/cpukit/rtems/src/ratemonperiod.c
+++ b/cpukit/rtems/src/ratemonperiod.c
@@ -70,9 +70,9 @@ static void _Rate_monotonic_Release_job(
   ISR_lock_Context       *lock_context
 )
 {
-  Per_CPU_Control *cpu_self;
-  Thread_Control  *update_priority;
-  uint64_t         deadline;
+  Per_CPU_Control      *cpu_self;
+  Thread_queue_Context  queue_context;
+  uint64_t              deadline;
 
   cpu_self = _Thread_Dispatch_disable_critical( lock_context );
 
@@ -81,10 +81,15 @@ static void _Rate_monotonic_Release_job(
     cpu_self,
     next_length
   );
-  update_priority = _Scheduler_Release_job( owner, deadline );
+  _Scheduler_Release_job(
+    owner,
+    &the_period->Priority,
+    deadline,
+    &queue_context
+  );
 
   _Rate_monotonic_Release( the_period, lock_context );
-  _Thread_Update_priority( update_priority );
+  _Thread_Priority_update( &queue_context );
   _Thread_Dispatch_enable( cpu_self );
 }
 
diff --git a/cpukit/rtems/src/semsetpriority.c b/cpukit/rtems/src/semsetpriority.c
index f992d99..37dea5d 100644
--- a/cpukit/rtems/src/semsetpriority.c
+++ b/cpukit/rtems/src/semsetpriority.c
@@ -42,16 +42,18 @@ static rtems_status_code _Semaphore_Set_priority(
   Thread_queue_Context    *queue_context
 )
 {
-  rtems_status_code    sc;
-  bool                 valid;
-  Priority_Control     core_priority;
-  Priority_Control     old_priority;
+  rtems_status_code  sc;
+  bool               valid;
+  Priority_Control   core_priority;
+  Priority_Control   old_priority;
+  Per_CPU_Control   *cpu_self;
 
   core_priority = _RTEMS_Priority_To_core( scheduler, new_priority, &valid );
   if ( new_priority != RTEMS_CURRENT_PRIORITY && !valid ) {
     return RTEMS_INVALID_PRIORITY;
   }
 
+  _Thread_queue_Context_clear_priority_updates( queue_context );
   _Thread_queue_Acquire_critical(
     &the_semaphore->Core_control.Wait_queue,
     queue_context
@@ -71,7 +73,8 @@ static rtems_status_code _Semaphore_Set_priority(
       if ( sc == RTEMS_SUCCESSFUL && new_priority != RTEMS_CURRENT_PRIORITY ) {
         _CORE_ceiling_mutex_Set_priority(
           &the_semaphore->Core_control.Mutex,
-          core_priority
+          core_priority,
+          queue_context
         );
       }
 
@@ -106,10 +109,15 @@ static rtems_status_code _Semaphore_Set_priority(
       break;
   }
 
+  cpu_self = _Thread_Dispatch_disable_critical(
+    &queue_context->Lock_context.Lock_context
+  );
   _Thread_queue_Release(
     &the_semaphore->Core_control.Wait_queue,
     queue_context
   );
+  _Thread_Priority_update( queue_context );
+  _Thread_Dispatch_enable( cpu_self );
 
   *old_priority_p = _RTEMS_Priority_From_core( scheduler, old_priority );
   return sc;
diff --git a/cpukit/rtems/src/tasksetpriority.c b/cpukit/rtems/src/tasksetpriority.c
index 9779c97..6b8ab4e 100644
--- a/cpukit/rtems/src/tasksetpriority.c
+++ b/cpukit/rtems/src/tasksetpriority.c
@@ -22,50 +22,43 @@
 #include <rtems/score/schedulerimpl.h>
 #include <rtems/score/threadimpl.h>
 
-typedef struct {
-  const Scheduler_Control *scheduler;
-  rtems_task_priority      new_priority;
-  Priority_Control         old_priority;
-  rtems_status_code        status;
-} RTEMS_tasks_Set_priority_context;
-
-static bool _RTEMS_tasks_Set_priority_filter(
-  Thread_Control   *the_thread,
-  Priority_Control *new_priority_p,
-  void             *arg
+static rtems_status_code _RTEMS_tasks_Set_priority(
+  Thread_Control          *the_thread,
+  const Scheduler_Control *scheduler,
+  Priority_Control         new_priority,
+  Thread_queue_Context    *queue_context
 )
 {
-  RTEMS_tasks_Set_priority_context *context;
-  const Scheduler_Control          *scheduler;
-  bool                              valid;
-  Priority_Control                  current_priority;
-  Priority_Control                  new_priority;
+  Priority_Control core_new_priority;
+  bool             valid;
+  Per_CPU_Control *cpu_self;
 
-  context = arg;
-  scheduler = _Scheduler_Get_own( the_thread );
-  current_priority = _Thread_Get_priority( the_thread );
-
-  context->scheduler = scheduler;
-  context->old_priority = current_priority;
-
-  new_priority = _RTEMS_Priority_To_core(
+  core_new_priority = _RTEMS_Priority_To_core(
     scheduler,
-    context->new_priority,
+    new_priority,
     &valid
   );
 
-  *new_priority_p = new_priority;
-
   if ( !valid ) {
-    context->status = RTEMS_INVALID_PRIORITY;
-    return false;
+    _Thread_Wait_release( the_thread, queue_context );
+    return RTEMS_INVALID_PRIORITY;
   }
 
-  the_thread->real_priority = new_priority;
-  context->status = STATUS_SUCCESSFUL;
-
-  return _Thread_Priority_less_than( current_priority, new_priority )
-    || !_Thread_Owns_resources( the_thread );
+  _Thread_queue_Context_clear_priority_updates( queue_context );
+  _Thread_Priority_change(
+    the_thread,
+    &the_thread->Real_priority,
+    core_new_priority,
+    false,
+    queue_context
+  );
+  cpu_self = _Thread_Dispatch_disable_critical(
+    &queue_context->Lock_context.Lock_context
+  );
+  _Thread_Wait_release( the_thread, queue_context );
+  _Thread_Priority_update( queue_context );
+  _Thread_Dispatch_enable( cpu_self );
+  return RTEMS_SUCCESSFUL;
 }
 
 rtems_status_code rtems_task_set_priority(
@@ -75,7 +68,7 @@ rtems_status_code rtems_task_set_priority(
 )
 {
   Thread_Control          *the_thread;
-  ISR_lock_Context         lock_context;
+  Thread_queue_Context     queue_context;
   const Scheduler_Control *scheduler;
   Priority_Control         old_priority;
   rtems_status_code        status;
@@ -84,7 +77,8 @@ rtems_status_code rtems_task_set_priority(
     return RTEMS_INVALID_ADDRESS;
   }
 
-  the_thread = _Thread_Get( id, &lock_context );
+  _Thread_queue_Context_initialize( &queue_context );
+  the_thread = _Thread_Get( id, &queue_context.Lock_context.Lock_context );
 
   if ( the_thread == NULL ) {
 #if defined(RTEMS_MULTIPROCESSING)
@@ -94,31 +88,20 @@ rtems_status_code rtems_task_set_priority(
 #endif
   }
 
-  if ( new_priority != RTEMS_CURRENT_PRIORITY ) {
-    RTEMS_tasks_Set_priority_context  context;
-    Per_CPU_Control                  *cpu_self;
+  _Thread_Wait_acquire_critical( the_thread, &queue_context );
 
-    cpu_self = _Thread_Dispatch_disable_critical( &lock_context );
-    _ISR_lock_ISR_enable( &lock_context );
+  scheduler = _Scheduler_Get_own( the_thread );
+  old_priority = _Thread_Get_priority( the_thread );
 
-    context.new_priority = new_priority;
-    _Thread_Change_priority(
+  if ( new_priority != RTEMS_CURRENT_PRIORITY ) {
+    status = _RTEMS_tasks_Set_priority(
       the_thread,
-      0,
-      &context,
-      _RTEMS_tasks_Set_priority_filter,
-      false
+      scheduler,
+      new_priority,
+      &queue_context
     );
-
-    _Thread_Dispatch_enable( cpu_self );
-    scheduler = context.scheduler;
-    old_priority = context.old_priority;
-    status = context.status;
   } else {
-    _Thread_State_acquire_critical( the_thread, &lock_context );
-    scheduler = _Scheduler_Get_own( the_thread );
-    old_priority = _Thread_Get_priority( the_thread );
-    _Thread_State_release( the_thread, &lock_context );
+    _Thread_Wait_release( the_thread, &queue_context );
     status = RTEMS_SUCCESSFUL;
   }
 
diff --git a/cpukit/score/Makefile.am b/cpukit/score/Makefile.am
index f18af7d..a196ff5 100644
--- a/cpukit/score/Makefile.am
+++ b/cpukit/score/Makefile.am
@@ -58,6 +58,7 @@ include_rtems_score_HEADERS += include/rtems/score/objectimpl.h
 include_rtems_score_HEADERS += include/rtems/score/onceimpl.h
 include_rtems_score_HEADERS += include/rtems/score/percpu.h
 include_rtems_score_HEADERS += include/rtems/score/priority.h
+include_rtems_score_HEADERS += include/rtems/score/priorityimpl.h
 include_rtems_score_HEADERS += include/rtems/score/prioritybitmap.h
 include_rtems_score_HEADERS += include/rtems/score/prioritybitmapimpl.h
 include_rtems_score_HEADERS += include/rtems/score/profiling.h
@@ -300,7 +301,7 @@ libscore_a_SOURCES += src/thread.c src/threadchangepriority.c \
     src/threaddispatch.c \
     src/threadget.c src/threadhandler.c src/threadinitialize.c \
     src/threadloadenv.c \
-    src/threadrestart.c src/threadsetpriority.c \
+    src/threadrestart.c \
     src/threadsetstate.c \
     src/threadstackallocate.c src/threadstackfree.c src/threadstart.c \
     src/threadstartmultitasking.c src/iterateoverthreads.c
diff --git a/cpukit/score/include/rtems/score/coremutex.h b/cpukit/score/include/rtems/score/coremutex.h
index a3dcabf..d2bf1c2 100644
--- a/cpukit/score/include/rtems/score/coremutex.h
+++ b/cpukit/score/include/rtems/score/coremutex.h
@@ -82,9 +82,9 @@ typedef struct {
   CORE_recursive_mutex_Control Recursive;
 
   /**
-   * @brief The priority ceiling value for the mutex owner.
+   * @brief The priority ceiling node for the mutex owner.
    */
-  Priority_Control priority_ceiling;
+  Priority_Node Priority_ceiling;
 
 #if defined(RTEMS_SMP)
   /**
diff --git a/cpukit/score/include/rtems/score/coremuteximpl.h b/cpukit/score/include/rtems/score/coremuteximpl.h
index 25094a4..1eca5a4 100644
--- a/cpukit/score/include/rtems/score/coremuteximpl.h
+++ b/cpukit/score/include/rtems/score/coremuteximpl.h
@@ -124,32 +124,6 @@ RTEMS_INLINE_ROUTINE bool _CORE_mutex_Is_owner(
   return _CORE_mutex_Get_owner( the_mutex ) == the_thread;
 }
 
-RTEMS_INLINE_ROUTINE void _CORE_mutex_Restore_priority(
-  Thread_Control *executing
-)
-{
-  /*
-   *  Whether or not someone is waiting for the mutex, an
-   *  inherited priority must be lowered if this is the last
-   *  mutex (i.e. resource) this task has.
-   */
-  if ( !_Thread_Owns_resources( executing ) ) {
-    /*
-     * Ensure that the executing resource count is visible to all other
-     * processors and that we read the latest priority restore hint.
-     */
-    _Atomic_Fence( ATOMIC_ORDER_ACQ_REL );
-
-    if ( executing->priority_restore_hint ) {
-      Per_CPU_Control *cpu_self;
-
-      cpu_self = _Thread_Dispatch_disable();
-      _Thread_Restore_priority( executing );
-      _Thread_Dispatch_enable( cpu_self );
-    }
-  }
-}
-
 RTEMS_INLINE_ROUTINE void _CORE_recursive_mutex_Initialize(
   CORE_recursive_mutex_Control *the_mutex
 )
@@ -212,7 +186,6 @@ RTEMS_INLINE_ROUTINE Status_Control _CORE_recursive_mutex_Surrender(
 {
   unsigned int        nest_level;
   Thread_queue_Heads *heads;
-  bool                keep_priority;
 
   _CORE_mutex_Acquire_critical( &the_mutex->Mutex, queue_context );
 
@@ -232,29 +205,19 @@ RTEMS_INLINE_ROUTINE Status_Control _CORE_recursive_mutex_Surrender(
   --executing->resource_count;
   _CORE_mutex_Set_owner( &the_mutex->Mutex, NULL );
 
-  /*
-   * Ensure that the owner resource count is visible to all other
-   * processors and that we read the latest priority restore
-   * hint.
-   */
-  _Atomic_Fence( ATOMIC_ORDER_ACQ_REL );
-
   heads = the_mutex->Mutex.Wait_queue.Queue.heads;
-  keep_priority = _Thread_Owns_resources( executing )
-    || !executing->priority_restore_hint;
 
-  if ( heads == NULL && keep_priority ) {
+  if ( heads == NULL ) {
     _CORE_mutex_Release( &the_mutex->Mutex, queue_context );
     return STATUS_SUCCESSFUL;
   }
 
   _Thread_queue_Surrender(
     &the_mutex->Mutex.Wait_queue.Queue,
-    CORE_MUTEX_TQ_PRIORITY_INHERIT_OPERATIONS,
     heads,
     executing,
-    keep_priority,
-    queue_context
+    queue_context,
+    CORE_MUTEX_TQ_PRIORITY_INHERIT_OPERATIONS
   );
   return STATUS_SUCCESSFUL;
 }
@@ -349,7 +312,7 @@ RTEMS_INLINE_ROUTINE void _CORE_ceiling_mutex_Initialize(
 )
 {
   _CORE_recursive_mutex_Initialize( &the_mutex->Recursive );
-  the_mutex->priority_ceiling = priority_ceiling;
+  _Priority_Node_initialize( &the_mutex->Priority_ceiling, priority_ceiling );
 #if defined(RTEMS_SMP)
   the_mutex->scheduler = scheduler;
 #endif
@@ -369,17 +332,34 @@ _CORE_ceiling_mutex_Get_scheduler(
 
 RTEMS_INLINE_ROUTINE void _CORE_ceiling_mutex_Set_priority(
   CORE_ceiling_mutex_Control *the_mutex,
-  Priority_Control            priority_ceiling
+  Priority_Control            priority_ceiling,
+  Thread_queue_Context       *queue_context
 )
 {
-  the_mutex->priority_ceiling = priority_ceiling;
+  Thread_Control *owner;
+
+  owner = _CORE_mutex_Get_owner( &the_mutex->Recursive.Mutex );
+
+  if ( owner != NULL ) {
+    _Thread_Wait_acquire( owner, queue_context );
+    _Thread_Priority_change(
+      owner,
+      &the_mutex->Priority_ceiling,
+      priority_ceiling,
+      false,
+      queue_context
+    );
+    _Thread_Wait_release( owner, queue_context );
+  } else {
+    the_mutex->Priority_ceiling.priority = priority_ceiling;
+  }
 }
 
 RTEMS_INLINE_ROUTINE Priority_Control _CORE_ceiling_mutex_Get_priority(
   const CORE_ceiling_mutex_Control *the_mutex
 )
 {
-  return the_mutex->priority_ceiling;
+  return the_mutex->Priority_ceiling.priority;
 }
 
 RTEMS_INLINE_ROUTINE Status_Control _CORE_ceiling_mutex_Set_owner(
@@ -388,31 +368,38 @@ RTEMS_INLINE_ROUTINE Status_Control _CORE_ceiling_mutex_Set_owner(
   Thread_queue_Context       *queue_context
 )
 {
-  Priority_Control  priority_ceiling;
-  Priority_Control  current_priority;
+  ISR_lock_Context  lock_context;
+  Scheduler_Node   *own_node;
   Per_CPU_Control  *cpu_self;
 
-  priority_ceiling = the_mutex->priority_ceiling;
-  current_priority = _Thread_Get_priority( owner );
+  _Thread_queue_Context_clear_priority_updates( queue_context );
+  _Thread_Wait_acquire_default_critical( owner, &lock_context );
 
-  if ( current_priority < priority_ceiling ) {
+  own_node = _Thread_Scheduler_get_own_node( owner );
+
+  if (
+    own_node->Wait.Priority.Node.priority
+      < the_mutex->Priority_ceiling.priority
+  ) {
+    _Thread_Wait_release_default_critical( owner, &lock_context );
     _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context );
     return STATUS_MUTEX_CEILING_VIOLATED;
   }
 
   _CORE_mutex_Set_owner( &the_mutex->Recursive.Mutex, owner );
   ++owner->resource_count;
-
-  if ( current_priority == priority_ceiling ) {
-    _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context );
-    return STATUS_SUCCESSFUL;
-  }
+  _Thread_Priority_add(
+    owner,
+    &the_mutex->Priority_ceiling,
+    queue_context
+  );
+  _Thread_Wait_release_default_critical( owner, &lock_context );
 
   cpu_self = _Thread_Dispatch_disable_critical(
     &queue_context->Lock_context.Lock_context
   );
   _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context );
-  _Thread_Raise_priority( owner, priority_ceiling );
+  _Thread_Priority_update( queue_context );
   _Thread_Dispatch_enable( cpu_self );
   return STATUS_SUCCESSFUL;
 }
@@ -472,8 +459,10 @@ RTEMS_INLINE_ROUTINE Status_Control _CORE_ceiling_mutex_Surrender(
   Thread_queue_Context       *queue_context
 )
 {
-  unsigned int    nest_level;
-  Thread_Control *new_owner;
+  unsigned int      nest_level;
+  ISR_lock_Context  lock_context;
+  Per_CPU_Control  *cpu_self;
+  Thread_Control   *new_owner;
 
   _CORE_mutex_Acquire_critical( &the_mutex->Recursive.Mutex, queue_context );
 
@@ -492,47 +481,52 @@ RTEMS_INLINE_ROUTINE Status_Control _CORE_ceiling_mutex_Surrender(
 
   --executing->resource_count;
 
+  _Thread_queue_Context_clear_priority_updates( queue_context );
+  _Thread_Wait_acquire_default_critical( executing, &lock_context );
+  _Thread_Priority_remove(
+    executing,
+    &the_mutex->Priority_ceiling,
+    queue_context
+  );
+  _Thread_Wait_release_default_critical( executing, &lock_context );
+
   new_owner = _Thread_queue_First_locked(
     &the_mutex->Recursive.Mutex.Wait_queue,
     CORE_MUTEX_TQ_OPERATIONS
   );
   _CORE_mutex_Set_owner( &the_mutex->Recursive.Mutex, new_owner );
 
-  if ( new_owner != NULL ) {
-    bool unblock;
-
-    /*
-     * We must extract the thread now since this will restore its default
-     * thread lock.  This is necessary to avoid a deadlock in the
-     * _Thread_Change_priority() below due to a recursive thread queue lock
-     * acquire.
-     */
-    unblock = _Thread_queue_Extract_locked(
-      &the_mutex->Recursive.Mutex.Wait_queue.Queue,
-      CORE_MUTEX_TQ_OPERATIONS,
-      new_owner,
-      queue_context
-    );
+  cpu_self = _Thread_Dispatch_disable_critical(
+    &queue_context->Lock_context.Lock_context
+  );
 
+  if ( new_owner != NULL ) {
 #if defined(RTEMS_MULTIPROCESSING)
+    queue_context->Priority.update = NULL;
+
     if ( _Objects_Is_local_id( new_owner->Object.id ) )
 #endif
     {
       ++new_owner->resource_count;
-      _Thread_Raise_priority( new_owner, the_mutex->priority_ceiling );
+      _Thread_Priority_add(
+        new_owner,
+        &the_mutex->Priority_ceiling,
+        queue_context
+      );
     }
 
-    _Thread_queue_Unblock_critical(
-      unblock,
+    _Thread_queue_Extract_critical(
       &the_mutex->Recursive.Mutex.Wait_queue.Queue,
+      CORE_MUTEX_TQ_OPERATIONS,
       new_owner,
-      &queue_context->Lock_context.Lock_context
+      queue_context
     );
   } else {
     _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context );
   }
 
-  _CORE_mutex_Restore_priority( executing );
+  _Thread_Priority_update( queue_context );
+  _Thread_Dispatch_enable( cpu_self );
   return STATUS_SUCCESSFUL;
 }
 
diff --git a/cpukit/score/include/rtems/score/mrsp.h b/cpukit/score/include/rtems/score/mrsp.h
index 08a2427..5af3a06 100644
--- a/cpukit/score/include/rtems/score/mrsp.h
+++ b/cpukit/score/include/rtems/score/mrsp.h
@@ -80,12 +80,9 @@ typedef struct {
   Thread_Control *thread;
 
   /**
-   * @brief The initial priority of the thread at the begin of the resource
-   * obtain sequence.
-   *
-   * Used to restore the priority after a release of this resource or timeout.
+   * @brief The ceiling priority used by the rival thread.
    */
-  Priority_Control initial_priority;
+  Priority_Node Ceiling_priority;
 
   /**
    * @brief The initial help state of the thread at the begin of the resource
@@ -135,10 +132,9 @@ struct MRSP_Control {
   Chain_Control Rivals;
 
   /**
-   * @brief The initial priority of the owner before it was elevated to the
-   * ceiling priority.
+   * @brief The ceiling priority used by the owner thread.
    */
-  Priority_Control initial_priority_of_owner;
+  Priority_Node Ceiling_priority;
 
   /**
    * @brief One ceiling priority per scheduler instance.
diff --git a/cpukit/score/include/rtems/score/mrspimpl.h b/cpukit/score/include/rtems/score/mrspimpl.h
index cc00aa3..deaacf2 100644
--- a/cpukit/score/include/rtems/score/mrspimpl.h
+++ b/cpukit/score/include/rtems/score/mrspimpl.h
@@ -77,53 +77,115 @@ RTEMS_INLINE_ROUTINE void _MRSP_Release(
   _Thread_queue_Release( &mrsp->Wait_queue, queue_context );
 }
 
-RTEMS_INLINE_ROUTINE bool _MRSP_Restore_priority_filter(
-  Thread_Control   *thread,
-  Priority_Control *new_priority,
-  void             *arg
+RTEMS_INLINE_ROUTINE Priority_Control _MRSP_Get_priority(
+  const MRSP_Control      *mrsp,
+  const Scheduler_Control *scheduler
 )
 {
-  *new_priority = _Thread_Priority_highest(
-    thread->real_priority,
-    *new_priority
-  );
+  uint32_t scheduler_index;
 
-  return *new_priority != _Thread_Get_priority( thread );
+  scheduler_index = _Scheduler_Get_index( scheduler );
+  return mrsp->ceiling_priorities[ scheduler_index ];
 }
 
-RTEMS_INLINE_ROUTINE void _MRSP_Restore_priority(
-  Thread_Control   *thread,
-  Priority_Control  initial_priority
+RTEMS_INLINE_ROUTINE void _MRSP_Set_priority(
+  MRSP_Control            *mrsp,
+  const Scheduler_Control *scheduler,
+  Priority_Control         new_priority
 )
 {
-  /*
-   * The Thread_Control::resource_count is used by the normal priority ceiling
-   * or priority inheritance semaphores.
-   */
-  if ( thread->resource_count == 0 ) {
-    _Thread_Change_priority(
-      thread,
-      initial_priority,
-      NULL,
-      _MRSP_Restore_priority_filter,
-      true
-    );
+  uint32_t scheduler_index;
+
+  scheduler_index = _Scheduler_Get_index( scheduler );
+  mrsp->ceiling_priorities[ scheduler_index ] = new_priority;
+}
+
+RTEMS_INLINE_ROUTINE Status_Control _MRSP_Raise_priority(
+  MRSP_Control         *mrsp,
+  Thread_Control       *thread,
+  Priority_Node        *priority_node,
+  Thread_queue_Context *queue_context
+)
+{
+  Status_Control           status;
+  ISR_lock_Context         lock_context;
+  const Scheduler_Control *scheduler;
+  Priority_Control         ceiling_priority;
+  Scheduler_Node          *own_node;
+
+  _Thread_queue_Context_clear_priority_updates( queue_context );
+  _Thread_Wait_acquire_default_critical( thread, &lock_context );
+
+  scheduler = _Scheduler_Get_own( thread );
+  own_node = _Thread_Scheduler_get_own_node( thread );
+  ceiling_priority = _MRSP_Get_priority( mrsp, scheduler );
+
+  if ( ceiling_priority <= own_node->Wait.Priority.Node.priority ) {
+    _Priority_Node_initialize( priority_node, ceiling_priority );
+    _Thread_Priority_add( thread, priority_node, queue_context );
+    status = STATUS_SUCCESSFUL;
+  } else {
+    status = STATUS_MUTEX_CEILING_VIOLATED;
   }
+
+  _Thread_Wait_release_default_critical( thread, &lock_context );
+  return status;
+}
+
+RTEMS_INLINE_ROUTINE void _MRSP_Remove_priority(
+  Thread_Control       *thread,
+  Priority_Node        *priority_node,
+  Thread_queue_Context *queue_context
+)
+{
+  ISR_lock_Context  lock_context;
+
+  _Thread_queue_Context_clear_priority_updates( queue_context );
+  _Thread_Wait_acquire_default_critical( thread, &lock_context );
+  _Thread_Priority_remove( thread, priority_node, queue_context );
+  _Thread_Wait_release_default_critical( thread, &lock_context );
+}
+
+RTEMS_INLINE_ROUTINE void _MRSP_Replace_priority(
+  MRSP_Control   *mrsp,
+  Thread_Control *thread,
+  MRSP_Rival     *rival
+)
+{
+  ISR_lock_Context lock_context;
+
+  _Thread_Wait_acquire_default_critical( thread, &lock_context );
+  _Thread_Priority_replace( 
+    thread,
+    &rival->Ceiling_priority,
+    &mrsp->Ceiling_priority
+  );
+  _Thread_Wait_release_default_critical( thread, &lock_context );
 }
 
-RTEMS_INLINE_ROUTINE void _MRSP_Claim_ownership(
+RTEMS_INLINE_ROUTINE Status_Control _MRSP_Claim_ownership(
   MRSP_Control         *mrsp,
   Thread_Control       *new_owner,
-  Priority_Control      initial_priority,
-  Priority_Control      ceiling_priority,
   Thread_queue_Context *queue_context
 )
 {
+  Status_Control   status;
   Per_CPU_Control *cpu_self;
 
+  status = _MRSP_Raise_priority(
+    mrsp,
+    new_owner,
+    &mrsp->Ceiling_priority,
+    queue_context
+  );
+
+  if ( status != STATUS_SUCCESSFUL ) {
+    _MRSP_Release( mrsp, queue_context );
+    return status;
+  }
+
   _Resource_Node_add_resource( &new_owner->Resource_node, &mrsp->Resource );
   _Resource_Set_owner( &mrsp->Resource, &new_owner->Resource_node );
-  mrsp->initial_priority_of_owner = initial_priority;
   _Scheduler_Thread_change_help_state( new_owner, SCHEDULER_HELP_ACTIVE_OWNER );
 
   cpu_self = _Thread_Dispatch_disable_critical(
@@ -131,9 +193,10 @@ RTEMS_INLINE_ROUTINE void _MRSP_Claim_ownership(
   );
   _MRSP_Release( mrsp, queue_context );
 
-  _Thread_Raise_priority( new_owner, ceiling_priority );
+  _Thread_Priority_update( queue_context );
 
   _Thread_Dispatch_enable( cpu_self );
+  return STATUS_SUCCESSFUL;
 }
 
 RTEMS_INLINE_ROUTINE Status_Control _MRSP_Initialize(
@@ -178,35 +241,16 @@ RTEMS_INLINE_ROUTINE Status_Control _MRSP_Initialize(
   return STATUS_SUCCESSFUL;
 }
 
-RTEMS_INLINE_ROUTINE Priority_Control _MRSP_Get_priority(
-  const MRSP_Control      *mrsp,
-  const Scheduler_Control *scheduler
-)
-{
-  uint32_t scheduler_index;
-
-  scheduler_index = _Scheduler_Get_index( scheduler );
-  return mrsp->ceiling_priorities[ scheduler_index ];
-}
-
-RTEMS_INLINE_ROUTINE void _MRSP_Set_priority(
-  MRSP_Control            *mrsp,
-  const Scheduler_Control *scheduler,
-  Priority_Control         new_priority
-)
-{
-  uint32_t scheduler_index;
-
-  scheduler_index = _Scheduler_Get_index( scheduler );
-  mrsp->ceiling_priorities[ scheduler_index ] = new_priority;
-}
-
 RTEMS_INLINE_ROUTINE void _MRSP_Timeout( Watchdog_Control *watchdog )
 {
-  MRSP_Rival *rival = RTEMS_CONTAINER_OF( watchdog, MRSP_Rival, Watchdog );
-  MRSP_Control *mrsp = rival->resource;
-  Thread_Control *thread = rival->thread;
-  Thread_queue_Context queue_context;
+  MRSP_Rival           *rival;
+  MRSP_Control         *mrsp;
+  Thread_Control       *thread;
+  Thread_queue_Context  queue_context;
+
+  rival = RTEMS_CONTAINER_OF( watchdog, MRSP_Rival, Watchdog );
+  mrsp = rival->resource;
+  thread = rival->thread;
 
   _Thread_queue_Context_initialize( &queue_context );
   _ISR_lock_ISR_disable( &queue_context.Lock_context.Lock_context );
@@ -215,6 +259,8 @@ RTEMS_INLINE_ROUTINE void _MRSP_Timeout( Watchdog_Control *watchdog )
   if ( rival->status == MRSP_WAIT_FOR_OWNERSHIP ) {
     ISR_lock_Context giant_lock_context;
 
+    _MRSP_Remove_priority( thread, &rival->Ceiling_priority, &queue_context );
+
     _MRSP_Giant_acquire( &giant_lock_context );
 
     _Chain_Extract_unprotected( &rival->Node );
@@ -228,6 +274,8 @@ RTEMS_INLINE_ROUTINE void _MRSP_Timeout( Watchdog_Control *watchdog )
     rival->status = STATUS_TIMEOUT;
 
     _MRSP_Release( mrsp, &queue_context );
+
+    _Thread_Priority_update( &queue_context );
   } else {
     _MRSP_Release( mrsp, &queue_context );
   }
@@ -237,23 +285,34 @@ RTEMS_INLINE_ROUTINE Status_Control _MRSP_Wait_for_ownership(
   MRSP_Control         *mrsp,
   Resource_Node        *owner,
   Thread_Control       *executing,
-  Priority_Control      initial_priority,
-  Priority_Control      ceiling_priority,
   Thread_queue_Context *queue_context
 )
 {
-  Status_Control status;
-  MRSP_Rival rival;
-  Thread_Life_state life_state;
-  Per_CPU_Control *cpu_self;
-  ISR_lock_Context giant_lock_context;
-  ISR_Level level;
-  Watchdog_Interval timeout = queue_context->timeout;
+  Status_Control     status;
+  MRSP_Rival         rival;
+  Thread_Life_state  life_state;
+  Per_CPU_Control   *cpu_self;
+  ISR_lock_Context   giant_lock_context;
+  ISR_Level          level;
+  Watchdog_Interval  timeout;
+
   _Assert( queue_context->timeout_discipline == WATCHDOG_RELATIVE );
 
+  status = _MRSP_Raise_priority(
+    mrsp,
+    executing,
+    &rival.Ceiling_priority,
+    queue_context
+  );
+
+  if ( status != STATUS_SUCCESSFUL ) {
+    _MRSP_Release( mrsp, queue_context );
+    return status;
+  }
+
   rival.thread = executing;
   rival.resource = mrsp;
-  rival.initial_priority = initial_priority;
+  _Chain_Initialize_node( &rival.Node );
 
   _MRSP_Giant_acquire( &giant_lock_context );
 
@@ -277,7 +336,9 @@ RTEMS_INLINE_ROUTINE Status_Control _MRSP_Wait_for_ownership(
   );
   _MRSP_Release( mrsp, queue_context );
 
-  _Thread_Raise_priority( executing, ceiling_priority );
+  _Thread_Priority_update( queue_context );
+
+  timeout = (Watchdog_Interval) queue_context->timeout;
 
   if ( timeout > 0 ) {
     _Watchdog_Preinitialize( &rival.Watchdog, cpu_self );
@@ -307,10 +368,6 @@ RTEMS_INLINE_ROUTINE Status_Control _MRSP_Wait_for_ownership(
       &cpu_self->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ]
     );
     _ISR_Local_enable( level );
-
-    if ( status == STATUS_TIMEOUT ) {
-      _MRSP_Restore_priority( executing, initial_priority );
-    }
   }
 
   return status;
@@ -323,44 +380,20 @@ RTEMS_INLINE_ROUTINE Status_Control _MRSP_Seize(
   Thread_queue_Context *queue_context
 )
 {
-  Status_Control status;
-  const Scheduler_Control *scheduler = _Scheduler_Get_own( executing );
-  Priority_Control initial_priority = _Thread_Get_priority( executing );
-  Priority_Control ceiling_priority = _MRSP_Get_priority( mrsp, scheduler );
-  bool priority_ok = !_Thread_Priority_less_than(
-    ceiling_priority,
-    initial_priority
-  );
-  Resource_Node *owner;
-
-  if ( !priority_ok) {
-    _ISR_lock_ISR_enable( &queue_context->Lock_context.Lock_context );
-    return STATUS_MUTEX_CEILING_VIOLATED;
-  }
+  Status_Control  status;
+  Resource_Node  *owner;
 
   _MRSP_Acquire_critical( mrsp, queue_context );
+
   owner = _Resource_Get_owner( &mrsp->Resource );
+
   if ( owner == NULL ) {
-    _MRSP_Claim_ownership(
-      mrsp,
-      executing,
-      initial_priority,
-      ceiling_priority,
-      queue_context
-    );
-    status = STATUS_SUCCESSFUL;
+    status = _MRSP_Claim_ownership( mrsp, executing, queue_context );
   } else if (
     wait
       && _Resource_Node_get_root( owner ) != &executing->Resource_node
   ) {
-    status = _MRSP_Wait_for_ownership(
-      mrsp,
-      owner,
-      executing,
-      initial_priority,
-      ceiling_priority,
-      queue_context
-    );
+    status = _MRSP_Wait_for_ownership( mrsp, owner, executing, queue_context );
   } else {
     _MRSP_Release( mrsp, queue_context );
     /* Not available, nested access or deadlock */
@@ -376,9 +409,8 @@ RTEMS_INLINE_ROUTINE Status_Control _MRSP_Surrender(
   Thread_queue_Context *queue_context
 )
 {
-  Priority_Control initial_priority;
-  Per_CPU_Control *cpu_self;
-  ISR_lock_Context giant_lock_context;
+  ISR_lock_Context  giant_lock_context;
+  Per_CPU_Control  *cpu_self;
 
   if ( _Resource_Get_owner( &mrsp->Resource ) != &executing->Resource_node ) {
     _ISR_lock_ISR_enable( &queue_context->Lock_context.Lock_context );
@@ -395,10 +427,8 @@ RTEMS_INLINE_ROUTINE Status_Control _MRSP_Surrender(
     return STATUS_RELEASE_ORDER_VIOLATION;
   }
 
-  initial_priority = mrsp->initial_priority_of_owner;
-
   _MRSP_Acquire_critical( mrsp, queue_context );
-
+  _MRSP_Remove_priority( executing, &mrsp->Ceiling_priority, queue_context );
   _MRSP_Giant_acquire( &giant_lock_context );
 
   _Resource_Extract( &mrsp->Resource );
@@ -406,10 +436,11 @@ RTEMS_INLINE_ROUTINE Status_Control _MRSP_Surrender(
   if ( _Chain_Is_empty( &mrsp->Rivals ) ) {
     _Resource_Set_owner( &mrsp->Resource, NULL );
   } else {
-    MRSP_Rival *rival = (MRSP_Rival *)
-      _Chain_Get_first_unprotected( &mrsp->Rivals );
+    MRSP_Rival     *rival;
     Thread_Control *new_owner;
 
+    rival = (MRSP_Rival *) _Chain_Get_first_unprotected( &mrsp->Rivals );
+
     /*
      * This must be inside the critical section since the status prevents a
      * potential double extraction in _MRSP_Timeout().
@@ -417,7 +448,9 @@ RTEMS_INLINE_ROUTINE Status_Control _MRSP_Surrender(
     rival->status = STATUS_SUCCESSFUL;
 
     new_owner = rival->thread;
-    mrsp->initial_priority_of_owner = rival->initial_priority;
+
+    _MRSP_Replace_priority( mrsp, new_owner, rival );
+
     _Resource_Node_extract( &new_owner->Resource_node );
     _Resource_Node_set_dependency( &new_owner->Resource_node, NULL );
     _Resource_Node_add_resource( &new_owner->Resource_node, &mrsp->Resource );
@@ -437,7 +470,7 @@ RTEMS_INLINE_ROUTINE Status_Control _MRSP_Surrender(
   );
   _MRSP_Release( mrsp, queue_context );
 
-  _MRSP_Restore_priority( executing, initial_priority );
+  _Thread_Priority_update( queue_context );
 
   _Thread_Dispatch_enable( cpu_self );
 
diff --git a/cpukit/score/include/rtems/score/priority.h b/cpukit/score/include/rtems/score/priority.h
index 842f017..595aa3e 100644
--- a/cpukit/score/include/rtems/score/priority.h
+++ b/cpukit/score/include/rtems/score/priority.h
@@ -1,17 +1,15 @@
 /**
- * @file rtems/score/priority.h
+ * @file
  *
- * @brief Thread Priority Manipulation Routines
- *
- * This include file contains all thread priority manipulation routines.
- * This Handler provides mechanisms which can be used to
- * initialize and manipulate thread priorities.
+ * @brief Priority Handler API
  */
 
 /*
  *  COPYRIGHT (c) 1989-2011.
  *  On-Line Applications Research Corporation (OAR).
  *
+ *  Copyright (c) 2016 embedded brains GmbH.
+ *
  *  The license and distribution terms for this file may be
  *  found in the file LICENSE in this distribution or at
  *  http://www.rtems.org/license/LICENSE.
@@ -20,58 +18,169 @@
 #ifndef _RTEMS_SCORE_PRIORITY_H
 #define _RTEMS_SCORE_PRIORITY_H
 
-/**
- *  @defgroup ScorePriority Priority Handler
- *
- *  @ingroup Score
- *
- *  This handler encapsulates functionality which is used to manage
- *  thread priorities.  At the SuperCore level 256 priority levels
- *  are supported with lower numbers representing logically more important
- *  threads.  The priority level 0 is reserved for internal RTEMS use.
- *  Typically it is assigned to threads which defer internal RTEMS
- *  actions from an interrupt to thread level to improve interrupt response.
- *  Priority level 255 is assigned to the IDLE thread and really should not
- *  be used by application threads.  The default IDLE thread implementation
- *  is an infinite "branch to self" loop which never yields to other threads
- *  at the same priority.
- */
-/**@{*/
-
-/*
- * Processor specific information.
- */
+#include <rtems/score/chain.h>
 #include <rtems/score/cpu.h>
+#include <rtems/score/rbtree.h>
+
+struct Scheduler_Control;
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /**
- *  The following type defines the control block used to manage
- *  thread priorities.
+ * @defgroup ScorePriority Priority Handler
+ *
+ * @ingroup Score
+ *
+ * This handler encapsulates functionality which is used to manage thread
+ * priorities.  The actual priority of a thread is 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.
+ *
+ * @{
+ */
+
+/**
+ * @brief A plain thread priority value.
  *
- *  @note Priority 0 is reserved for internal threads only.
+ * Lower values represent higher priorities.  So, a priority value of zero
+ * represents the highest priority thread.  This value is reserved for internal
+ * threads and the priority ceiling protocol.
  */
 typedef uint64_t Priority_Control;
 
-/** This defines the highest (most important) thread priority. */
+/**
+ * @brief The highest (most important) thread priority value.
+ */
 #define PRIORITY_MINIMUM      0
 
 /**
- * @brief This defines the priority of pseudo-ISR threads.
+ * @brief The priority value of pseudo-ISR threads.
  *
  * Examples are the MPCI and timer server threads.
  */
 #define PRIORITY_PSEUDO_ISR   PRIORITY_MINIMUM
 
-/** This defines the default lowest (least important) thread priority. */
+/**
+ * @brief The default lowest (least important) thread priority value.
+ *
+ * This value is CPU port dependent.
+ */
 #if defined (CPU_PRIORITY_MAXIMUM)
   #define PRIORITY_DEFAULT_MAXIMUM      CPU_PRIORITY_MAXIMUM
 #else
   #define PRIORITY_DEFAULT_MAXIMUM      255
 #endif
 
+/**
+ * @brief The priority node to build up a priority aggregation.
+ */
+typedef struct {
+  /**
+   * @brief Node component for a chain or red-black tree.
+   */
+  union {
+    Chain_Node Chain;
+    RBTree_Node RBTree;
+  } Node;
+
+  /**
+   * @brief The priority value of this node.
+   */
+  Priority_Control priority;
+} Priority_Node;
+
+/**
+ * @brief The priority action type.
+ */
+typedef enum {
+  PRIORITY_ACTION_ADD,
+  PRIORITY_ACTION_CHANGE,
+  PRIORITY_ACTION_REMOVE,
+  PRIORITY_ACTION_INVALID
+} Priority_Action_type;
+
+typedef struct Priority_Aggregation Priority_Aggregation;
+
+/**
+ * @brief The priority aggregation.
+ *
+ * This structure serves two purposes.  Firstly, it provides a place to
+ * register priority nodes and reflects the overall priority of its
+ * contributors.  Secondly, it provides an action block to signal addition,
+ * change and removal of a priority node.
+ */
+struct Priority_Aggregation {
+  /**
+   * @brief This priority node reflects the overall priority of the aggregation.
+   *
+   * The overall priority of the aggregation is the minimum priority of the
+   * priority nodes in the contributors tree.
+   *
+   * This priority node may be used to add this aggregation to another
+   * aggregation to build up a recursive priority scheme.
+   *
+   * In case priority nodes of the contributors tree are added, changed or
+   * removed the priority of this node may change.  To signal such changes to a
+   * priority aggregation the action block may be used.
+   */
+  Priority_Node Node;
+
+  /**
+   * @brief A red-black tree to contain priority nodes contributing to the
+   * overall priority of this priority aggregation.
+   */
+  RBTree_Control Contributors;
+
+#if defined(RTEMS_SMP)
+  /**
+   * @brief The scheduler instance of this priority aggregation.
+   */
+  const struct Scheduler_Control *scheduler;
+#endif
+
+  /**
+   * @brief A priority action block to manage priority node additions, changes
+   * and removals.
+   */
+  struct {
+#if defined(RTEMS_SMP)
+    /**
+     * @brief The next priority aggregation in the action list.
+     */
+    Priority_Aggregation *next;
+#endif
+
+    /**
+     * @brief The priority node of the action.
+     */
+    Priority_Node *node;
+
+    /**
+     * @brief The type of the action.
+     */
+    Priority_Action_type type;
+  } Action;
+};
+
+/**
+ * @brief A list of priority actions.
+ *
+ * Actions are only added to the list.  The action lists reside on the stack
+ * and have a short life-time.  They are moved, processed or destroyed as a
+ * whole.
+ */
+typedef struct {
+  /**
+   * @brief The first action of a priority action list.
+   */
+  Priority_Aggregation *actions;
+} Priority_Actions;
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/cpukit/score/include/rtems/score/priorityimpl.h b/cpukit/score/include/rtems/score/priorityimpl.h
new file mode 100644
index 0000000..0035a82
--- /dev/null
+++ b/cpukit/score/include/rtems/score/priorityimpl.h
@@ -0,0 +1,421 @@
+/*
+ * Copyright (c) 2016 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Dornierstr. 4
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#ifndef _RTEMS_SCORE_PRIORITYIMPL_H
+#define _RTEMS_SCORE_PRIORITYIMPL_H
+
+#include <rtems/score/priority.h>
+#include <rtems/score/scheduler.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+RTEMS_INLINE_ROUTINE void _Priority_Actions_initialize_empty(
+  Priority_Actions *actions
+)
+{
+  actions->actions = NULL;
+}
+
+RTEMS_INLINE_ROUTINE void _Priority_Actions_initialize_one(
+  Priority_Actions     *actions,
+  Priority_Aggregation *aggregation,
+  Priority_Node        *node,
+  Priority_Action_type  type
+)
+{
+#if defined(RTEMS_SMP)
+  aggregation->Action.next = NULL;
+#endif
+  aggregation->Action.node = node;
+  aggregation->Action.type = type;
+
+  actions->actions = aggregation;
+}
+
+RTEMS_INLINE_ROUTINE bool _Priority_Actions_is_empty(
+  const Priority_Actions *actions
+)
+{
+  return actions->actions == NULL;
+}
+
+RTEMS_INLINE_ROUTINE bool _Priority_Actions_is_valid(
+  const Priority_Aggregation *aggregation
+)
+{
+#if defined(RTEMS_SMP)
+  return aggregation != NULL;
+#else
+  (void) aggregation;
+  return false;
+#endif
+}
+
+RTEMS_INLINE_ROUTINE void _Priority_Actions_move(
+  Priority_Actions *target_actions,
+  Priority_Actions *source_actions
+)
+{
+  target_actions->actions = source_actions->actions;
+  source_actions->actions = NULL;
+}
+
+RTEMS_INLINE_ROUTINE Priority_Aggregation *_Priority_Actions_get_first(
+  const Priority_Actions *actions
+)
+{
+  return actions->actions;
+}
+
+RTEMS_INLINE_ROUTINE void _Priority_Actions_add(
+  Priority_Actions     *actions,
+  Priority_Aggregation *aggregation
+)
+{
+#if defined(RTEMS_SMP)
+  /*
+   * Priority aggregations are only added to action lists, so do not care about
+   * the current next pointer value.
+   */
+  aggregation->Action.next = actions->actions;
+#endif
+  actions->actions = aggregation;
+}
+
+RTEMS_INLINE_ROUTINE void _Priority_Node_initialize(
+  Priority_Node    *node,
+  Priority_Control  priority
+)
+{
+  node->priority = priority;
+  _RBTree_Initialize_node( &node->Node.RBTree );
+}
+
+RTEMS_INLINE_ROUTINE void _Priority_Node_set_priority(
+  Priority_Node    *node,
+  Priority_Control  priority
+)
+{
+  node->priority = priority;
+}
+
+RTEMS_INLINE_ROUTINE void _Priority_Node_set_inactive(
+  Priority_Node *node
+)
+{
+  _RBTree_Set_off_tree( &node->Node.RBTree );
+}
+
+RTEMS_INLINE_ROUTINE bool _Priority_Node_is_active(
+  const Priority_Node *node
+)
+{
+  return !_RBTree_Is_node_off_tree( &node->Node.RBTree );
+}
+
+RTEMS_INLINE_ROUTINE void _Priority_Initialize_empty(
+  Priority_Aggregation *aggregation
+)
+{
+#if defined(RTEMS_DEBUG)
+#if defined(RTEMS_SMP)
+  aggregation->Action.next = NULL;
+#endif
+  aggregation->Action.node = NULL;
+  aggregation->Action.type = PRIORITY_ACTION_INVALID;
+#endif
+  _RBTree_Initialize_node( &aggregation->Node.Node.RBTree );
+  _RBTree_Initialize_empty( &aggregation->Contributors );
+}
+
+RTEMS_INLINE_ROUTINE void _Priority_Initialize_one(
+  Priority_Aggregation *aggregation,
+  Priority_Node        *node
+)
+{
+#if defined(RTEMS_DEBUG)
+#if defined(RTEMS_SMP)
+  aggregation->Action.next = NULL;
+#endif
+  aggregation->Action.node = NULL;
+  aggregation->Action.type = PRIORITY_ACTION_INVALID;
+#endif
+  _Priority_Node_initialize( &aggregation->Node, node->priority );
+  _RBTree_Initialize_one( &aggregation->Contributors, &node->Node.RBTree );
+}
+
+RTEMS_INLINE_ROUTINE bool _Priority_Is_empty(
+  const Priority_Aggregation *aggregation
+)
+{
+  return _RBTree_Is_empty( &aggregation->Contributors );
+}
+
+RTEMS_INLINE_ROUTINE Priority_Control _Priority_Get_priority(
+  const Priority_Aggregation *aggregation
+)
+{
+  return aggregation->Node.priority;
+}
+
+RTEMS_INLINE_ROUTINE const Scheduler_Control *_Priority_Get_scheduler(
+  const Priority_Aggregation *aggregation
+)
+{
+#if defined(RTEMS_SMP)
+  return aggregation->scheduler;
+#else
+  return &_Scheduler_Table[ 0 ];
+#endif
+}
+
+RTEMS_INLINE_ROUTINE Priority_Node *_Priority_Get_minimum_node(
+  const Priority_Aggregation *aggregation
+)
+{
+  return (Priority_Node *) _RBTree_Minimum( &aggregation->Contributors );
+}
+
+RTEMS_INLINE_ROUTINE void _Priority_Set_action_node(
+  Priority_Aggregation *aggregation,
+  Priority_Node        *node
+)
+{
+  aggregation->Action.node = node;
+}
+
+RTEMS_INLINE_ROUTINE void _Priority_Set_action_type(
+  Priority_Aggregation *aggregation,
+  Priority_Action_type  type
+)
+{
+  aggregation->Action.type = type;
+}
+
+RTEMS_INLINE_ROUTINE Priority_Aggregation *_Priority_Get_next_action(
+  const Priority_Aggregation *aggregation
+)
+{
+#if defined(RTEMS_SMP)
+  return aggregation->Action.next;
+#else
+  (void) aggregation;
+  return NULL;
+#endif
+}
+
+RTEMS_INLINE_ROUTINE bool _Priority_Less(
+  const void        *left,
+  const RBTree_Node *right
+)
+{
+  const Priority_Control *the_left;
+  const Priority_Node    *the_right;
+
+  the_left = left;
+  the_right = RTEMS_CONTAINER_OF( right, Priority_Node, Node.RBTree );
+
+  return *the_left < the_right->priority;
+}
+
+RTEMS_INLINE_ROUTINE bool _Priority_Plain_insert(
+  Priority_Aggregation *aggregation,
+  Priority_Node        *node,
+  Priority_Control      priority
+)
+{
+  return _RBTree_Insert_inline(
+    &aggregation->Contributors,
+    &node->Node.RBTree,
+    &priority,
+    _Priority_Less
+  );
+}
+
+RTEMS_INLINE_ROUTINE void _Priority_Plain_extract(
+  Priority_Aggregation *aggregation,
+  Priority_Node        *node
+)
+{
+  _RBTree_Extract( &aggregation->Contributors, &node->Node.RBTree );
+}
+
+typedef void ( *Priority_Add_handler )(
+  Priority_Aggregation *aggregation,
+  Priority_Actions     *actions,
+  void                 *arg
+);
+
+typedef void ( *Priority_Change_handler )(
+  Priority_Aggregation *aggregation,
+  bool                  prepend_it,
+  Priority_Actions     *actions,
+  void                 *arg
+);
+
+typedef void ( *Priority_Remove_handler )(
+  Priority_Aggregation *aggregation,
+  Priority_Actions     *actions,
+  void                 *arg
+);
+
+RTEMS_INLINE_ROUTINE void _Priority_Change_nothing(
+  Priority_Aggregation *aggregation,
+  bool                  prepend_it,
+  Priority_Actions     *actions,
+  void                 *arg
+)
+{
+  (void) aggregation;
+  (void) prepend_it;
+  (void) actions;
+  (void) arg;
+}
+
+RTEMS_INLINE_ROUTINE void _Priority_Remove_nothing(
+  Priority_Aggregation *aggregation,
+  Priority_Actions     *actions,
+  void                 *arg
+)
+{
+  (void) aggregation;
+  (void) actions;
+  (void) arg;
+}
+
+RTEMS_INLINE_ROUTINE void _Priority_Non_empty_insert(
+  Priority_Aggregation    *aggregation,
+  Priority_Node           *node,
+  Priority_Actions        *actions,
+  Priority_Change_handler  change,
+  void                    *arg
+)
+{
+  bool is_new_minimum;
+
+  _Assert( !_Priority_Is_empty( aggregation ) );
+  is_new_minimum = _Priority_Plain_insert( aggregation, node, node->priority );
+
+  if ( is_new_minimum ) {
+    aggregation->Node.priority = node->priority;
+    ( *change )( aggregation, false, actions, arg );
+  }
+}
+
+RTEMS_INLINE_ROUTINE void _Priority_Insert(
+  Priority_Aggregation    *aggregation,
+  Priority_Node           *node,
+  Priority_Actions        *actions,
+  Priority_Add_handler     add,
+  Priority_Change_handler  change,
+  void                    *arg
+)
+{
+  if ( _Priority_Is_empty( aggregation ) ) {
+    _Priority_Initialize_one( aggregation, node );
+    ( *add )( aggregation, actions, arg );
+  } else {
+    _Priority_Non_empty_insert( aggregation, node, actions, change, arg );
+  }
+}
+
+RTEMS_INLINE_ROUTINE void _Priority_Extract(
+  Priority_Aggregation    *aggregation,
+  Priority_Node           *node,
+  Priority_Actions        *actions,
+  Priority_Remove_handler  remove,
+  Priority_Change_handler  change,
+  void                    *arg
+)
+{
+  _Priority_Plain_extract( aggregation, node );
+
+  if ( _Priority_Is_empty( aggregation ) ) {
+    ( *remove )( aggregation, actions, arg );
+  } else {
+    Priority_Node *min;
+
+    min = _Priority_Get_minimum_node( aggregation );
+
+    if ( node->priority < min->priority ) {
+      aggregation->Node.priority = min->priority;
+      ( *change )( aggregation, true, actions, arg );
+    }
+  }
+}
+
+RTEMS_INLINE_ROUTINE void _Priority_Extract_non_empty(
+  Priority_Aggregation    *aggregation,
+  Priority_Node           *node,
+  Priority_Actions        *actions,
+  Priority_Change_handler  change,
+  void                    *arg
+)
+{
+  Priority_Node *min;
+
+  _Priority_Plain_extract( aggregation, node );
+  _Assert( !_Priority_Is_empty( aggregation ) );
+
+  min = _Priority_Get_minimum_node( aggregation );
+
+  if ( node->priority < min->priority ) {
+    aggregation->Node.priority = min->priority;
+    ( *change )( aggregation, true, actions, arg );
+  }
+}
+
+RTEMS_INLINE_ROUTINE void _Priority_Change(
+  Priority_Aggregation    *aggregation,
+  Priority_Node           *node,
+  bool                     prepend_it,
+  Priority_Actions        *actions,
+  Priority_Change_handler  change,
+  void                    *arg
+)
+{
+  Priority_Node *min;
+
+  _Priority_Plain_extract( aggregation, node );
+  _Priority_Plain_insert( aggregation, node, node->priority );
+
+  min = _Priority_Get_minimum_node( aggregation );
+
+  if ( min->priority != aggregation->Node.priority ) {
+    aggregation->Node.priority = min->priority;
+    ( *change )( aggregation, prepend_it, actions, arg );
+  }
+}
+
+RTEMS_INLINE_ROUTINE void _Priority_Replace(
+  Priority_Aggregation *aggregation,
+  Priority_Node        *victim,
+  Priority_Node        *replacement
+)
+{
+  replacement->priority = victim->priority;
+  _RBTree_Replace_node(
+    &aggregation->Contributors,
+    &victim->Node.RBTree,
+    &replacement->Node.RBTree
+  );
+}
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _RTEMS_SCORE_PRIORITYIMPL_H */
diff --git a/cpukit/score/include/rtems/score/scheduler.h b/cpukit/score/include/rtems/score/scheduler.h
index bbb4e37..b934269 100644
--- a/cpukit/score/include/rtems/score/scheduler.h
+++ b/cpukit/score/include/rtems/score/scheduler.h
@@ -135,16 +135,20 @@ typedef struct {
   void ( *node_destroy )( const Scheduler_Control *, Scheduler_Node * );
 
   /** @see _Scheduler_Release_job() */
-  Thread_Control *( *release_job ) (
+  void ( *release_job ) (
     const Scheduler_Control *,
     Thread_Control *,
-    uint64_t
+    Priority_Node *,
+    uint64_t,
+    Thread_queue_Context *
   );
 
   /** @see _Scheduler_Cancel_job() */
-  Thread_Control *( *cancel_job ) (
+  void ( *cancel_job ) (
     const Scheduler_Control *,
-    Thread_Control *
+    Thread_Control *,
+    Priority_Node *,
+    Thread_queue_Context *
   );
 
   /** @see _Scheduler_Tick() */
@@ -373,14 +377,18 @@ void _Scheduler_default_Node_destroy(
  *
  * @param[in] scheduler Unused.
  * @param[in] the_thread Unused.
+ * @param[in] priority_node Unused.
  * @param[in] deadline Unused.
+ * @param[in] queue_context Unused.
  *
  * @retval NULL Always.
  */
-Thread_Control *_Scheduler_default_Release_job(
+void _Scheduler_default_Release_job(
   const Scheduler_Control *scheduler,
   Thread_Control          *the_thread,
-  uint64_t                 deadline
+  Priority_Node           *priority_node,
+  uint64_t                 deadline,
+  Thread_queue_Context    *queue_context
 );
 
 /**
@@ -388,12 +396,16 @@ Thread_Control *_Scheduler_default_Release_job(
  *
  * @param[in] scheduler Unused.
  * @param[in] the_thread Unused.
+ * @param[in] priority_node Unused.
+ * @param[in] queue_context Unused.
  *
  * @retval NULL Always.
  */
-Thread_Control *_Scheduler_default_Cancel_job(
+void _Scheduler_default_Cancel_job(
   const Scheduler_Control *scheduler,
-  Thread_Control          *the_thread
+  Thread_Control          *the_thread,
+  Priority_Node           *priority_node,
+  Thread_queue_Context    *queue_context
 );
 
 /**
diff --git a/cpukit/score/include/rtems/score/schedulercbs.h b/cpukit/score/include/rtems/score/schedulercbs.h
index c230e08..02c7b53 100644
--- a/cpukit/score/include/rtems/score/schedulercbs.h
+++ b/cpukit/score/include/rtems/score/schedulercbs.h
@@ -61,7 +61,7 @@ extern "C" {
     _Scheduler_CBS_Node_initialize,  /* node initialize entry point */ \
     _Scheduler_default_Node_destroy, /* node destroy entry point */ \
     _Scheduler_CBS_Release_job,      /* new period of task */ \
-    _Scheduler_EDF_Cancel_job,       /* cancel period of task */ \
+    _Scheduler_CBS_Cancel_job,       /* cancel period of task */ \
     _Scheduler_default_Tick,         /* tick entry point */ \
     _Scheduler_default_Start_idle    /* start idle entry point */ \
     SCHEDULER_OPERATION_DEFAULT_GET_SET_AFFINITY \
@@ -135,6 +135,8 @@ typedef struct {
   Scheduler_EDF_Node            Base;
   /** CBS server specific data of a task. */
   Scheduler_CBS_Server         *cbs_server;
+
+  Priority_Node                *deadline_node;
 } Scheduler_CBS_Node;
 
 
@@ -163,10 +165,19 @@ Scheduler_Void_or_thread _Scheduler_CBS_Unblock(
   Thread_Control          *the_thread
 );
 
-Thread_Control *_Scheduler_CBS_Release_job(
+void _Scheduler_CBS_Release_job(
+  const Scheduler_Control *scheduler,
+  Thread_Control          *the_thread,
+  Priority_Node           *priority_node,
+  uint64_t                 deadline,
+  Thread_queue_Context    *queue_context
+);
+
+void _Scheduler_CBS_Cancel_job(
   const Scheduler_Control *scheduler,
   Thread_Control          *the_thread,
-  uint64_t                 length
+  Priority_Node           *priority_node,
+  Thread_queue_Context    *queue_context
 );
 
 /**
diff --git a/cpukit/score/include/rtems/score/scheduleredf.h b/cpukit/score/include/rtems/score/scheduleredf.h
index 81b245e..ab43672 100644
--- a/cpukit/score/include/rtems/score/scheduleredf.h
+++ b/cpukit/score/include/rtems/score/scheduleredf.h
@@ -89,24 +89,14 @@ typedef struct {
   Scheduler_Node Base;
 
   /**
-   * Pointer to corresponding Thread Control Block.
-   */
-  Thread_Control *thread;
-  /**
    * Rbtree node related to this thread.
    */
   RBTree_Node Node;
 
   /**
-   * @brief The thread priority used by this scheduler instance in case no job
-   * is released.
+   * @brief The thread priority currently used for this scheduler instance.
    */
-  Priority_Control background_priority;
-
-  /**
-   * @brief The thread priority currently used by this scheduler instance.
-   */
-  Priority_Control current_priority;
+  Priority_Control priority;
 } Scheduler_EDF_Node;
 
 /**
@@ -215,15 +205,19 @@ Scheduler_Void_or_thread _Scheduler_EDF_Yield(
   Thread_Control          *the_thread
 );
 
-Thread_Control *_Scheduler_EDF_Release_job(
+void _Scheduler_EDF_Release_job(
   const Scheduler_Control *scheduler,
   Thread_Control          *the_thread,
-  uint64_t                 deadline
+  Priority_Node           *priority_node,
+  uint64_t                 deadline,
+  Thread_queue_Context    *queue_context
 );
 
-Thread_Control *_Scheduler_EDF_Cancel_job(
+void _Scheduler_EDF_Cancel_job(
   const Scheduler_Control *scheduler,
-  Thread_Control          *the_thread
+  Thread_Control          *the_thread,
+  Priority_Node           *priority_node,
+  Thread_queue_Context    *queue_context
 );
 
 #ifdef __cplusplus
diff --git a/cpukit/score/include/rtems/score/scheduleredfimpl.h b/cpukit/score/include/rtems/score/scheduleredfimpl.h
index 844d745..61acedd 100644
--- a/cpukit/score/include/rtems/score/scheduleredfimpl.h
+++ b/cpukit/score/include/rtems/score/scheduleredfimpl.h
@@ -74,7 +74,7 @@ RTEMS_INLINE_ROUTINE bool _Scheduler_EDF_Less(
   the_right = RTEMS_CONTAINER_OF( right, Scheduler_EDF_Node, Node );
 
   prio_left = *the_left;
-  prio_right = the_right->current_priority;
+  prio_right = the_right->priority;
 
   return prio_left < prio_right;
 }
@@ -93,7 +93,7 @@ RTEMS_INLINE_ROUTINE bool _Scheduler_EDF_Less_or_equal(
   the_right = RTEMS_CONTAINER_OF( right, Scheduler_EDF_Node, Node );
 
   prio_left = *the_left;
-  prio_right = the_right->current_priority;
+  prio_right = the_right->priority;
 
   return prio_left <= prio_right;
 }
@@ -101,13 +101,13 @@ RTEMS_INLINE_ROUTINE bool _Scheduler_EDF_Less_or_equal(
 RTEMS_INLINE_ROUTINE void _Scheduler_EDF_Enqueue(
   Scheduler_EDF_Context *context,
   Scheduler_EDF_Node    *node,
-  Priority_Control       current_priority
+  Priority_Control       priority
 )
 {
   _RBTree_Insert_inline(
     &context->Ready,
     &node->Node,
-    &current_priority,
+    &priority,
     _Scheduler_EDF_Less
   );
 }
@@ -115,13 +115,13 @@ RTEMS_INLINE_ROUTINE void _Scheduler_EDF_Enqueue(
 RTEMS_INLINE_ROUTINE void _Scheduler_EDF_Enqueue_first(
   Scheduler_EDF_Context *context,
   Scheduler_EDF_Node    *node,
-  Priority_Control       current_priority
+  Priority_Control       priority
 )
 {
   _RBTree_Insert_inline(
     &context->Ready,
     &node->Node,
-    &current_priority,
+    &priority,
     _Scheduler_EDF_Less_or_equal
   );
 }
@@ -164,7 +164,7 @@ RTEMS_INLINE_ROUTINE void _Scheduler_EDF_Schedule_body(
   first = _RBTree_Minimum( &context->Ready );
   node = RTEMS_CONTAINER_OF( first, Scheduler_EDF_Node, Node );
 
-  _Scheduler_Update_heir( node->thread, force_dispatch );
+  _Scheduler_Update_heir( node->Base.owner, force_dispatch );
 }
 
 /**@}*/
diff --git a/cpukit/score/include/rtems/score/schedulerimpl.h b/cpukit/score/include/rtems/score/schedulerimpl.h
index bbad6e0..dea1888 100644
--- a/cpukit/score/include/rtems/score/schedulerimpl.h
+++ b/cpukit/score/include/rtems/score/schedulerimpl.h
@@ -22,6 +22,7 @@
 
 #include <rtems/score/scheduler.h>
 #include <rtems/score/cpusetimpl.h>
+#include <rtems/score/priorityimpl.h>
 #include <rtems/score/smpimpl.h>
 #include <rtems/score/status.h>
 #include <rtems/score/threadimpl.h>
@@ -99,17 +100,6 @@ RTEMS_INLINE_ROUTINE const Scheduler_Control *_Scheduler_Get_by_CPU(
   return _Scheduler_Get_by_CPU_index( cpu_index );
 }
 
-RTEMS_INLINE_ROUTINE Scheduler_Node *_Scheduler_Thread_get_own_node(
-  const Thread_Control *the_thread
-)
-{
-#if defined(RTEMS_SMP)
-  return the_thread->Scheduler.own_node;
-#else
-  return the_thread->Scheduler.node;
-#endif
-}
-
 ISR_LOCK_DECLARE( extern, _Scheduler_Lock )
 
 /**
@@ -264,7 +254,7 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Ask_for_help_if_necessary(
     needs_help != NULL
       && _Resource_Node_owns_resources( &needs_help->Resource_node )
   ) {
-    Scheduler_Node *node = _Scheduler_Thread_get_own_node( needs_help );
+    Scheduler_Node *node = _Thread_Scheduler_get_own_node( needs_help );
 
     if (
       node->help_state != SCHEDULER_HELP_ACTIVE_RIVAL
@@ -486,21 +476,27 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Node_destroy(
  * @brief Releases a job of a thread with respect to the scheduler.
  *
  * @param[in] the_thread The thread.
+ * @param[in] priority_node The priority node of the job.
  * @param[in] deadline The deadline in watchdog ticks since boot.
- *
- * @return The thread to hand over to _Thread_Update_priority().
+ * @param[in] queue_context The thread queue context to provide the set of
+ *   threads for _Thread_Priority_update().
  */
-RTEMS_INLINE_ROUTINE Thread_Control *_Scheduler_Release_job(
-  Thread_Control *the_thread,
-  uint64_t        deadline
+RTEMS_INLINE_ROUTINE void _Scheduler_Release_job(
+  Thread_Control       *the_thread,
+  Priority_Node        *priority_node,
+  uint64_t              deadline,
+  Thread_queue_Context *queue_context
 )
 {
   const Scheduler_Control *scheduler = _Scheduler_Get( the_thread );
 
-  return ( *scheduler->Operations.release_job )(
+  _Thread_queue_Context_clear_priority_updates( queue_context );
+  ( *scheduler->Operations.release_job )(
     scheduler,
     the_thread,
-    deadline
+    priority_node,
+    deadline,
+    queue_context
   );
 }
 
@@ -508,16 +504,25 @@ RTEMS_INLINE_ROUTINE Thread_Control *_Scheduler_Release_job(
  * @brief Cancels a job of a thread with respect to the scheduler.
  *
  * @param[in] the_thread The thread.
- *
- * @return The thread to hand over to _Thread_Update_priority().
+ * @param[in] priority_node The priority node of the job.
+ * @param[in] queue_context The thread queue context to provide the set of
+ *   threads for _Thread_Priority_update().
  */
-RTEMS_INLINE_ROUTINE Thread_Control *_Scheduler_Cancel_job(
-  Thread_Control *the_thread
+RTEMS_INLINE_ROUTINE void _Scheduler_Cancel_job(
+  Thread_Control       *the_thread,
+  Priority_Node        *priority_node,
+  Thread_queue_Context *queue_context
 )
 {
   const Scheduler_Control *scheduler = _Scheduler_Get( the_thread );
 
-  return ( *scheduler->Operations.cancel_job )( scheduler, the_thread );
+  _Thread_queue_Context_clear_priority_updates( queue_context );
+  ( *scheduler->Operations.cancel_job )(
+    scheduler,
+    the_thread,
+    priority_node,
+    queue_context
+  );
 }
 
 /**
@@ -776,12 +781,10 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Thread_set_priority(
   bool              prepend_it
 )
 {
-  Scheduler_Node *own_node;
-
-  own_node = _Scheduler_Thread_get_own_node( the_thread );
-  _Scheduler_Node_set_priority( own_node, new_priority, prepend_it );
+  Scheduler_Node *scheduler_node;
 
-  the_thread->current_priority = new_priority;
+  scheduler_node = _Thread_Scheduler_get_own_node( the_thread );
+  _Scheduler_Node_set_priority( scheduler_node, new_priority, prepend_it );
 }
 
 #if defined(RTEMS_SMP)
@@ -857,7 +860,7 @@ RTEMS_INLINE_ROUTINE Scheduler_Help_state _Scheduler_Thread_change_help_state(
   Scheduler_Help_state  new_help_state
 )
 {
-  Scheduler_Node *node = _Scheduler_Thread_get_own_node( the_thread );
+  Scheduler_Node *node = _Thread_Scheduler_get_own_node( the_thread );
   Scheduler_Help_state previous_help_state = node->help_state;
 
   node->help_state = new_help_state;
@@ -1294,7 +1297,7 @@ RTEMS_INLINE_ROUTINE Thread_Control *_Scheduler_Ask_scheduled_node_for_help(
     _Scheduler_Thread_change_state( old_user, THREAD_SCHEDULER_READY );
     _Scheduler_Thread_set_scheduler_and_node(
       old_user,
-      _Scheduler_Thread_get_own_node( old_user ),
+      _Thread_Scheduler_get_own_node( old_user ),
       old_user
     );
 
@@ -1383,11 +1386,24 @@ RTEMS_INLINE_ROUTINE Status_Control _Scheduler_Set(
     return STATUS_RESOURCE_IN_USE;
   }
 
-  the_thread->current_priority = priority;
-  the_thread->real_priority = priority;
-  the_thread->Start.initial_priority = priority;
+  own_node = _Thread_Scheduler_get_own_node( the_thread );
+  _Priority_Plain_extract( &own_node->Wait.Priority, &the_thread->Real_priority );
 
-  own_node = _Scheduler_Thread_get_own_node( the_thread );
+  if ( !_Priority_Is_empty( &own_node->Wait.Priority ) ) {
+    _Priority_Plain_insert(
+      &own_node->Wait.Priority,
+      &the_thread->Real_priority,
+      the_thread->Real_priority.priority
+    );
+    return STATUS_RESOURCE_IN_USE;
+  }
+
+  the_thread->Start.initial_priority = priority;
+  _Priority_Node_set_priority( &the_thread->Real_priority, priority );
+  _Priority_Initialize_one(
+    &own_node->Wait.Priority,
+    &the_thread->Real_priority
+  );
 
 #if defined(RTEMS_SMP)
   {
diff --git a/cpukit/score/include/rtems/score/schedulernode.h b/cpukit/score/include/rtems/score/schedulernode.h
index 293887c..7ba0064 100644
--- a/cpukit/score/include/rtems/score/schedulernode.h
+++ b/cpukit/score/include/rtems/score/schedulernode.h
@@ -144,24 +144,7 @@ typedef struct {
    * @brief Thread wait support block.
    */
   struct {
-    /**
-     * @brief Node for thread queues.
-     *
-     * Each scheduler node can be enqueued on a thread queue on behalf of the
-     * thread owning the scheduler node.  The scheduler node reflects the
-     * priority of the thread within the corresponding scheduler instance.
-     */
-    union {
-      /**
-       * @brief A node for chains.
-       */
-      Chain_Node Chain;
-
-      /**
-       * @brief A node for red-black trees.
-       */
-      RBTree_Node RBTree;
-    } Node;
+    Priority_Aggregation Priority;
   } Wait;
 
   /**
diff --git a/cpukit/score/include/rtems/score/schedulernodeimpl.h b/cpukit/score/include/rtems/score/schedulernodeimpl.h
index ecb61c2..766e2f6 100644
--- a/cpukit/score/include/rtems/score/schedulernodeimpl.h
+++ b/cpukit/score/include/rtems/score/schedulernodeimpl.h
@@ -17,20 +17,20 @@
 
 #include <rtems/score/schedulernode.h>
 
+struct Scheduler_Control;
+
 #ifdef __cplusplus
 extern "C" {
 #endif /* __cplusplus */
 
-#define SCHEDULER_NODE_OF_WAIT_CHAIN_NODE( node ) \
-  RTEMS_CONTAINER_OF( node, Scheduler_Node, Wait.Node.Chain )
-
-#define SCHEDULER_NODE_OF_WAIT_RBTREE_NODE( node ) \
-  RTEMS_CONTAINER_OF( node, Scheduler_Node, Wait.Node.RBTree )
+#define SCHEDULER_NODE_OF_WAIT_PRIORITY_NODE( node ) \
+  RTEMS_CONTAINER_OF( node, Scheduler_Node, Wait.Priority.Node )
 
 RTEMS_INLINE_ROUTINE void _Scheduler_Node_do_initialize(
-  Scheduler_Node   *node,
-  Thread_Control   *the_thread,
-  Priority_Control  priority
+  const struct Scheduler_Control *scheduler,
+  Scheduler_Node                 *node,
+  Thread_Control                 *the_thread,
+  Priority_Control                priority
 )
 {
   node->owner = the_thread;
@@ -39,12 +39,14 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Node_do_initialize(
   node->Priority.prepend_it = false;
 
 #if defined(RTEMS_SMP)
+  node->Wait.Priority.scheduler = scheduler;
   node->user = the_thread;
   node->help_state = SCHEDULER_HELP_YOURSELF;
   node->idle = NULL;
   node->accepts_help = the_thread;
   _SMP_sequence_lock_Initialize( &node->Priority.Lock );
 #else
+  (void) scheduler;
   (void) the_thread;
 #endif
 }
diff --git a/cpukit/score/include/rtems/score/schedulersmpimpl.h b/cpukit/score/include/rtems/score/schedulersmpimpl.h
index ae1941a..035df46 100644
--- a/cpukit/score/include/rtems/score/schedulersmpimpl.h
+++ b/cpukit/score/include/rtems/score/schedulersmpimpl.h
@@ -375,7 +375,7 @@ static inline Scheduler_SMP_Node *_Scheduler_SMP_Thread_get_own_node(
   Thread_Control *thread
 )
 {
-  return (Scheduler_SMP_Node *) _Scheduler_Thread_get_own_node( thread );
+  return (Scheduler_SMP_Node *) _Thread_Scheduler_get_own_node( thread );
 }
 
 static inline Scheduler_SMP_Node *_Scheduler_SMP_Node_downcast(
@@ -386,12 +386,13 @@ static inline Scheduler_SMP_Node *_Scheduler_SMP_Node_downcast(
 }
 
 static inline void _Scheduler_SMP_Node_initialize(
-  Scheduler_SMP_Node *node,
-  Thread_Control     *thread,
-  Priority_Control    priority
+  const Scheduler_Control *scheduler,
+  Scheduler_SMP_Node      *node,
+  Thread_Control          *thread,
+  Priority_Control         priority
 )
 {
-  _Scheduler_Node_do_initialize( &node->Base, thread, priority );
+  _Scheduler_Node_do_initialize( scheduler, &node->Base, thread, priority );
   node->state = SCHEDULER_SMP_NODE_BLOCKED;
   node->priority = priority;
 }
diff --git a/cpukit/score/include/rtems/score/thread.h b/cpukit/score/include/rtems/score/thread.h
index 2cd229f..393d431 100644
--- a/cpukit/score/include/rtems/score/thread.h
+++ b/cpukit/score/include/rtems/score/thread.h
@@ -373,7 +373,7 @@ typedef struct {
    *
    * The thread wait lock mechanism protects the following thread variables
    *  - POSIX_API_Control::Attributes,
-   *  - Thread_Control::current_priority,
+   *  - Scheduler_Node::Wait,
    *  - Thread_Control::Wait::Lock::Pending_requests,
    *  - Thread_Control::Wait::queue, and
    *  - Thread_Control::Wait::operations.
@@ -461,32 +461,11 @@ typedef struct {
 
   /** This field is the current execution state of this proxy. */
   States_Control           current_state;
-  /**
-   * @brief This field is the current priority state of this thread.
-   *
-   * Writes to this field are only allowed in _Thread_Initialize() or via
-   * _Thread_Change_priority().
-   */
-  Priority_Control         current_priority;
 
   /**
-   * @brief This field is the base priority of this thread.
-   *
-   * Writes to this field are only allowed in _Thread_Initialize() or via
-   * _Thread_Change_priority().
+   * @brief The base priority of this thread in its home scheduler instance.
    */
-  Priority_Control         real_priority;
-
-  /**
-   * @brief Hints if a priority restore is necessary once the resource count
-   * changes from one to zero.
-   *
-   * This is an optimization to speed up the mutex surrender sequence in case
-   * no attempt to change the priority was made during the mutex ownership.  On
-   * SMP configurations atomic fences must synchronize writes to
-   * Thread_Control::priority_restore_hint and Thread_Control::resource_count.
-   */
-  bool                     priority_restore_hint;
+  Priority_Node            Real_priority;
 
   /** This field is the number of mutexes currently held by this proxy. */
   uint32_t                 resource_count;
@@ -708,31 +687,9 @@ struct _Thread_Control {
   States_Control           current_state;
 
   /**
-   * @brief This field is the current priority state of this thread.
-   *
-   * Writes to this field are only allowed in _Thread_Initialize() or via
-   * _Thread_Change_priority().
-   */
-  Priority_Control         current_priority;
-
-  /**
-   * @brief This field is the base priority of this thread.
-   *
-   * Writes to this field are only allowed in _Thread_Initialize() or via
-   * _Thread_Change_priority().
-   */
-  Priority_Control         real_priority;
-
-  /**
-   * @brief Hints if a priority restore is necessary once the resource count
-   * changes from one to zero.
-   *
-   * This is an optimization to speed up the mutex surrender sequence in case
-   * no attempt to change the priority was made during the mutex ownership.  On
-   * SMP configurations atomic fences must synchronize writes to
-   * Thread_Control::priority_restore_hint and Thread_Control::resource_count.
+   * @brief The base priority of this thread in its home scheduler instance.
    */
-  bool                     priority_restore_hint;
+  Priority_Node            Real_priority;
 
   /** This field is the number of mutexes currently held by this thread. */
   uint32_t                 resource_count;
diff --git a/cpukit/score/include/rtems/score/threadimpl.h b/cpukit/score/include/rtems/score/threadimpl.h
index 1fce842..63ef82c 100644
--- a/cpukit/score/include/rtems/score/threadimpl.h
+++ b/cpukit/score/include/rtems/score/threadimpl.h
@@ -415,128 +415,185 @@ RTEMS_INLINE_ROUTINE bool _Thread_State_is_owner(
 #endif
 
 /**
- * @brief Returns true if the left thread priority is less than the right
- * thread priority in the intuitive sense of priority and false otherwise.
+ * @brief Performs the priority actions specified by the thread queue context
+ * along the thread queue path.
+ *
+ * The caller must be the owner of the thread wait lock.
+ *
+ * @param start_of_path The start thread of the thread queue path.
+ * @param queue_context The thread queue context specifying the thread queue
+ *   path and initial thread priority actions.
+ *
+ * @see _Thread_queue_Path_acquire_critical().
  */
-RTEMS_INLINE_ROUTINE bool _Thread_Priority_less_than(
-  Priority_Control left,
-  Priority_Control right
-)
-{
-  return left > right;
-}
+void _Thread_Priority_perform_actions(
+  Thread_Control       *start_of_path,
+  Thread_queue_Context *queue_context
+);
 
 /**
- * @brief Returns the highest priority of the left and right thread priorities
- * in the intuitive sense of priority.
+ * @brief Adds the specified thread priority node to the corresponding thread
+ * priority aggregation.
+ *
+ * The caller must be the owner of the thread wait lock.
+ *
+ * @param the_thread The thread.
+ * @param priority_node The thread priority node to add.
+ * @param queue_context The thread queue context to return an updated set of
+ *   threads for _Thread_Priority_update().  The thread queue context must be
+ *   initialized via _Thread_queue_Context_clear_priority_updates() before a
+ *   call of this function.
+ *
+ * @see _Thread_Wait_acquire().
  */
-RTEMS_INLINE_ROUTINE Priority_Control _Thread_Priority_highest(
-  Priority_Control left,
-  Priority_Control right
-)
-{
-  return _Thread_Priority_less_than( left, right ) ? right : left;
-}
+void _Thread_Priority_add(
+  Thread_Control       *the_thread,
+  Priority_Node        *priority_node,
+  Thread_queue_Context *queue_context
+);
 
 /**
- * @brief Filters a thread priority change.
+ * @brief Removes the specified thread priority node from the corresponding
+ * thread priority aggregation.
  *
- * Called by _Thread_Change_priority() under the protection of the thread lock.
+ * The caller must be the owner of the thread wait lock.
  *
- * @param[in] the_thread The thread.
- * @param[in, out] new_priority The new priority of the thread.  The filter may
- * alter this value.
- * @param[in] arg The argument passed to _Thread_Change_priority().
+ * @param the_thread The thread.
+ * @param priority_node The thread priority node to remove.
+ * @param queue_context The thread queue context to return an updated set of
+ *   threads for _Thread_Priority_update().  The thread queue context must be
+ *   initialized via _Thread_queue_Context_clear_priority_updates() before a
+ *   call of this function.
  *
- * @retval true Change the current priority.
- * @retval false Otherwise.
+ * @see _Thread_Wait_acquire().
  */
-typedef bool ( *Thread_Change_priority_filter )(
-  Thread_Control   *the_thread,
-  Priority_Control *new_priority,
-  void             *arg
-);
-
-Thread_Control *_Thread_Apply_priority(
-  Thread_Control                *the_thread,
-  Priority_Control               new_priority,
-  void                          *arg,
-  Thread_Change_priority_filter  filter,
-  bool                           prepend_it
+void _Thread_Priority_remove(
+  Thread_Control       *the_thread,
+  Priority_Node        *priority_node,
+  Thread_queue_Context *queue_context
 );
 
-void _Thread_Update_priority( Thread_Control *the_thread );
-
 /**
- * @brief Changes the priority of a thread if allowed by the filter function.
+ * @brief Propagates a thread priority value change in the specified thread
+ * priority node to the corresponding thread priority aggregation.
  *
- * It changes current priority of the thread to the new priority in case the
- * filter function returns true.  In this case the scheduler is notified of the
- * priority change as well.
+ * The caller must be the owner of the thread wait lock.
  *
- * @param[in] the_thread The thread.
- * @param[in] new_priority The new priority of the thread.
- * @param[in] arg The argument for the filter function.
- * @param[in] filter The filter function to determine if a priority change is
- * allowed and optionally perform other actions under the protection of the
- * thread lock simultaneously with the update of the current priority.
- * @param[in] prepend_it In case this is true, then the thread is prepended to
- * its priority group in its scheduler instance, otherwise it is appended.
- */
-void _Thread_Change_priority(
-  Thread_Control                *the_thread,
-  Priority_Control               new_priority,
-  void                          *arg,
-  Thread_Change_priority_filter  filter,
-  bool                           prepend_it
+ * @param the_thread The thread.
+ * @param priority_node The thread priority node to change.
+ * @param prepend_it In case this is true, then the thread is prepended to
+ *   its priority group in its home scheduler instance, otherwise it is
+ *   appended.
+ * @param queue_context The thread queue context to return an updated set of
+ *   threads for _Thread_Priority_update().  The thread queue context must be
+ *   initialized via _Thread_queue_Context_clear_priority_updates() before a
+ *   call of this function.
+ *
+ * @see _Thread_Wait_acquire().
+ */
+void _Thread_Priority_changed(
+  Thread_Control       *the_thread,
+  Priority_Node        *priority_node,
+  bool                  prepend_it,
+  Thread_queue_Context *queue_context
 );
 
 /**
- * @brief Raises the priority of a thread.
+ * @brief Changes the thread priority value of the specified thread priority
+ * node in the corresponding thread priority aggregation.
  *
- * It changes the current priority of the thread to the new priority if the new
- * priority is higher than the current priority.  In this case the thread is
- * appended to its new priority group in its scheduler instance.
+ * The caller must be the owner of the thread wait lock.
  *
- * @param[in] the_thread The thread.
- * @param[in] new_priority The new priority of the thread.
+ * @param the_thread The thread.
+ * @param priority_node The thread priority node to change.
+ * @param new_priority The new thread priority value of the thread priority
+ *   node to change.
+ * @param prepend_it In case this is true, then the thread is prepended to
+ *   its priority group in its home scheduler instance, otherwise it is
+ *   appended.
+ * @param queue_context The thread queue context to return an updated set of
+ *   threads for _Thread_Priority_update().  The thread queue context must be
+ *   initialized via _Thread_queue_Context_clear_priority_updates() before a
+ *   call of this function.
  *
- * @see _Thread_Change_priority().
+ * @see _Thread_Wait_acquire().
  */
-void _Thread_Raise_priority(
-  Thread_Control   *the_thread,
-  Priority_Control  new_priority
-);
+RTEMS_INLINE_ROUTINE void _Thread_Priority_change(
+  Thread_Control       *the_thread,
+  Priority_Node        *priority_node,
+  Priority_Control      new_priority,
+  bool                  prepend_it,
+  Thread_queue_Context *queue_context
+)
+{
+  _Priority_Node_set_priority( priority_node, new_priority );
+  _Thread_Priority_changed(
+    the_thread,
+    priority_node,
+    prepend_it,
+    queue_context
+  );
+}
 
 /**
- * @brief Sets the current to the real priority of a thread.
+ * @brief Replaces the victim priority node with the replacement priority node
+ * in the corresponding thread priority aggregation.
+ *
+ * The caller must be the owner of the thread wait lock.
  *
- * Sets the priority restore hint to false.
+ * @param the_thread The thread.
+ * @param victim_node The victim thread priority node.
+ * @param replacement_node The replacement thread priority node.
+ *
+ * @see _Thread_Wait_acquire().
  */
-void _Thread_Restore_priority( Thread_Control *the_thread );
+void _Thread_Priority_replace(
+  Thread_Control *the_thread,
+  Priority_Node  *victim_node,
+  Priority_Node  *replacement_node
+);
 
 /**
- * @brief Sets the priority of a thread.
+ * @brief Adds a priority node to the corresponding thread priority
+ * aggregation.
  *
- * It sets the real priority of the thread.  In addition it changes the current
- * priority of the thread if the new priority is higher than the current
- * priority or the thread owns no resources.
+ * The caller must be the owner of the thread wait lock.
  *
- * @param[in] the_thread The thread.
- * @param[in] new_priority The new priority of the thread.
- * @param[out] old_priority The old real priority of the thread.  This pointer
- * must not be @c NULL.
- * @param[in] prepend_it In case this is true, then the thread is prepended to
- * its priority group in its scheduler instance, otherwise it is appended.
+ * @param the_thread The thread.
+ * @param priority_node The thread priority node to add.
+ * @param queue_context The thread queue context to return an updated set of
+ *   threads for _Thread_Priority_update().  The thread queue context must be
+ *   initialized via _Thread_queue_Context_clear_priority_updates() before a
+ *   call of this function.
  *
- * @see _Thread_Change_priority().
+ * @see _Thread_Priority_add(), _Thread_Priority_change(),
+ *   _Thread_Priority_changed() and _Thread_Priority_remove().
  */
-void _Thread_Set_priority(
-  Thread_Control   *the_thread,
-  Priority_Control  new_priority,
-  Priority_Control *old_priority,
-  bool              prepend_it
-);
+void _Thread_Priority_update( Thread_queue_Context *queue_context );
+
+/**
+ * @brief Returns true if the left thread priority is less than the right
+ * thread priority in the intuitive sense of priority and false otherwise.
+ */
+RTEMS_INLINE_ROUTINE bool _Thread_Priority_less_than(
+  Priority_Control left,
+  Priority_Control right
+)
+{
+  return left > right;
+}
+
+/**
+ * @brief Returns the highest priority of the left and right thread priorities
+ * in the intuitive sense of priority.
+ */
+RTEMS_INLINE_ROUTINE Priority_Control _Thread_Priority_highest(
+  Priority_Control left,
+  Priority_Control right
+)
+{
+  return _Thread_Priority_less_than( left, right ) ? right : left;
+}
 
 RTEMS_INLINE_ROUTINE Objects_Information *_Thread_Get_objects_information(
   Objects_Id id
@@ -929,6 +986,17 @@ RTEMS_INLINE_ROUTINE bool _Thread_Owns_resources(
   return owns_resources;
 }
 
+RTEMS_INLINE_ROUTINE Scheduler_Node *_Thread_Scheduler_get_own_node(
+  const Thread_Control *the_thread
+)
+{
+#if defined(RTEMS_SMP)
+  return the_thread->Scheduler.own_node;
+#else
+  return the_thread->Scheduler.node;
+#endif
+}
+
 /**
  * @brief Returns the priority of the thread.
  *
@@ -937,14 +1005,15 @@ RTEMS_INLINE_ROUTINE bool _Thread_Owns_resources(
  * protocols, a job release or the POSIX sporadic server for example.
  *
  * @return The priority of the thread.
- *
- * @see _Scheduler_Node_get_priority().
  */
 RTEMS_INLINE_ROUTINE Priority_Control _Thread_Get_priority(
   const Thread_Control *the_thread
 )
 {
-  return the_thread->current_priority;
+  Scheduler_Node *scheduler_node;
+
+  scheduler_node = _Thread_Scheduler_get_own_node( the_thread );
+  return scheduler_node->Wait.Priority.Node.priority;
 }
 
 /**
@@ -1389,7 +1458,11 @@ RTEMS_INLINE_ROUTINE void _Thread_Wait_cancel(
     _Assert( queue_context->Lock_context.Wait.queue == queue );
 #endif
 
-    ( *the_thread->Wait.operations->extract )( queue, the_thread );
+    ( *the_thread->Wait.operations->extract )(
+      queue,
+      the_thread,
+      queue_context
+    );
     _Thread_Wait_restore_default( the_thread );
 
 #if defined(RTEMS_SMP)
diff --git a/cpukit/score/include/rtems/score/threadq.h b/cpukit/score/include/rtems/score/threadq.h
index a4ad082..c370465 100644
--- a/cpukit/score/include/rtems/score/threadq.h
+++ b/cpukit/score/include/rtems/score/threadq.h
@@ -47,8 +47,6 @@ typedef struct Thread_queue_Queue Thread_queue_Queue;
 
 typedef struct Thread_queue_Operations Thread_queue_Operations;
 
-typedef struct Thread_queue_Path Thread_queue_Path;
-
 /**
  * @brief Thread queue deadlock callout.
  *
@@ -195,6 +193,56 @@ typedef struct {
    */
   uint64_t timeout;
 
+#if defined(RTEMS_SMP)
+  /**
+   * @brief Representation of a thread queue path from a start thread queue to
+   * the terminal thread queue.
+   *
+   * The start thread queue is determined by the object on which a thread intends
+   * to block.  The terminal thread queue is the thread queue reachable via
+   * thread queue links whose owner is not blocked on a thread queue.  The thread
+   * queue links are determined by the thread queue owner and thread wait queue
+   * relationships.
+   */
+  struct {
+    /**
+     * @brief The chain of thread queue links defining the thread queue path.
+     */
+    Chain_Control Links;
+
+    /**
+     * @brief The start of a thread queue path.
+     */
+    Thread_queue_Link Start;
+  } Path;
+#endif
+
+  /**
+   * @brief Block to manage thread priority changes due to a thread queue
+   * operation.
+   */
+  struct {
+    /**
+     * @brief A priority action list.
+     */
+    Priority_Actions Actions;
+
+    /**
+     * @brief Count of threads to update the priority via
+     * _Thread_Priority_update().
+     */
+    size_t update_count;
+
+    /**
+     * @brief Threads to update the priority via _Thread_Priority_update().
+     *
+     * Currently, a maximum of two threads need an update in one rush, for
+     * example the thread of the thread queue operation and the owner of the
+     * thread queue.
+     */
+    Thread_Control *update[ 2 ];
+  } Priority;
+
   /**
    * @brief Invoked in case of a detected deadlock.
    *
@@ -237,7 +285,7 @@ typedef struct {
   /**
    * @brief The actual thread priority queue.
    */
-  RBTree_Control Queue;
+  Priority_Aggregation Queue;
 } Thread_queue_Priority_queue;
 
 /**
@@ -289,6 +337,11 @@ typedef struct _Thread_queue_Heads {
 
 #if defined(RTEMS_SMP)
   /**
+   * @brief Boost priority.
+   */
+  Priority_Node Boost_priority;
+
+  /**
    * @brief One priority queue per scheduler instance.
    */
   Thread_queue_Priority_queue Priority[ RTEMS_ZERO_LENGTH_ARRAY ];
@@ -337,34 +390,33 @@ struct Thread_queue_Queue {
 };
 
 /**
- * @brief Thread queue priority change operation.
+ * @brief Thread queue action operation.
  *
  * @param[in] queue The actual thread queue.
  * @param[in] the_thread The thread.
- * @param[in] new_priority The new priority value.
- *
- * @see Thread_queue_Operations.
+ * @param[in] queue_context The thread queue context providing the thread queue
+ *   action set to perform.  Returns the thread queue action set to perform on
+ *   the thread queue owner or the empty set in case there is nothing to do.
  */
-typedef void ( *Thread_queue_Priority_change_operation )(
-  Thread_queue_Queue *queue,
-  Thread_Control     *the_thread,
-  Priority_Control    new_priority
+typedef void ( *Thread_queue_Priority_actions_operation )(
+  Thread_queue_Queue   *queue,
+  Priority_Actions     *priority_actions
 );
 
 /**
  * @brief Thread queue enqueue operation.
  *
  * A potential thread to update the priority due to priority inheritance is
- * returned via the thread queue path.  This thread is handed over to
- * _Thread_Update_priority().
+ * returned via the thread queue context.  This thread is handed over to
+ * _Thread_Priority_update().
  *
  * @param[in] queue The actual thread queue.
  * @param[in] the_thread The thread to enqueue on the queue.
  */
 typedef void ( *Thread_queue_Enqueue_operation )(
-  Thread_queue_Queue *queue,
-  Thread_Control     *the_thread,
-  Thread_queue_Path  *path
+  Thread_queue_Queue   *queue,
+  Thread_Control       *the_thread,
+  Thread_queue_Context *queue_context
 );
 
 /**
@@ -374,8 +426,9 @@ typedef void ( *Thread_queue_Enqueue_operation )(
  * @param[in] the_thread The thread to extract from the thread queue.
  */
 typedef void ( *Thread_queue_Extract_operation )(
-  Thread_queue_Queue *queue,
-  Thread_Control     *the_thread
+  Thread_queue_Queue   *queue,
+  Thread_Control       *the_thread,
+  Thread_queue_Context *queue_context
 );
 
 /**
@@ -390,9 +443,10 @@ typedef void ( *Thread_queue_Extract_operation )(
  * @return The previous first thread on the queue.
  */
 typedef Thread_Control *( *Thread_queue_Surrender_operation )(
-  Thread_queue_Queue *queue,
-  Thread_queue_Heads *heads,
-  Thread_Control     *previous_owner
+  Thread_queue_Queue   *queue,
+  Thread_queue_Heads   *heads,
+  Thread_Control       *previous_owner,
+  Thread_queue_Context *queue_context
 );
 
 /**
@@ -415,16 +469,9 @@ typedef Thread_Control *( *Thread_queue_First_operation )(
  */
 struct Thread_queue_Operations {
   /**
-   * @brief Thread queue priority change operation.
-   *
-   * Called by _Thread_Change_priority() to notify a thread about a priority
-   * change.  In case this thread waits currently for a resource the handler
-   * may adjust its data structures according to the new priority value.  This
-   * handler must not be NULL, instead the default handler
-   * _Thread_Do_nothing_priority_change() should be used in case nothing needs
-   * to be done during a priority change.
-   */
-  Thread_queue_Priority_change_operation priority_change;
+   * @brief Thread queue priority actions operation.
+   */
+  Thread_queue_Priority_actions_operation priority_actions;
 
   /**
    * @brief Thread queue enqueue operation.
diff --git a/cpukit/score/include/rtems/score/threadqimpl.h b/cpukit/score/include/rtems/score/threadqimpl.h
index 977b0ce..91c7f25 100644
--- a/cpukit/score/include/rtems/score/threadqimpl.h
+++ b/cpukit/score/include/rtems/score/threadqimpl.h
@@ -21,7 +21,7 @@
 
 #include <rtems/score/threadq.h>
 #include <rtems/score/chainimpl.h>
-#include <rtems/score/rbtreeimpl.h>
+#include <rtems/score/priorityimpl.h>
 #include <rtems/score/scheduler.h>
 #include <rtems/score/smp.h>
 #include <rtems/score/thread.h>
@@ -39,38 +39,8 @@ extern "C" {
  */
 /**@{*/
 
-/**
- * @brief Representation of a thread queue path from a start thread queue to
- * the terminal thread queue.
- *
- * The start thread queue is determined by the object on which a thread intends
- * to block.  The terminal thread queue is the thread queue reachable via
- * thread queue links those owner is not blocked on a thread queue.  The thread
- * queue links are determined by the thread queue owner and thread wait queue
- * relationships.
- */
-struct Thread_queue_Path {
-#if defined(RTEMS_SMP)
-  /**
-   * @brief The chain of thread queue links defining the thread queue path.
-   */
-  Chain_Control Links;
-
-  /**
-   * @brief The start of a thread queue path.
-   */
-  Thread_queue_Link Start;
-#endif
-
-  /**
-   * @brief A potential thread to update the priority via
-   * _Thread_Update_priority().
-   *
-   * This thread is determined by thread queues which support priority
-   * inheritance.
-   */
-  Thread_Control *update_priority;
-};
+#define THREAD_QUEUE_LINK_OF_PATH_NODE( node ) \
+  RTEMS_CONTAINER_OF( node, Thread_queue_Link, Path_node );
 
 /**
  * @brief Thread queue with a layout compatible to struct _Thread_queue_Queue
@@ -210,6 +180,42 @@ RTEMS_INLINE_ROUTINE void _Thread_queue_Context_set_deadlock_callout(
   queue_context->deadlock_callout = deadlock_callout;
 }
 
+RTEMS_INLINE_ROUTINE void _Thread_queue_Context_clear_priority_updates(
+  Thread_queue_Context *queue_context
+)
+{
+  queue_context->Priority.update_count = 0;
+}
+
+RTEMS_INLINE_ROUTINE size_t _Thread_queue_Context_save_priority_updates(
+  Thread_queue_Context *queue_context
+)
+{
+  return queue_context->Priority.update_count;
+}
+
+RTEMS_INLINE_ROUTINE void _Thread_queue_Context_restore_priority_updates(
+  Thread_queue_Context *queue_context,
+  size_t                update_count
+)
+{
+  queue_context->Priority.update_count = update_count;
+}
+
+RTEMS_INLINE_ROUTINE void _Thread_queue_Context_add_priority_update(
+  Thread_queue_Context *queue_context,
+  Thread_Control       *the_thread
+)
+{
+  size_t n;
+
+  n = queue_context->Priority.update_count;
+  _Assert( n < RTEMS_ARRAY_SIZE( queue_context->Priority.update ) );
+
+  queue_context->Priority.update_count = n + 1;
+  queue_context->Priority.update[ n ] = the_thread;
+}
+
 /**
  * @brief Sets the MP callout in the thread queue context.
  *
@@ -274,9 +280,12 @@ RTEMS_INLINE_ROUTINE void _Thread_queue_Heads_initialize(
 #if defined(RTEMS_SMP)
   size_t i;
 
+  _Priority_Node_initialize( &heads->Boost_priority, 0 );
+  _Priority_Node_set_inactive( &heads->Boost_priority );
+
   for ( i = 0; i < _Scheduler_Count; ++i ) {
     _Chain_Initialize_node( &heads->Priority[ i ].Node );
-    _RBTree_Initialize_empty( &heads->Priority[ i ].Queue );
+    _Priority_Initialize_empty( &heads->Priority[ i ].Queue );
   }
 #endif
 
@@ -579,16 +588,6 @@ RTEMS_INLINE_ROUTINE void _Thread_queue_Enqueue(
   );
 }
 
-bool _Thread_queue_Do_extract_locked(
-  Thread_queue_Queue            *queue,
-  const Thread_queue_Operations *operations,
-  Thread_Control                *the_thread
-#if defined(RTEMS_MULTIPROCESSING)
-  ,
-  const Thread_queue_Context    *queue_context
-#endif
-);
-
 /**
  * @brief Extracts the thread from the thread queue, restores the default wait
  * operations and restores the default thread lock.
@@ -599,8 +598,7 @@ bool _Thread_queue_Do_extract_locked(
  * @param[in] queue The actual thread queue.
  * @param[in] operations The thread queue operations.
  * @param[in] the_thread The thread to extract.
- * @param[in] queue_context The thread queue context.  This parameter is only
- *   used on multiprocessing configurations.
+ * @param[in] queue_context The thread queue context.
  *
  * @return Returns the unblock indicator for _Thread_queue_Unblock_critical().
  * True indicates, that this thread must be unblocked by the scheduler later in
@@ -610,32 +608,12 @@ bool _Thread_queue_Do_extract_locked(
  * since this thread may already block on another resource in an SMP
  * configuration.
  */
-#if defined(RTEMS_MULTIPROCESSING)
-  #define _Thread_queue_Extract_locked( \
-    unblock, \
-    queue, \
-    the_thread, \
-    queue_context \
-  ) \
-    _Thread_queue_Do_extract_locked( \
-      unblock, \
-      queue, \
-      the_thread, \
-      queue_context \
-    )
-#else
-  #define _Thread_queue_Extract_locked( \
-    unblock, \
-    queue, \
-    the_thread, \
-    queue_context \
-  ) \
-    _Thread_queue_Do_extract_locked( \
-      unblock, \
-      queue, \
-      the_thread \
-    )
-#endif
+bool _Thread_queue_Extract_locked(
+  Thread_queue_Queue            *queue,
+  const Thread_queue_Operations *operations,
+  Thread_Control                *the_thread,
+  const Thread_queue_Context    *queue_context
+);
 
 /**
  * @brief Unblocks the thread which was on the thread queue before.
@@ -735,7 +713,7 @@ void _Thread_queue_Extract_with_proxy(
 
 /**
  * @brief Surrenders the thread queue previously owned by the thread to the
- * first enqueued thread if it exists.
+ * first enqueued thread.
  *
  * The owner of the thread queue must be set to NULL by the caller.
  *
@@ -743,21 +721,18 @@ void _Thread_queue_Extract_with_proxy(
  * thread dispatch if necessary.
  *
  * @param[in] queue The actual thread queue.
- * @param[in] operations The thread queue operations.
- * @param[in] heads The thread queue heads.
+ * @param[in] heads The thread queue heads.  It must not be NULL.
  * @param[in] previous_owner The previous owner thread surrendering the thread
  *   queue.
- * @param[in] keep_priority Indicates if the previous owner thread should keep
- *   its current priority.
  * @param[in] queue_context The thread queue context of the lock acquire.
+ * @param[in] operations The thread queue operations.
  */
 void _Thread_queue_Surrender(
   Thread_queue_Queue            *queue,
-  const Thread_queue_Operations *operations,
   Thread_queue_Heads            *heads,
   Thread_Control                *previous_owner,
-  bool                           keep_priority,
-  Thread_queue_Context          *queue_context
+  Thread_queue_Context          *queue_context,
+  const Thread_queue_Operations *operations
 );
 
 RTEMS_INLINE_ROUTINE bool _Thread_queue_Is_empty(
@@ -980,6 +955,16 @@ void _Thread_queue_Unblock_proxy(
 );
 #endif
 
+bool _Thread_queue_Path_acquire_critical(
+  Thread_queue_Queue   *queue,
+  Thread_Control       *the_thread,
+  Thread_queue_Context *queue_context
+);
+
+void _Thread_queue_Path_release_critical(
+  Thread_queue_Context *queue_context
+);
+
 /**
  * @brief Helper structure to ensure that all objects containing a thread queue
  * have the right layout.
diff --git a/cpukit/score/preinstall.am b/cpukit/score/preinstall.am
index 61d44b8..94865a0 100644
--- a/cpukit/score/preinstall.am
+++ b/cpukit/score/preinstall.am
@@ -200,6 +200,10 @@ $(PROJECT_INCLUDE)/rtems/score/priority.h: include/rtems/score/priority.h $(PROJ
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/priority.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/priority.h
 
+$(PROJECT_INCLUDE)/rtems/score/priorityimpl.h: include/rtems/score/priorityimpl.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/priorityimpl.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/priorityimpl.h
+
 $(PROJECT_INCLUDE)/rtems/score/prioritybitmap.h: include/rtems/score/prioritybitmap.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/prioritybitmap.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/prioritybitmap.h
diff --git a/cpukit/score/src/mutex.c b/cpukit/score/src/mutex.c
index bfa36ff..daa90a5 100644
--- a/cpukit/score/src/mutex.c
+++ b/cpukit/score/src/mutex.c
@@ -128,33 +128,20 @@ static void _Mutex_Release_critical(
 )
 {
   Thread_queue_Heads *heads;
-  bool keep_priority;
 
+  heads = mutex->Queue.Queue.heads;
   mutex->Queue.Queue.owner = NULL;
-
   --executing->resource_count;
 
-  /*
-   * Ensure that the owner resource count is visible to all other
-   * processors and that we read the latest priority restore
-   * hint.
-   */
-  _Atomic_Fence( ATOMIC_ORDER_ACQ_REL );
-
-  heads = mutex->Queue.Queue.heads;
-  keep_priority = _Thread_Owns_resources( executing )
-    || !executing->priority_restore_hint;
-
-  if ( __predict_true( heads == NULL && keep_priority ) ) {
+  if ( __predict_true( heads == NULL ) ) {
     _Mutex_Queue_release( mutex, queue_context );
   } else {
     _Thread_queue_Surrender(
       &mutex->Queue.Queue,
-      MUTEX_TQ_OPERATIONS,
       heads,
       executing,
-      keep_priority,
-      queue_context
+      queue_context,
+      MUTEX_TQ_OPERATIONS
     );
   }
 }
diff --git a/cpukit/score/src/schedulercbs.c b/cpukit/score/src/schedulercbs.c
index 98ec0eb..f114d4f 100644
--- a/cpukit/score/src/schedulercbs.c
+++ b/cpukit/score/src/schedulercbs.c
@@ -19,24 +19,28 @@
 #endif
 
 #include <rtems/score/schedulercbsimpl.h>
-#include <rtems/score/threadimpl.h>
-#include <rtems/score/wkspace.h>
 
 void _Scheduler_CBS_Budget_callout(
   Thread_Control *the_thread
 )
 {
-  Priority_Control          new_priority;
-  Priority_Control          unused;
-  Scheduler_CBS_Node       *node;
-  Scheduler_CBS_Server_id   server_id;
+  Scheduler_CBS_Node      *node;
+  Scheduler_CBS_Server_id  server_id;
+  Thread_queue_Context     queue_context;
+
+  node = _Scheduler_CBS_Thread_get_node( the_thread );
 
   /* Put violating task to background until the end of period. */
-  new_priority = the_thread->Start.initial_priority;
-  _Thread_Set_priority( the_thread, new_priority, &unused, true );
+  _Thread_queue_Context_clear_priority_updates( &queue_context );
+  _Scheduler_CBS_Cancel_job(
+    NULL,
+    the_thread,
+    node->deadline_node,
+    &queue_context
+  );
+  _Thread_Priority_update( &queue_context );
 
   /* Invoke callback function if any. */
-  node = _Scheduler_CBS_Thread_get_node( the_thread );
   if ( node->cbs_server->cbs_budget_overrun ) {
     _Scheduler_CBS_Get_server_id(
         node->cbs_server->task_id,
diff --git a/cpukit/score/src/schedulercbsnodeinit.c b/cpukit/score/src/schedulercbsnodeinit.c
index 5380069..89b6f8e 100644
--- a/cpukit/score/src/schedulercbsnodeinit.c
+++ b/cpukit/score/src/schedulercbsnodeinit.c
@@ -33,4 +33,5 @@ void _Scheduler_CBS_Node_initialize(
 
   the_node = _Scheduler_CBS_Node_downcast( node );
   the_node->cbs_server = NULL;
+  the_node->deadline_node = NULL;
 }
diff --git a/cpukit/score/src/schedulercbsreleasejob.c b/cpukit/score/src/schedulercbsreleasejob.c
index d2169af..186f95c 100644
--- a/cpukit/score/src/schedulercbsreleasejob.c
+++ b/cpukit/score/src/schedulercbsreleasejob.c
@@ -21,10 +21,12 @@
 
 #include <rtems/score/schedulercbsimpl.h>
 
-Thread_Control *_Scheduler_CBS_Release_job(
+void _Scheduler_CBS_Release_job(
   const Scheduler_Control *scheduler,
   Thread_Control          *the_thread,
-  uint64_t                 deadline
+  Priority_Node           *priority_node,
+  uint64_t                 deadline,
+  Thread_queue_Context    *queue_context
 )
 {
   Scheduler_CBS_Node   *node;
@@ -38,5 +40,37 @@ Thread_Control *_Scheduler_CBS_Release_job(
     the_thread->cpu_time_budget = serv_info->parameters.budget;
   }
 
-  return _Scheduler_EDF_Release_job( scheduler, the_thread, deadline );
+  node->deadline_node = priority_node;
+
+  _Scheduler_EDF_Release_job(
+    scheduler,
+    the_thread,
+    priority_node,
+    deadline,
+    queue_context
+  );
+}
+
+void _Scheduler_CBS_Cancel_job(
+  const Scheduler_Control *scheduler,
+  Thread_Control          *the_thread,
+  Priority_Node           *priority_node,
+  Thread_queue_Context    *queue_context
+)
+{
+  Scheduler_CBS_Node *node;
+
+  node = _Scheduler_CBS_Thread_get_node( the_thread );
+
+  if ( node->deadline_node != NULL ) {
+    _Assert( node->deadline_node == priority_node );
+    node->deadline_node = NULL;
+
+    _Scheduler_EDF_Cancel_job(
+      scheduler,
+      the_thread,
+      priority_node,
+      queue_context
+    );
+  }
 }
diff --git a/cpukit/score/src/schedulercbsunblock.c b/cpukit/score/src/schedulercbsunblock.c
index 0c1e48e..c09f471 100644
--- a/cpukit/score/src/schedulercbsunblock.c
+++ b/cpukit/score/src/schedulercbsunblock.c
@@ -30,13 +30,11 @@ Scheduler_Void_or_thread _Scheduler_CBS_Unblock(
   Thread_Control          *the_thread
 )
 {
-  Scheduler_EDF_Context *context;
-  Scheduler_CBS_Node    *node;
-  Scheduler_CBS_Server  *serv_info;
-  Priority_Control       priority;
-  bool                   prepend_it;
+  Scheduler_CBS_Node   *node;
+  Scheduler_CBS_Server *serv_info;
+  Priority_Control      priority;
+  bool                  prepend_it;
 
-  context = _Scheduler_EDF_Get_context( scheduler );
   node = _Scheduler_CBS_Thread_get_node( the_thread );
   serv_info = node->cbs_server;
   priority = _Scheduler_Node_get_priority( &node->Base.Base, &prepend_it );
@@ -55,40 +53,19 @@ Scheduler_Void_or_thread _Scheduler_CBS_Unblock(
     Priority_Control budget_left = priority - _Watchdog_Ticks_since_boot;
 
     if ( deadline * budget_left > budget * deadline_left ) {
-      /* Put late unblocked task to background until the end of period. */
-
-      priority = node->Base.background_priority;
-      the_thread->real_priority = priority;
+      Thread_queue_Context queue_context;
 
-      if (
-        _Thread_Priority_less_than(
-          _Thread_Get_priority( the_thread ),
-          priority
-        ) || !_Thread_Owns_resources( the_thread )
-      ) {
-        the_thread->current_priority = priority;
-      }
+      /* Put late unblocked task to background until the end of period. */
+      _Thread_queue_Context_clear_priority_updates( &queue_context );
+      _Scheduler_CBS_Cancel_job(
+        scheduler,
+        the_thread,
+        node->deadline_node,
+        &queue_context
+      );
     }
   }
 
-  node->Base.current_priority = priority;
-  _Scheduler_EDF_Enqueue( context, &node->Base, priority );
-
-  /*
-   *  If the thread that was unblocked is more important than the heir,
-   *  then we have a new heir.  This may or may not result in a
-   *  context switch.
-   *
-   *  Normal case:
-   *    If the current thread is preemptible, then we need to do
-   *    a context switch.
-   *  Pseudo-ISR case:
-   *    Even if the thread isn't preemptible, if the new heir is
-   *    a pseudo-ISR system task, we need to do a context switch.
-   */
-  if ( priority < _Thread_Get_priority( _Thread_Heir ) ) {
-    _Scheduler_Update_heir( the_thread, priority == PRIORITY_PSEUDO_ISR );
-  }
-
+  _Scheduler_EDF_Unblock( scheduler, the_thread );
   SCHEDULER_RETURN_VOID_OR_NULL;
 }
diff --git a/cpukit/score/src/schedulerdefaultnodeinit.c b/cpukit/score/src/schedulerdefaultnodeinit.c
index 10e71f8..53aed52 100644
--- a/cpukit/score/src/schedulerdefaultnodeinit.c
+++ b/cpukit/score/src/schedulerdefaultnodeinit.c
@@ -28,7 +28,5 @@ void _Scheduler_default_Node_initialize(
   Priority_Control         priority
 )
 {
-  (void) scheduler;
-
-  _Scheduler_Node_do_initialize( node, the_thread, priority );
+  _Scheduler_Node_do_initialize( scheduler, node, the_thread, priority );
 }
diff --git a/cpukit/score/src/schedulerdefaultreleasejob.c b/cpukit/score/src/schedulerdefaultreleasejob.c
index 7272fc1..490d58b 100644
--- a/cpukit/score/src/schedulerdefaultreleasejob.c
+++ b/cpukit/score/src/schedulerdefaultreleasejob.c
@@ -21,26 +21,30 @@
 
 #include <rtems/score/scheduler.h>
 
-Thread_Control *_Scheduler_default_Release_job(
+void _Scheduler_default_Release_job(
   const Scheduler_Control *scheduler,
   Thread_Control          *the_thread,
-  uint64_t                 deadline
+  Priority_Node           *priority_node,
+  uint64_t                 deadline,
+  Thread_queue_Context    *queue_context
 )
 {
   (void) scheduler;
   (void) the_thread;
+  (void) priority_node;
   (void) deadline;
-
-  return NULL;
+  (void) queue_context;
 }
 
-Thread_Control *_Scheduler_default_Cancel_job(
+void _Scheduler_default_Cancel_job(
   const Scheduler_Control *scheduler,
-  Thread_Control          *the_thread
+  Thread_Control          *the_thread,
+  Priority_Node           *priority_node,
+  Thread_queue_Context    *queue_context
 )
 {
   (void) scheduler;
   (void) the_thread;
-
-  return NULL;
+  (void) priority_node;
+  (void) queue_context;
 }
diff --git a/cpukit/score/src/scheduleredfchangepriority.c b/cpukit/score/src/scheduleredfchangepriority.c
index 9a73128..8940b1d 100644
--- a/cpukit/score/src/scheduleredfchangepriority.c
+++ b/cpukit/score/src/scheduleredfchangepriority.c
@@ -54,16 +54,12 @@ Scheduler_Void_or_thread _Scheduler_EDF_Update_priority(
   node = _Scheduler_EDF_Thread_get_node( the_thread );
   priority = _Scheduler_Node_get_priority( &node->Base, &prepend_it );
 
-  if ( priority == node->current_priority ) {
+  if ( priority == node->priority ) {
     /* Nothing to do */
     SCHEDULER_RETURN_VOID_OR_NULL;
   }
 
-  if ( ( priority & SCHEDULER_EDF_PRIO_MSB ) != 0 ) {
-    node->background_priority = priority;
-  }
-
-  node->current_priority = priority;
+  node->priority = priority;
   context = _Scheduler_EDF_Get_context( scheduler );
 
   _Scheduler_EDF_Extract( context, node );
diff --git a/cpukit/score/src/scheduleredfnodeinit.c b/cpukit/score/src/scheduleredfnodeinit.c
index d290bd7..94f8fac 100644
--- a/cpukit/score/src/scheduleredfnodeinit.c
+++ b/cpukit/score/src/scheduleredfnodeinit.c
@@ -29,11 +29,9 @@ void _Scheduler_EDF_Node_initialize(
 {
   Scheduler_EDF_Node *the_node;
 
-  (void) scheduler;
-
-  _Scheduler_Node_do_initialize( node, the_thread, priority );
+  _Scheduler_Node_do_initialize( scheduler, node, the_thread, priority );
 
   the_node = _Scheduler_EDF_Node_downcast( node );
-  the_node->thread = the_thread;
   _RBTree_Initialize_node( &the_node->Node );
+  the_node->priority = priority;
 }
diff --git a/cpukit/score/src/scheduleredfreleasejob.c b/cpukit/score/src/scheduleredfreleasejob.c
index 4c74c48..c19d9b9 100644
--- a/cpukit/score/src/scheduleredfreleasejob.c
+++ b/cpukit/score/src/scheduleredfreleasejob.c
@@ -20,75 +20,47 @@
 
 #include <rtems/score/scheduleredfimpl.h>
 
-static bool _Scheduler_EDF_Release_job_filter(
-  Thread_Control   *the_thread,
-  Priority_Control *new_priority_p,
-  void             *arg
+void _Scheduler_EDF_Release_job(
+  const Scheduler_Control *scheduler,
+  Thread_Control          *the_thread,
+  Priority_Node           *priority_node,
+  uint64_t                 deadline,
+  Thread_queue_Context    *queue_context
 )
 {
-  Scheduler_EDF_Node *node;
-  Priority_Control    current_priority;
-  Priority_Control    new_priority;
+  (void) scheduler;
 
-  node = _Scheduler_EDF_Thread_get_node( the_thread );
+  _Thread_Wait_acquire_critical( the_thread, queue_context );
 
-  current_priority = _Thread_Get_priority( the_thread );
-  new_priority = *new_priority_p;
+  _Priority_Node_set_priority( priority_node, deadline );
 
-  node->current_priority = new_priority;
-  the_thread->real_priority = new_priority;
+  if ( _Priority_Node_is_active( priority_node ) ) {
+    _Thread_Priority_changed(
+      the_thread,
+      priority_node,
+      false,
+      queue_context
+    );
+  } else {
+    _Thread_Priority_add( the_thread, priority_node, queue_context );
+  }
 
-  return _Thread_Priority_less_than( current_priority, new_priority )
-    || !_Thread_Owns_resources( the_thread );
+  _Thread_Wait_release_critical( the_thread, queue_context );
 }
 
-Thread_Control *_Scheduler_EDF_Release_job(
+void _Scheduler_EDF_Cancel_job(
   const Scheduler_Control *scheduler,
   Thread_Control          *the_thread,
-  uint64_t                 deadline
-)
-{
-  return _Thread_Apply_priority(
-    the_thread,
-    deadline,
-    NULL,
-    _Scheduler_EDF_Release_job_filter,
-    true
-  );
-}
-
-static bool _Scheduler_EDF_Cancel_job_filter(
-  Thread_Control   *the_thread,
-  Priority_Control *new_priority_p,
-  void             *arg
+  Priority_Node           *priority_node,
+  Thread_queue_Context    *queue_context
 )
 {
-  Scheduler_EDF_Node *node;
-  Priority_Control    current_priority;
-  Priority_Control    new_priority;
+  (void) scheduler;
 
-  node = _Scheduler_EDF_Thread_get_node( the_thread );
+  _Thread_Wait_acquire_critical( the_thread, queue_context );
 
-  current_priority = _Thread_Get_priority( the_thread );
-  new_priority = node->background_priority;
+  _Thread_Priority_remove( the_thread, priority_node, queue_context );
+  _Priority_Node_set_inactive( priority_node );
 
-  node->current_priority = new_priority;
-  the_thread->real_priority = new_priority;
-
-  return _Thread_Priority_less_than( current_priority, new_priority )
-    || !_Thread_Owns_resources( the_thread );
-}
-
-Thread_Control *_Scheduler_EDF_Cancel_job(
-  const Scheduler_Control *scheduler,
-  Thread_Control          *the_thread
-)
-{
-  return _Thread_Apply_priority(
-    the_thread,
-    0,
-    NULL,
-    _Scheduler_EDF_Cancel_job_filter,
-    true
-  );
+  _Thread_Wait_release_critical( the_thread, queue_context );
 }
diff --git a/cpukit/score/src/scheduleredfunblock.c b/cpukit/score/src/scheduleredfunblock.c
index 9b156ec..a5cc4b6 100644
--- a/cpukit/score/src/scheduleredfunblock.c
+++ b/cpukit/score/src/scheduleredfunblock.c
@@ -37,7 +37,7 @@ Scheduler_Void_or_thread _Scheduler_EDF_Unblock(
   priority = _Scheduler_Node_get_priority( &node->Base, &prepend_it );
   (void) prepend_it;
 
-  node->current_priority = priority;
+  node->priority = priority;
   _Scheduler_EDF_Enqueue( context, node, priority );
 
   /*
diff --git a/cpukit/score/src/scheduleredfyield.c b/cpukit/score/src/scheduleredfyield.c
index 06c1b46..3e64e5c 100644
--- a/cpukit/score/src/scheduleredfyield.c
+++ b/cpukit/score/src/scheduleredfyield.c
@@ -33,7 +33,7 @@ Scheduler_Void_or_thread _Scheduler_EDF_Yield(
   node = _Scheduler_EDF_Thread_get_node( the_thread );
 
   _Scheduler_EDF_Extract( context, node );
-  _Scheduler_EDF_Enqueue( context, node, node->current_priority );
+  _Scheduler_EDF_Enqueue( context, node, node->priority );
   _Scheduler_EDF_Schedule_body( scheduler, the_thread, true );
 
   SCHEDULER_RETURN_VOID_OR_NULL;
diff --git a/cpukit/score/src/schedulerpriority.c b/cpukit/score/src/schedulerpriority.c
index 11cee92..ddfd973 100644
--- a/cpukit/score/src/schedulerpriority.c
+++ b/cpukit/score/src/schedulerpriority.c
@@ -43,7 +43,7 @@ void _Scheduler_priority_Node_initialize(
   Scheduler_priority_Context *context;
   Scheduler_priority_Node    *the_node;
 
-  _Scheduler_Node_do_initialize( node, the_thread, priority );
+  _Scheduler_Node_do_initialize( scheduler, node, the_thread, priority );
 
   context = _Scheduler_priority_Get_context( scheduler );
   the_node = _Scheduler_priority_Node_downcast( node );
diff --git a/cpukit/score/src/schedulerprioritysmp.c b/cpukit/score/src/schedulerprioritysmp.c
index 07e7af4..e624a6a 100644
--- a/cpukit/score/src/schedulerprioritysmp.c
+++ b/cpukit/score/src/schedulerprioritysmp.c
@@ -57,7 +57,12 @@ void _Scheduler_priority_SMP_Node_initialize(
   Scheduler_priority_SMP_Node    *the_node;
 
   the_node = _Scheduler_priority_SMP_Node_downcast( node );
-  _Scheduler_SMP_Node_initialize( &the_node->Base, the_thread, priority );
+  _Scheduler_SMP_Node_initialize(
+    scheduler,
+    &the_node->Base,
+    the_thread,
+    priority
+  );
 
   context = _Scheduler_Get_context( scheduler );
   self = _Scheduler_priority_SMP_Get_self( context );
diff --git a/cpukit/score/src/schedulersimplesmp.c b/cpukit/score/src/schedulersimplesmp.c
index 8f86ea8..9606896 100644
--- a/cpukit/score/src/schedulersimplesmp.c
+++ b/cpukit/score/src/schedulersimplesmp.c
@@ -52,7 +52,7 @@ void _Scheduler_simple_SMP_Node_initialize(
   Scheduler_SMP_Node *the_node;
 
   the_node = _Scheduler_SMP_Node_downcast( node );
-  _Scheduler_SMP_Node_initialize( the_node, the_thread, priority );
+  _Scheduler_SMP_Node_initialize( scheduler, the_node, the_thread, priority );
 }
 
 static void _Scheduler_simple_SMP_Do_update(
diff --git a/cpukit/score/src/schedulerstrongapa.c b/cpukit/score/src/schedulerstrongapa.c
index 5d7c7f7..fc6d012 100644
--- a/cpukit/score/src/schedulerstrongapa.c
+++ b/cpukit/score/src/schedulerstrongapa.c
@@ -183,7 +183,12 @@ void _Scheduler_strong_APA_Node_initialize(
   Scheduler_strong_APA_Node    *the_node;
 
   the_node = _Scheduler_strong_APA_Node_downcast( node );
-  _Scheduler_SMP_Node_initialize( &the_node->Base, the_thread, priority );
+  _Scheduler_SMP_Node_initialize(
+    scheduler,
+    &the_node->Base,
+    the_thread,
+    priority
+  );
 
   context = _Scheduler_Get_context( scheduler );
   self = _Scheduler_strong_APA_Get_self( context );
diff --git a/cpukit/score/src/thread.c b/cpukit/score/src/thread.c
index c569ae5..864b21b 100644
--- a/cpukit/score/src/thread.c
+++ b/cpukit/score/src/thread.c
@@ -32,9 +32,7 @@
 THREAD_OFFSET_ASSERT( Object );
 THREAD_OFFSET_ASSERT( Join_queue );
 THREAD_OFFSET_ASSERT( current_state );
-THREAD_OFFSET_ASSERT( current_priority );
-THREAD_OFFSET_ASSERT( real_priority );
-THREAD_OFFSET_ASSERT( priority_restore_hint );
+THREAD_OFFSET_ASSERT( Real_priority );
 THREAD_OFFSET_ASSERT( resource_count );
 THREAD_OFFSET_ASSERT( Scheduler );
 THREAD_OFFSET_ASSERT( Wait );
diff --git a/cpukit/score/src/threadchangepriority.c b/cpukit/score/src/threadchangepriority.c
index 3429e1a..98241e0 100644
--- a/cpukit/score/src/threadchangepriority.c
+++ b/cpukit/score/src/threadchangepriority.c
@@ -10,6 +10,8 @@
  *  COPYRIGHT (c) 1989-2014.
  *  On-Line Applications Research Corporation (OAR).
  *
+ *  Copyright (c) 2013, 2016 embedded brains GmbH
+ *
  *  The license and distribution terms for this file may be
  *  found in the file LICENSE in this distribution or at
  *  http://www.rtems.org/license/LICENSE.
@@ -20,145 +22,328 @@
 #endif
 
 #include <rtems/score/threadimpl.h>
+#include <rtems/score/assert.h>
 #include <rtems/score/schedulerimpl.h>
 
-static Thread_Control *_Thread_Apply_priority_locked(
+static void _Thread_Set_scheduler_node_priority(
+  Priority_Aggregation *priority_aggregation,
+  bool                  prepend_it
+)
+{
+  _Scheduler_Node_set_priority(
+    SCHEDULER_NODE_OF_WAIT_PRIORITY_NODE( priority_aggregation ),
+    _Priority_Get_priority( priority_aggregation ),
+    prepend_it
+  );
+}
+
+#if defined(RTEMS_SMP)
+static void _Thread_Priority_action_add(
+  Priority_Aggregation *priority_aggregation,
+  Priority_Actions     *priority_actions,
+  void                 *arg
+)
+{
+  _Thread_Set_scheduler_node_priority( priority_aggregation, false );
+  _Priority_Set_action_type( priority_aggregation, PRIORITY_ACTION_ADD );
+  _Priority_Actions_add( priority_actions, priority_aggregation );
+}
+
+static void _Thread_Priority_action_remove(
+  Priority_Aggregation *priority_aggregation,
+  Priority_Actions     *priority_actions,
+  void                 *arg
+)
+{
+  _Thread_Set_scheduler_node_priority( priority_aggregation, true );
+  _Priority_Set_action_type( priority_aggregation, PRIORITY_ACTION_REMOVE );
+  _Priority_Actions_add( priority_actions, priority_aggregation );
+}
+#endif
+
+static void _Thread_Priority_action_change(
+  Priority_Aggregation *priority_aggregation,
+  bool                  prepend_it,
+  Priority_Actions     *priority_actions,
+  void                 *arg
+)
+{
+  _Thread_Set_scheduler_node_priority( priority_aggregation, prepend_it );
+#if defined(RTEMS_SMP)
+  _Priority_Set_action_type( priority_aggregation, PRIORITY_ACTION_CHANGE );
+#elif defined(RTEMS_DEBUG)
+  _Priority_Set_action_type( priority_aggregation, PRIORITY_ACTION_INVALID );
+#endif
+  _Priority_Actions_add( priority_actions, priority_aggregation );
+}
+
+static void _Thread_Priority_do_perform_actions(
   Thread_Control                *the_thread,
-  Priority_Control               new_priority,
-  void                          *arg,
-  Thread_Change_priority_filter  filter,
+  Thread_queue_Queue            *queue,
+  const Thread_queue_Operations *operations,
   bool                           prepend_it,
   Thread_queue_Context          *queue_context
 )
 {
-  /*
-   * For simplicity set the priority restore hint unconditionally since this is
-   * an average case optimization.  Otherwise complicated atomic operations
-   * would be necessary.  Synchronize with a potential read of the resource
-   * count in the filter function.  See also _CORE_mutex_Surrender(),
-   * _Thread_Set_priority_filter() and _Thread_Restore_priority_filter().
-   */
-  the_thread->priority_restore_hint = true;
-  _Atomic_Fence( ATOMIC_ORDER_ACQ_REL );
+  Priority_Actions      actions_now;
+  Priority_Aggregation *priority_aggregation;
 
-  /*
-   *  Do not bother recomputing all the priority related information if
-   *  we are not REALLY changing priority.
-   */
-  if ( ( *filter )( the_thread, &new_priority, arg ) ) {
-    _Scheduler_Thread_set_priority( the_thread, new_priority, prepend_it );
+  _Assert( !_Priority_Actions_is_empty( &queue_context->Priority.Actions ) );
 
-    ( *the_thread->Wait.operations->priority_change )(
-      the_thread->Wait.queue,
-      the_thread,
-      new_priority
+  _Priority_Actions_move( &actions_now, &queue_context->Priority.Actions );
+  priority_aggregation = _Priority_Actions_get_first( &actions_now );
+
+  do {
+    Priority_Aggregation *priority_aggregation_next;
+    Priority_Node        *priority_action_node;
+    Priority_Action_type  priority_action_type;
+
+    priority_aggregation_next = _Priority_Get_next_action(
+      priority_aggregation
+    );
+
+    priority_action_node = priority_aggregation->Action.node;
+    priority_action_type = priority_aggregation->Action.type;
+
+    switch ( priority_action_type ) {
+      case PRIORITY_ACTION_ADD:
+#if defined(RTEMS_SMP)
+        _Priority_Insert(
+          priority_aggregation,
+          priority_action_node,
+          &queue_context->Priority.Actions,
+          _Thread_Priority_action_add,
+          _Thread_Priority_action_change,
+          NULL
+        );
+#else
+        _Priority_Non_empty_insert(
+          priority_aggregation,
+          priority_action_node,
+          &queue_context->Priority.Actions,
+          _Thread_Priority_action_change,
+          NULL
+        );
+#endif
+        break;
+      case PRIORITY_ACTION_REMOVE:
+#if defined(RTEMS_SMP)
+        _Priority_Extract(
+          priority_aggregation,
+          priority_action_node,
+          &queue_context->Priority.Actions,
+          _Thread_Priority_action_remove,
+          _Thread_Priority_action_change,
+          NULL
+        );
+#else
+        _Priority_Extract_non_empty(
+          priority_aggregation,
+          priority_action_node,
+          &queue_context->Priority.Actions,
+          _Thread_Priority_action_change,
+          NULL
+        );
+#endif
+        break;
+      default:
+        _Assert( priority_action_type == PRIORITY_ACTION_CHANGE );
+        _Priority_Change(
+          priority_aggregation,
+          priority_action_node,
+          prepend_it,
+          &queue_context->Priority.Actions,
+          _Thread_Priority_action_change,
+          NULL
+        );
+        break;
+    }
+
+    priority_aggregation = priority_aggregation_next;
+  } while ( _Priority_Actions_is_valid( priority_aggregation ) );
+
+  if ( !_Priority_Actions_is_empty( &queue_context->Priority.Actions ) ) {
+    _Thread_queue_Context_add_priority_update( queue_context, the_thread );
+    ( *operations->priority_actions )(
+      queue,
+      &queue_context->Priority.Actions
     );
-  } else {
-    the_thread = NULL;
   }
+}
+
+void _Thread_Priority_perform_actions(
+  Thread_Control       *start_of_path,
+  Thread_queue_Context *queue_context
+)
+{
+#if defined(RTEMS_SMP)
+  Thread_queue_Link *link;
+#endif
+  Thread_Control    *the_thread;
+  size_t             update_count;
 
-  return the_thread;
+  _Assert( start_of_path != NULL );
+
+#if defined(RTEMS_SMP)
+  link = &queue_context->Path.Start;
+#endif
+  the_thread = start_of_path;
+  update_count = _Thread_queue_Context_save_priority_updates( queue_context );
+
+  while ( true ) {
+    Thread_queue_Queue *queue;
+
+#if defined(RTEMS_SMP)
+    _Assert( link->owner == the_thread );
+    queue = link->Lock_context.Wait.queue;
+#else
+    queue = the_thread->Wait.queue;
+#endif
+
+    _Thread_Priority_do_perform_actions(
+      the_thread,
+      queue,
+      the_thread->Wait.operations,
+      false,
+      queue_context
+    );
+
+    if ( _Priority_Actions_is_empty( &queue_context->Priority.Actions ) ) {
+      return;
+    }
+
+    _Assert( queue != NULL );
+    the_thread = queue->owner;
+    _Assert( the_thread != NULL );
+
+#if defined(RTEMS_SMP)
+    link = THREAD_QUEUE_LINK_OF_PATH_NODE( _Chain_Next( &link->Path_node ) );
+#endif
+
+    /*
+     * In case the priority action list is non-empty, then the current thread
+     * is enqueued on a thread queue.  There is no need to notify the scheduler
+     * about a priority change, since it will pick up the new priority once it
+     * is unblocked.  Restore the previous set of threads bound to update the
+     * priority.
+     */
+    _Thread_queue_Context_restore_priority_updates(
+      queue_context,
+      update_count
+    );
+  }
 }
 
-Thread_Control *_Thread_Apply_priority(
-  Thread_Control                *the_thread,
-  Priority_Control               new_priority,
-  void                          *arg,
-  Thread_Change_priority_filter  filter,
-  bool                           prepend_it
+static void _Thread_Priority_apply(
+  Thread_Control       *the_thread,
+  Priority_Node        *priority_action_node,
+  Thread_queue_Context *queue_context,
+  bool                  prepend_it,
+  Priority_Action_type  priority_action_type
 )
 {
-  Thread_queue_Context  queue_context;
-  Thread_Control       *the_thread_to_update;
+  Scheduler_Node     *own_node;
+  Thread_queue_Queue *queue;
 
-  _Thread_Wait_acquire( the_thread, &queue_context );
-  the_thread_to_update = _Thread_Apply_priority_locked(
+  own_node = _Thread_Scheduler_get_own_node( the_thread );
+  _Priority_Actions_initialize_one(
+    &queue_context->Priority.Actions,
+    &own_node->Wait.Priority,
+    priority_action_node,
+    priority_action_type
+  );
+  queue = the_thread->Wait.queue;
+  _Thread_Priority_do_perform_actions(
     the_thread,
-    new_priority,
-    arg,
-    filter,
+    queue,
+    the_thread->Wait.operations,
     prepend_it,
-    &queue_context
+    queue_context
   );
-  _Thread_Wait_release( the_thread, &queue_context );
-  return the_thread_to_update;
-}
-
-void _Thread_Update_priority( Thread_Control *the_thread )
-{
-  if ( the_thread != NULL ) {
-    ISR_lock_Context lock_context;
 
-    _Thread_State_acquire( the_thread, &lock_context );
-    _Scheduler_Update_priority( the_thread );
-    _Thread_State_release( the_thread, &lock_context );
+  if ( !_Priority_Actions_is_empty( &queue_context->Priority.Actions ) ) {
+    _Thread_queue_Path_acquire_critical( queue, the_thread, queue_context );
+    _Thread_Priority_perform_actions( queue->owner, queue_context );
+    _Thread_queue_Path_release_critical( queue_context );
   }
 }
 
-void _Thread_Change_priority(
-  Thread_Control                *the_thread,
-  Priority_Control               new_priority,
-  void                          *arg,
-  Thread_Change_priority_filter  filter,
-  bool                           prepend_it
+void _Thread_Priority_add(
+  Thread_Control       *the_thread,
+  Priority_Node        *priority_node,
+  Thread_queue_Context *queue_context
 )
 {
-  the_thread = _Thread_Apply_priority(
+  _Thread_Priority_apply(
     the_thread,
-    new_priority,
-    arg,
-    filter,
-    prepend_it
+    priority_node,
+    queue_context,
+    false,
+    PRIORITY_ACTION_ADD
   );
-  _Thread_Update_priority( the_thread );
 }
 
-static bool _Thread_Raise_priority_filter(
-  Thread_Control   *the_thread,
-  Priority_Control *new_priority,
-  void             *arg
+void _Thread_Priority_remove(
+  Thread_Control       *the_thread,
+  Priority_Node        *priority_node,
+  Thread_queue_Context *queue_context
 )
 {
-  return _Thread_Priority_less_than(
-    _Thread_Get_priority( the_thread ),
-    *new_priority
+  _Thread_Priority_apply(
+    the_thread,
+    priority_node,
+    queue_context,
+    true,
+    PRIORITY_ACTION_REMOVE
   );
 }
 
-void _Thread_Raise_priority(
-  Thread_Control   *the_thread,
-  Priority_Control  new_priority
+void _Thread_Priority_changed(
+  Thread_Control       *the_thread,
+  Priority_Node        *priority_node,
+  bool                  prepend_it,
+  Thread_queue_Context *queue_context
 )
 {
-  _Thread_Change_priority(
+  _Thread_Priority_apply(
     the_thread,
-    new_priority,
-    NULL,
-    _Thread_Raise_priority_filter,
-    false
+    priority_node,
+    queue_context,
+    prepend_it,
+    PRIORITY_ACTION_CHANGE
   );
 }
 
-static bool _Thread_Restore_priority_filter(
-  Thread_Control   *the_thread,
-  Priority_Control *new_priority,
-  void             *arg
+void _Thread_Priority_replace(
+  Thread_Control *the_thread,
+  Priority_Node  *victim_node,
+  Priority_Node  *replacement_node
 )
 {
-  *new_priority = the_thread->real_priority;
-
-  the_thread->priority_restore_hint = false;
+  Scheduler_Node *own_node;
 
-  return *new_priority != _Thread_Get_priority( the_thread );
+  own_node = _Thread_Scheduler_get_own_node( the_thread );
+  _Priority_Replace( &own_node->Wait.Priority, victim_node, replacement_node );
 }
 
-void _Thread_Restore_priority( Thread_Control *the_thread )
+void _Thread_Priority_update( Thread_queue_Context *queue_context )
 {
-  _Thread_Change_priority(
-    the_thread,
-    0,
-    NULL,
-    _Thread_Restore_priority_filter,
-    true
-  );
+  size_t i;
+  size_t n;
+
+  n = queue_context->Priority.update_count;
+
+  /*
+   * Update the priority of all threads of the set.  Do not care to clear the
+   * set, since the thread queue context will soon get destroyed anyway.
+   */
+  for ( i = 0; i < n ; ++i ) {
+    Thread_Control   *the_thread;
+    ISR_lock_Context  lock_context;
+
+    the_thread = queue_context->Priority.update[ i ];
+    _Thread_State_acquire( the_thread, &lock_context );
+    _Scheduler_Update_priority( the_thread );
+    _Thread_State_release( the_thread, &lock_context );
+  }
 }
diff --git a/cpukit/score/src/threadinitialize.c b/cpukit/score/src/threadinitialize.c
index 90f58e6..76b1dff 100644
--- a/cpukit/score/src/threadinitialize.c
+++ b/cpukit/score/src/threadinitialize.c
@@ -198,12 +198,15 @@ bool _Thread_Initialize(
 
   the_thread->current_state           = STATES_DORMANT;
   the_thread->Wait.operations         = &_Thread_queue_Operations_default;
-  the_thread->current_priority        = priority;
-  the_thread->real_priority           = priority;
   the_thread->Start.initial_priority  = priority;
 
   RTEMS_STATIC_ASSERT( THREAD_WAIT_FLAGS_INITIAL == 0, Wait_flags );
 
+  _Priority_Node_initialize( &the_thread->Real_priority, priority );
+  _Priority_Initialize_one(
+    &scheduler_node->Wait.Priority,
+    &the_thread->Real_priority
+  );
   _Scheduler_Node_initialize( scheduler, scheduler_node, the_thread, priority );
   scheduler_node_initialized = true;
 
diff --git a/cpukit/score/src/threadmp.c b/cpukit/score/src/threadmp.c
index cbb6c1c..f30b32a 100644
--- a/cpukit/score/src/threadmp.c
+++ b/cpukit/score/src/threadmp.c
@@ -80,6 +80,7 @@ void _Thread_MP_Handler_initialization (
 #endif
     proxy->Scheduler.node = &proxy->Scheduler_node;
     _Scheduler_Node_do_initialize(
+      _Scheduler_Get_index( 0 ),
       &proxy->Scheduler_node,
       (Thread_Control *) proxy,
       0
@@ -150,7 +151,7 @@ Thread_Control *_Thread_MP_Allocate_proxy (
 
     the_proxy->receive_packet = receive_packet;
     the_proxy->Object.id = source_tid;
-    the_proxy->current_priority = receive_packet->source_priority;
+    the_proxy->Scheduler.Real_priority.priority = receive_packet->source_priority;
     the_proxy->current_state = _States_Set( STATES_DORMANT, the_state );
 
     the_proxy->Wait.count                   = executing->Wait.count;
diff --git a/cpukit/score/src/threadqenqueue.c b/cpukit/score/src/threadqenqueue.c
index f16dff0..ae5ece3 100644
--- a/cpukit/score/src/threadqenqueue.c
+++ b/cpukit/score/src/threadqenqueue.c
@@ -162,17 +162,16 @@ static void _Thread_queue_Link_remove( Thread_queue_Link *link )
 }
 #endif
 
-#define THREAD_QUEUE_LINK_OF_PATH_NODE( node ) \
-  RTEMS_CONTAINER_OF( node, Thread_queue_Link, Path_node );
-
-static void _Thread_queue_Path_release( Thread_queue_Path *path )
+void _Thread_queue_Path_release_critical(
+  Thread_queue_Context *queue_context
+)
 {
 #if defined(RTEMS_SMP)
   Chain_Node *head;
   Chain_Node *node;
 
-  head = _Chain_Head( &path->Links );
-  node = _Chain_Last( &path->Links );
+  head = _Chain_Head( &queue_context->Path.Links );
+  node = _Chain_Last( &queue_context->Path.Links );
 
   if ( head != node ) {
     Thread_queue_Link *link;
@@ -215,18 +214,17 @@ static void _Thread_queue_Path_release( Thread_queue_Path *path )
     }
   }
 #else
-  (void) path;
+  (void) queue_context;
 #endif
 }
 
-static bool _Thread_queue_Path_acquire(
-  Thread_Control     *the_thread,
-  Thread_queue_Queue *queue,
-  Thread_queue_Path  *path
+bool _Thread_queue_Path_acquire_critical(
+  Thread_queue_Queue   *queue,
+  Thread_Control       *the_thread,
+  Thread_queue_Context *queue_context
 )
 {
   Thread_Control     *owner;
-
 #if defined(RTEMS_SMP)
   Thread_queue_Link  *link;
   Thread_queue_Queue *target;
@@ -239,7 +237,7 @@ static bool _Thread_queue_Path_acquire(
    * this would result in an unrecoverable deadlock of the overall system.
    */
 
-  _Chain_Initialize_empty( &path->Links );
+  _Chain_Initialize_empty( &queue_context->Path.Links );
 
   owner = queue->owner;
 
@@ -251,13 +249,15 @@ static bool _Thread_queue_Path_acquire(
     return false;
   }
 
-  _RBTree_Initialize_node( &path->Start.Registry_node );
-  _Chain_Initialize_node( &path->Start.Path_node );
-  _Chain_Initialize_node( &path->Start.Lock_context.Wait.Gate.Node );
-  link = &path->Start;
+  _RBTree_Initialize_node( &queue_context->Path.Start.Registry_node );
+  _Chain_Initialize_node( &queue_context->Path.Start.Path_node );
+  _Chain_Initialize_node(
+    &queue_context->Path.Start.Lock_context.Wait.Gate.Node
+  );
+  link = &queue_context->Path.Start;
 
   do {
-    _Chain_Append_unprotected( &path->Links, &link->Path_node );
+    _Chain_Append_unprotected( &queue_context->Path.Links, &link->Path_node );
     link->owner = owner;
 
     _Thread_Wait_acquire_default_critical(
@@ -293,7 +293,6 @@ static bool _Thread_queue_Path_acquire(
         }
       } else {
         link->Lock_context.Wait.queue = NULL;
-        _Thread_queue_Path_release( path );
         return false;
       }
     } else {
@@ -345,9 +344,8 @@ void _Thread_queue_Enqueue_critical(
   Thread_queue_Context          *queue_context
 )
 {
-  Thread_queue_Path  path;
-  Per_CPU_Control   *cpu_self;
-  bool               success;
+  Per_CPU_Control *cpu_self;
+  bool             success;
 
 #if defined(RTEMS_MULTIPROCESSING)
   if ( _Thread_MP_Is_receive( the_thread ) && the_thread->receive_packet ) {
@@ -357,7 +355,8 @@ void _Thread_queue_Enqueue_critical(
 
   _Thread_Wait_claim( the_thread, queue, operations );
 
-  if ( !_Thread_queue_Path_acquire( the_thread, queue, &path ) ) {
+  if ( !_Thread_queue_Path_acquire_critical( queue, the_thread, queue_context ) ) {
+    _Thread_queue_Path_release_critical( queue_context );
     _Thread_Wait_restore_default( the_thread );
     _Thread_queue_Queue_release( queue, &queue_context->Lock_context.Lock_context );
     _Thread_Wait_tranquilize( the_thread );
@@ -365,9 +364,10 @@ void _Thread_queue_Enqueue_critical(
     return;
   }
 
-  ( *operations->enqueue )( queue, the_thread, &path );
+  _Thread_queue_Context_clear_priority_updates( queue_context );
+  ( *operations->enqueue )( queue, the_thread, queue_context );
 
-  _Thread_queue_Path_release( &path );
+  _Thread_queue_Path_release_critical( queue_context );
 
   the_thread->Wait.return_code = STATUS_SUCCESSFUL;
   _Thread_Wait_flags_set( the_thread, THREAD_QUEUE_INTEND_TO_BLOCK );
@@ -437,7 +437,7 @@ void _Thread_queue_Enqueue_critical(
     _Thread_Remove_timer_and_unblock( the_thread, queue );
   }
 
-  _Thread_Update_priority( path.update_priority );
+  _Thread_Priority_update( queue_context );
   _Thread_Dispatch_enable( cpu_self );
 }
 
@@ -488,20 +488,17 @@ static bool _Thread_queue_Make_ready_again( Thread_Control *the_thread )
   return unblock;
 }
 
-bool _Thread_queue_Do_extract_locked(
+bool _Thread_queue_Extract_locked(
   Thread_queue_Queue            *queue,
   const Thread_queue_Operations *operations,
-  Thread_Control                *the_thread
-#if defined(RTEMS_MULTIPROCESSING)
-  ,
+  Thread_Control                *the_thread,
   const Thread_queue_Context    *queue_context
-#endif
 )
 {
 #if defined(RTEMS_MULTIPROCESSING)
   _Thread_queue_MP_set_callout( the_thread, queue_context );
 #endif
-  ( *operations->extract )( queue, the_thread );
+  ( *operations->extract )( queue, the_thread, queue_context );
   return _Thread_queue_Make_ready_again( the_thread );
 }
 
@@ -587,46 +584,51 @@ void _Thread_queue_Extract( Thread_Control *the_thread )
 
 void _Thread_queue_Surrender(
   Thread_queue_Queue            *queue,
-  const Thread_queue_Operations *operations,
   Thread_queue_Heads            *heads,
   Thread_Control                *previous_owner,
-  bool                           keep_priority,
-  Thread_queue_Context          *queue_context
+  Thread_queue_Context          *queue_context,
+  const Thread_queue_Operations *operations
 )
 {
-  if ( heads != NULL ) {
-    Thread_Control *new_owner;
-    bool            unblock;
+  Thread_Control  *new_owner;
+  bool             unblock;
+  Per_CPU_Control *cpu_self;
 
-    new_owner = ( *operations->surrender )( queue, heads, previous_owner );
-    queue->owner = new_owner;
+  _Assert( heads != NULL );
+
+  _Thread_queue_Context_clear_priority_updates( queue_context );
+  new_owner = ( *operations->surrender )(
+    queue,
+    heads,
+    previous_owner,
+    queue_context
+  );
+  queue->owner = new_owner;
 
 #if defined(RTEMS_MULTIPROCESSING)
-    if ( !_Thread_queue_MP_set_callout( new_owner, queue_context ) )
+  if ( !_Thread_queue_MP_set_callout( new_owner, queue_context ) )
 #endif
-    {
-      ++new_owner->resource_count;
-    }
+  {
+    ++new_owner->resource_count;
+  }
 
-    unblock = _Thread_queue_Make_ready_again( new_owner );
+  unblock = _Thread_queue_Make_ready_again( new_owner );
 
-    _Thread_queue_Unblock_critical(
-      unblock,
-      queue,
-      new_owner,
-      &queue_context->Lock_context.Lock_context
-    );
-  } else {
-    _Thread_queue_Queue_release( queue, &queue_context->Lock_context.Lock_context );
-  }
+  cpu_self = _Thread_Dispatch_disable_critical(
+    &queue_context->Lock_context.Lock_context
+  );
+  _Thread_queue_Queue_release(
+    queue,
+    &queue_context->Lock_context.Lock_context
+  );
 
-  if ( !keep_priority ) {
-    Per_CPU_Control *cpu_self;
+  _Thread_Priority_update( queue_context );
 
-    cpu_self = _Thread_Dispatch_disable();
-    _Thread_Restore_priority( previous_owner );
-    _Thread_Dispatch_enable( cpu_self );
+  if ( unblock ) {
+    _Thread_Remove_timer_and_unblock( new_owner, queue );
   }
+
+  _Thread_Dispatch_enable( cpu_self );
 }
 
 Thread_Control *_Thread_queue_Do_dequeue(
diff --git a/cpukit/score/src/threadqflush.c b/cpukit/score/src/threadqflush.c
index fb13230..9ea82af 100644
--- a/cpukit/score/src/threadqflush.c
+++ b/cpukit/score/src/threadqflush.c
@@ -99,8 +99,11 @@ size_t _Thread_queue_Flush_critical(
     if ( do_unblock ) {
       Scheduler_Node *scheduler_node;
 
-      scheduler_node = _Scheduler_Thread_get_own_node( first );
-      _Chain_Append_unprotected( &unblock, &scheduler_node->Wait.Node.Chain );
+      scheduler_node = _Thread_Scheduler_get_own_node( first );
+      _Chain_Append_unprotected(
+        &unblock,
+        &scheduler_node->Wait.Priority.Node.Node.Chain
+      );
     }
 
     ++flushed;
@@ -123,7 +126,7 @@ size_t _Thread_queue_Flush_critical(
       Chain_Node     *next;
 
       next = _Chain_Next( node );
-      scheduler_node = SCHEDULER_NODE_OF_WAIT_CHAIN_NODE( node );
+      scheduler_node = SCHEDULER_NODE_OF_WAIT_PRIORITY_NODE( node );
       the_thread = _Scheduler_Node_get_owner( scheduler_node );
       _Thread_Remove_timer_and_unblock( the_thread, queue );
 
diff --git a/cpukit/score/src/threadqops.c b/cpukit/score/src/threadqops.c
index e20241d..80af46d 100644
--- a/cpukit/score/src/threadqops.c
+++ b/cpukit/score/src/threadqops.c
@@ -22,31 +22,39 @@
 #include <rtems/score/rbtreeimpl.h>
 #include <rtems/score/schedulerimpl.h>
 
-static void _Thread_queue_Do_nothing_priority_change(
+#define THREAD_QUEUE_CONTEXT_OF_PRIORITY_ACTIONS( priority_actions ) \
+  RTEMS_CONTAINER_OF( \
+    priority_actions, \
+    Thread_queue_Context, \
+    Priority.Actions \
+  )
+
+static void _Thread_queue_Do_nothing_priority_actions(
   Thread_queue_Queue *queue,
-  Thread_Control     *the_thread,
-  Priority_Control    new_priority
+  Priority_Actions   *priority_actions
 )
 {
   (void) queue;
-  (void) the_thread;
-  (void) new_priority;
+  _Priority_Actions_initialize_empty( priority_actions );
 }
 
 static void _Thread_queue_Do_nothing_extract(
-  Thread_queue_Queue *queue,
-  Thread_Control     *the_thread
+  Thread_queue_Queue   *queue,
+  Thread_Control       *the_thread,
+  Thread_queue_Context *queue_context
 )
 {
   (void) queue;
   (void) the_thread;
+  (void) queue_context;
 }
 
-static Thread_queue_Heads *_Thread_queue_Queue_enqueue(
-  Thread_queue_Queue *queue,
-  Thread_Control     *the_thread,
-  void             ( *initialize )( Thread_queue_Heads *, Thread_Control * ),
-  void             ( *enqueue )( Thread_queue_Heads *, Thread_Control * )
+static void _Thread_queue_Queue_enqueue(
+  Thread_queue_Queue   *queue,
+  Thread_Control       *the_thread,
+  Thread_queue_Context *queue_context,
+  void               ( *initialize )( Thread_queue_Queue *, Thread_Control *, Thread_queue_Context *, Thread_queue_Heads * ),
+  void               ( *enqueue )( Thread_queue_Queue *, Thread_Control *, Thread_queue_Context *, Thread_queue_Heads * )
 )
 {
   Thread_queue_Heads *heads;
@@ -63,20 +71,20 @@ static Thread_queue_Heads *_Thread_queue_Queue_enqueue(
     heads = spare_heads;
     queue->heads = heads;
     _Chain_Prepend_unprotected( &heads->Free_chain, &spare_heads->Free_node );
-    ( *initialize )( heads, the_thread );
+    ( *initialize )( queue, the_thread, queue_context, heads );
   } else {
     _Chain_Prepend_unprotected( &heads->Free_chain, &spare_heads->Free_node );
-    ( *enqueue )( heads, the_thread );
+    ( *enqueue )( queue, the_thread, queue_context, heads );
   }
-
-  return heads;
 }
 
 static void _Thread_queue_Queue_extract(
-  Thread_queue_Queue *queue,
-  Thread_queue_Heads *heads,
-  Thread_Control     *the_thread,
-  void             ( *extract )( Thread_queue_Heads *, Thread_Control * )
+  Thread_queue_Queue   *queue,
+  Thread_queue_Heads   *heads,
+  Thread_Control       *current_or_previous_owner,
+  Thread_queue_Context *queue_context,
+  Thread_Control       *the_thread,
+  void               ( *extract )( Thread_queue_Queue *, Thread_queue_Heads *, Thread_Control *, Thread_queue_Context *, Thread_Control * )
 )
 {
   _Assert( heads != NULL );
@@ -91,76 +99,94 @@ static void _Thread_queue_Queue_extract(
     queue->heads = NULL;
   }
 
-  ( *extract )( heads, the_thread );
+  ( *extract )(
+    queue,
+    heads,
+    current_or_previous_owner,
+    queue_context,
+    the_thread
+  );
 }
 
 static void _Thread_queue_FIFO_do_initialize(
-  Thread_queue_Heads *heads,
-  Thread_Control     *the_thread
+  Thread_queue_Queue   *queue,
+  Thread_Control       *the_thread,
+  Thread_queue_Context *queue_context,
+  Thread_queue_Heads   *heads
 )
 {
   Scheduler_Node *scheduler_node;
 
-  scheduler_node = _Scheduler_Thread_get_own_node( the_thread );
+  scheduler_node = _Thread_Scheduler_get_own_node( the_thread );
 
-  _Chain_Initialize_node( &scheduler_node->Wait.Node.Chain );
+  _Chain_Initialize_node( &scheduler_node->Wait.Priority.Node.Node.Chain );
   _Chain_Initialize_one(
     &heads->Heads.Fifo,
-    &scheduler_node->Wait.Node.Chain
+    &scheduler_node->Wait.Priority.Node.Node.Chain
   );
 }
 
 static void _Thread_queue_FIFO_do_enqueue(
-  Thread_queue_Heads *heads,
-  Thread_Control     *the_thread
+  Thread_queue_Queue   *queue,
+  Thread_Control       *the_thread,
+  Thread_queue_Context *queue_context,
+  Thread_queue_Heads   *heads
 )
 {
   Scheduler_Node *scheduler_node;
 
-  scheduler_node = _Scheduler_Thread_get_own_node( the_thread );
+  scheduler_node = _Thread_Scheduler_get_own_node( the_thread );
 
-  _Chain_Initialize_node( &scheduler_node->Wait.Node.Chain );
+  _Chain_Initialize_node( &scheduler_node->Wait.Priority.Node.Node.Chain );
   _Chain_Append_unprotected(
     &heads->Heads.Fifo,
-    &scheduler_node->Wait.Node.Chain
+    &scheduler_node->Wait.Priority.Node.Node.Chain
   );
 }
 
 static void _Thread_queue_FIFO_do_extract(
-  Thread_queue_Heads *heads,
-  Thread_Control     *the_thread
+  Thread_queue_Queue   *queue,
+  Thread_queue_Heads   *heads,
+  Thread_Control       *current_or_previous_owner,
+  Thread_queue_Context *queue_context,
+  Thread_Control       *the_thread
 )
 {
   Scheduler_Node *scheduler_node;
 
-  scheduler_node = _Scheduler_Thread_get_own_node( the_thread );
-  _Chain_Extract_unprotected( &scheduler_node->Wait.Node.Chain );
+  (void) queue_context;
+
+  scheduler_node = _Thread_Scheduler_get_own_node( the_thread );
+
+  _Chain_Extract_unprotected( &scheduler_node->Wait.Priority.Node.Node.Chain );
 }
 
 static void _Thread_queue_FIFO_enqueue(
-  Thread_queue_Queue *queue,
-  Thread_Control     *the_thread,
-  Thread_queue_Path  *path
+  Thread_queue_Queue   *queue,
+  Thread_Control       *the_thread,
+  Thread_queue_Context *queue_context
 )
 {
-  path->update_priority = NULL;
-
   _Thread_queue_Queue_enqueue(
     queue,
     the_thread,
+    queue_context,
     _Thread_queue_FIFO_do_initialize,
     _Thread_queue_FIFO_do_enqueue
   );
 }
 
 static void _Thread_queue_FIFO_extract(
-  Thread_queue_Queue *queue,
-  Thread_Control     *the_thread
+  Thread_queue_Queue   *queue,
+  Thread_Control       *the_thread,
+  Thread_queue_Context *queue_context
 )
 {
   _Thread_queue_Queue_extract(
     queue,
     queue->heads,
+    NULL,
+    queue_context,
     the_thread,
     _Thread_queue_FIFO_do_extract
   );
@@ -177,15 +203,16 @@ static Thread_Control *_Thread_queue_FIFO_first(
   fifo = &heads->Heads.Fifo;
   _Assert( !_Chain_Is_empty( fifo ) );
   first = _Chain_First( fifo );
-  scheduler_node = SCHEDULER_NODE_OF_WAIT_CHAIN_NODE( first );
+  scheduler_node = SCHEDULER_NODE_OF_WAIT_PRIORITY_NODE( first );
 
   return _Scheduler_Node_get_owner( scheduler_node );
 }
 
 static Thread_Control *_Thread_queue_FIFO_surrender(
-  Thread_queue_Queue *queue,
-  Thread_queue_Heads *heads,
-  Thread_Control     *previous_owner
+  Thread_queue_Queue   *queue,
+  Thread_queue_Heads   *heads,
+  Thread_Control       *previous_owner,
+  Thread_queue_Context *queue_context
 )
 {
   Thread_Control *first;
@@ -194,6 +221,8 @@ static Thread_Control *_Thread_queue_FIFO_surrender(
   _Thread_queue_Queue_extract(
     queue,
     heads,
+    NULL,
+    queue_context,
     first,
     _Thread_queue_FIFO_do_extract
   );
@@ -202,166 +231,176 @@ static Thread_Control *_Thread_queue_FIFO_surrender(
 }
 
 static Thread_queue_Priority_queue *_Thread_queue_Priority_queue(
-  Thread_queue_Heads   *heads,
-  const Thread_Control *the_thread
+  Thread_queue_Heads         *heads,
+  const Priority_Aggregation *priority_aggregation
 )
 {
 #if defined(RTEMS_SMP)
   return &heads->Priority[
-    _Scheduler_Get_index( _Scheduler_Get_own( the_thread ) )
+    _Scheduler_Get_index( _Priority_Get_scheduler( priority_aggregation ) )
   ];
 #else
-  (void) the_thread;
-
+  (void) priority_aggregation;
   return &heads->Heads.Priority;
 #endif
 }
 
-static bool _Thread_queue_Priority_less(
-  const void        *left,
-  const RBTree_Node *right
-)
-{
-  const Priority_Control *the_left;
-  const Scheduler_Node   *scheduler_node;
-  const Thread_Control   *the_right;
-
-  the_left = left;
-  scheduler_node = SCHEDULER_NODE_OF_WAIT_RBTREE_NODE( right );
-  the_right = _Scheduler_Node_get_owner( scheduler_node );
-
-  return *the_left < _Thread_Get_priority( the_right );
-}
-
-static void _Thread_queue_Priority_priority_change(
+static void _Thread_queue_Priority_priority_actions(
   Thread_queue_Queue *queue,
-  Thread_Control     *the_thread,
-  Priority_Control    new_priority
+  Priority_Actions   *priority_actions
 )
 {
-  Thread_queue_Heads          *heads;
-  Thread_queue_Priority_queue *priority_queue;
-  Scheduler_Node              *scheduler_node;
+  Thread_queue_Heads   *heads;
+  Priority_Aggregation *priority_aggregation;
+
+  _Assert( !_Priority_Actions_is_empty( priority_actions ) );
 
   heads = queue->heads;
   _Assert( heads != NULL );
 
-  priority_queue = _Thread_queue_Priority_queue( heads, the_thread );
-  scheduler_node = _Scheduler_Thread_get_own_node( the_thread );
+  priority_aggregation = _Priority_Actions_get_first( priority_actions );
 
-  _RBTree_Extract(
-    &priority_queue->Queue,
-    &scheduler_node->Wait.Node.RBTree
-  );
-  _RBTree_Insert_inline(
-    &priority_queue->Queue,
-    &scheduler_node->Wait.Node.RBTree,
-    &new_priority,
-    _Thread_queue_Priority_less
-  );
+  do {
+    Thread_queue_Priority_queue *priority_queue;
+
+    priority_queue = _Thread_queue_Priority_queue(
+      heads,
+      priority_aggregation
+    );
+
+    _Priority_Plain_extract(
+      &priority_queue->Queue,
+      &priority_aggregation->Node
+    );
+    _Priority_Plain_insert(
+      &priority_queue->Queue,
+      &priority_aggregation->Node,
+      priority_aggregation->Node.priority
+    );
+
+    priority_aggregation = _Priority_Get_next_action( priority_aggregation );
+  } while ( _Priority_Actions_is_valid( priority_aggregation ) );
+
+  _Priority_Actions_initialize_empty( priority_actions );
 }
 
 static void _Thread_queue_Priority_do_initialize(
-  Thread_queue_Heads *heads,
-  Thread_Control     *the_thread
+  Thread_queue_Queue   *queue,
+  Thread_Control       *the_thread,
+  Thread_queue_Context *queue_context,
+  Thread_queue_Heads   *heads
 )
 {
-  Thread_queue_Priority_queue *priority_queue;
   Scheduler_Node              *scheduler_node;
+  Priority_Aggregation        *priority_aggregation;
+  Thread_queue_Priority_queue *priority_queue;
 
-  priority_queue = _Thread_queue_Priority_queue( heads, the_thread );
+  scheduler_node = _Thread_Scheduler_get_own_node( the_thread );
+  priority_aggregation = &scheduler_node->Wait.Priority;
+  priority_queue = _Thread_queue_Priority_queue( heads, priority_aggregation );
 
 #if defined(RTEMS_SMP)
   _Chain_Initialize_one( &heads->Heads.Fifo, &priority_queue->Node );
 #endif
 
-  scheduler_node = _Scheduler_Thread_get_own_node( the_thread );
-
-  _RBTree_Initialize_node( &scheduler_node->Wait.Node.RBTree );
-  _RBTree_Initialize_one(
+  _Priority_Initialize_one(
     &priority_queue->Queue,
-    &scheduler_node->Wait.Node.RBTree
+    &scheduler_node->Wait.Priority.Node
   );
 }
 
 static void _Thread_queue_Priority_do_enqueue(
-  Thread_queue_Heads *heads,
-  Thread_Control     *the_thread
+  Thread_queue_Queue   *queue,
+  Thread_Control       *the_thread,
+  Thread_queue_Context *queue_context,
+  Thread_queue_Heads   *heads
 )
 {
-  Thread_queue_Priority_queue *priority_queue;
   Scheduler_Node              *scheduler_node;
-  Priority_Control             current_priority;
+  Priority_Aggregation        *priority_aggregation;
+  Thread_queue_Priority_queue *priority_queue;
 
-  priority_queue = _Thread_queue_Priority_queue( heads, the_thread );
+  scheduler_node = _Thread_Scheduler_get_own_node( the_thread );
+  priority_aggregation = &scheduler_node->Wait.Priority;
+  priority_queue = _Thread_queue_Priority_queue( heads, priority_aggregation );
 
 #if defined(RTEMS_SMP)
-  if ( _RBTree_Is_empty( &priority_queue->Queue ) ) {
+  if ( _Priority_Is_empty( &priority_queue->Queue ) ) {
     _Chain_Append_unprotected( &heads->Heads.Fifo, &priority_queue->Node );
   }
 #endif
 
-  scheduler_node = _Scheduler_Thread_get_own_node( the_thread );
-  current_priority = _Thread_Get_priority( the_thread );
+  scheduler_node = _Thread_Scheduler_get_own_node( the_thread );
 
-  _RBTree_Initialize_node( &scheduler_node->Wait.Node.RBTree );
-  _RBTree_Insert_inline(
+  _Priority_Node_initialize(
+    &scheduler_node->Wait.Priority.Node,
+    scheduler_node->Wait.Priority.Node.priority
+  );
+  _Priority_Plain_insert(
     &priority_queue->Queue,
-    &scheduler_node->Wait.Node.RBTree,
-    &current_priority,
-    _Thread_queue_Priority_less
+    &scheduler_node->Wait.Priority.Node,
+    scheduler_node->Wait.Priority.Node.priority
   );
 }
 
 static void _Thread_queue_Priority_do_extract(
-  Thread_queue_Heads *heads,
-  Thread_Control     *the_thread
+  Thread_queue_Queue   *queue,
+  Thread_queue_Heads   *heads,
+  Thread_Control       *current_or_previous_owner,
+  Thread_queue_Context *queue_context,
+  Thread_Control       *the_thread
 )
 {
-  Thread_queue_Priority_queue *priority_queue;
   Scheduler_Node              *scheduler_node;
+  Priority_Aggregation        *priority_aggregation;
+  Thread_queue_Priority_queue *priority_queue;
+
+  (void) queue_context;
 
-  priority_queue = _Thread_queue_Priority_queue( heads, the_thread );
-  scheduler_node = _Scheduler_Thread_get_own_node( the_thread );
+  scheduler_node = _Thread_Scheduler_get_own_node( the_thread );
+  priority_aggregation = &scheduler_node->Wait.Priority;
+  priority_queue = _Thread_queue_Priority_queue( heads, priority_aggregation );
 
-  _RBTree_Extract(
+  _Priority_Plain_extract(
     &priority_queue->Queue,
-    &scheduler_node->Wait.Node.RBTree
+    &scheduler_node->Wait.Priority.Node
   );
 
 #if defined(RTEMS_SMP)
   _Chain_Extract_unprotected( &priority_queue->Node );
 
-  if ( !_RBTree_Is_empty( &priority_queue->Queue ) ) {
+  if ( !_Priority_Is_empty( &priority_queue->Queue ) ) {
     _Chain_Append_unprotected( &heads->Heads.Fifo, &priority_queue->Node );
   }
 #endif
 }
 
 static void _Thread_queue_Priority_enqueue(
-  Thread_queue_Queue *queue,
-  Thread_Control     *the_thread,
-  Thread_queue_Path  *path
+  Thread_queue_Queue   *queue,
+  Thread_Control       *the_thread,
+  Thread_queue_Context *queue_context
 )
 {
-  path->update_priority = NULL;
-
   _Thread_queue_Queue_enqueue(
     queue,
     the_thread,
+    queue_context,
     _Thread_queue_Priority_do_initialize,
     _Thread_queue_Priority_do_enqueue
   );
 }
 
 static void _Thread_queue_Priority_extract(
-  Thread_queue_Queue *queue,
-  Thread_Control     *the_thread
+  Thread_queue_Queue   *queue,
+  Thread_Control       *the_thread,
+  Thread_queue_Context *queue_context
 )
 {
   _Thread_queue_Queue_extract(
     queue,
     queue->heads,
+    NULL,
+    queue_context,
     the_thread,
     _Thread_queue_Priority_do_extract
   );
@@ -372,7 +411,7 @@ static Thread_Control *_Thread_queue_Priority_first(
 )
 {
   Thread_queue_Priority_queue *priority_queue;
-  RBTree_Node                 *first;
+  Priority_Node               *first;
   Scheduler_Node              *scheduler_node;
 
 #if defined(RTEMS_SMP)
@@ -383,17 +422,18 @@ static Thread_Control *_Thread_queue_Priority_first(
   priority_queue = &heads->Heads.Priority;
 #endif
 
-  _Assert( !_RBTree_Is_empty( &priority_queue->Queue ) );
-  first = _RBTree_Minimum( &priority_queue->Queue );
-  scheduler_node = SCHEDULER_NODE_OF_WAIT_RBTREE_NODE( first );
+  _Assert( !_Priority_Is_empty( &priority_queue->Queue ) );
+  first = _Priority_Get_minimum_node( &priority_queue->Queue );
+  scheduler_node = SCHEDULER_NODE_OF_WAIT_PRIORITY_NODE( first );
 
   return _Scheduler_Node_get_owner( scheduler_node );
 }
 
 static Thread_Control *_Thread_queue_Priority_surrender(
-  Thread_queue_Queue *queue,
-  Thread_queue_Heads *heads,
-  Thread_Control     *previous_owner
+  Thread_queue_Queue   *queue,
+  Thread_queue_Heads   *heads,
+  Thread_Control       *previous_owner,
+  Thread_queue_Context *queue_context
 )
 {
   Thread_Control *first;
@@ -402,6 +442,8 @@ static Thread_Control *_Thread_queue_Priority_surrender(
   _Thread_queue_Queue_extract(
     queue,
     heads,
+    NULL,
+    queue_context,
     first,
     _Thread_queue_Priority_do_extract
   );
@@ -409,104 +451,537 @@ static Thread_Control *_Thread_queue_Priority_surrender(
   return first;
 }
 
-static void _Thread_queue_Priority_inherit_enqueue(
+static void _Thread_queue_Priority_inherit_add_change(
+  Priority_Aggregation *priority_aggregation,
+  bool                  prepend_it,
+  Priority_Actions     *priority_actions,
+  void                 *arg
+)
+{
+  Thread_Control *owner;
+  Scheduler_Node *scheduler_node;
+
+  owner = arg;
+  scheduler_node = _Thread_Scheduler_get_own_node( owner );
+
+  _Priority_Set_action_node( &scheduler_node->Wait.Priority, &priority_aggregation->Node );
+  _Priority_Set_action_type( &scheduler_node->Wait.Priority, PRIORITY_ACTION_CHANGE );
+  _Priority_Actions_add( priority_actions, &scheduler_node->Wait.Priority );
+}
+
+static void _Thread_queue_Priority_inherit_priority_actions(
   Thread_queue_Queue *queue,
-  Thread_Control     *the_thread,
-  Thread_queue_Path  *path
+  Priority_Actions   *actions_next
 )
 {
-  Thread_queue_Heads *heads;
-  Thread_Control     *owner;
-  Priority_Control    priority;
+  Thread_queue_Heads   *heads;
+  Thread_Control       *owner;
+  Priority_Actions      actions_now;
+  Priority_Aggregation *priority_aggregation;
 
-  heads = _Thread_queue_Queue_enqueue(
-    queue,
-    the_thread,
-    _Thread_queue_Priority_do_initialize,
-    _Thread_queue_Priority_do_enqueue
-  );
+  _Assert( !_Priority_Actions_is_empty( actions_next ) );
+
+  heads = queue->heads;
+  _Assert( heads != NULL );
 
   owner = queue->owner;
+  _Assert( owner != NULL );
 
-#if defined(RTEMS_SMP)
-  if ( _Chain_Has_only_one_node( &heads->Heads.Fifo ) ) {
-    priority = the_thread->current_priority;
-  } else {
-    priority = _Scheduler_Map_priority(
-      _Scheduler_Get_own( the_thread ),
-      PRIORITY_PSEUDO_ISR
+  _Priority_Actions_move( &actions_now, actions_next );
+  priority_aggregation = _Priority_Actions_get_first( &actions_now );
+
+  do {
+    Priority_Aggregation        *priority_aggregation_next;
+    Thread_queue_Priority_queue *priority_queue;
+
+    priority_aggregation_next = _Priority_Get_next_action(
+      priority_aggregation
+    );
+
+    priority_queue = _Thread_queue_Priority_queue(
+      heads,
+      priority_aggregation
+    );
+
+    _Priority_Change(
+      &priority_queue->Queue,
+      &priority_aggregation->Node,
+      false,
+      actions_next,
+      _Thread_queue_Priority_inherit_add_change,
+      owner
     );
+
+    priority_aggregation = priority_aggregation_next;
+  } while ( _Priority_Actions_is_valid( priority_aggregation ) );
+}
+
+static void _Thread_queue_Boost_priority(
+  Thread_queue_Heads   *heads,
+  Thread_Control       *the_thread,
+  Thread_Control       *owner,
+  Thread_queue_Context *queue_context
+)
+{
+#if defined(RTEMS_SMP)
+  const Scheduler_Control *scheduler;
+  const Scheduler_Control *scheduler_of_owner;
+  Scheduler_Node          *scheduler_node_of_owner;
+  Priority_Control         boost_priority;
+
+  if ( _Priority_Node_is_active( &heads->Boost_priority ) ) {
+    return;
   }
+
+  scheduler = _Scheduler_Get_own( the_thread );
+  scheduler_of_owner = _Scheduler_Get_own( owner );
+
+  if ( scheduler == scheduler_of_owner ) {
+    return;
+  }
+
+  scheduler_node_of_owner = _Thread_Scheduler_get_own_node( owner );
+
+  boost_priority = _Scheduler_Map_priority(
+    scheduler_of_owner,
+    PRIORITY_PSEUDO_ISR
+  );
+
+  _Priority_Node_initialize( &heads->Boost_priority, boost_priority );
+  _Priority_Actions_initialize_one(
+    &queue_context->Priority.Actions,
+    &scheduler_node_of_owner->Wait.Priority,
+    &heads->Boost_priority,
+    PRIORITY_ACTION_ADD
+  );
+  _Thread_Priority_perform_actions( owner, queue_context );
 #else
   (void) heads;
+  (void) the_thread;
+  (void) owner;
+  (void) queue_context;
+#endif
+}
+
+static void _Thread_queue_Priority_inherit_do_initialize(
+  Thread_queue_Queue   *queue,
+  Thread_Control       *the_thread,
+  Thread_queue_Context *queue_context,
+  Thread_queue_Heads   *heads
+)
+{
+  Scheduler_Node              *scheduler_node;
+  Priority_Aggregation        *priority_aggregation;
+  Thread_queue_Priority_queue *priority_queue;
+  Thread_Control              *owner;
+  Scheduler_Node              *scheduler_node_of_owner;
+
+  scheduler_node = _Thread_Scheduler_get_own_node( the_thread );
+  priority_aggregation = &scheduler_node->Wait.Priority;
+  priority_queue = _Thread_queue_Priority_queue( heads, priority_aggregation );
+
+#if defined(RTEMS_SMP)
+  _Chain_Initialize_one( &heads->Heads.Fifo, &priority_queue->Node );
+#endif
+
+  _Priority_Initialize_one(
+    &priority_queue->Queue,
+    &priority_aggregation->Node
+  );
+
+  owner = queue->owner;
+  scheduler_node_of_owner = _Thread_Scheduler_get_own_node( owner );
+  _Priority_Actions_initialize_one(
+    &queue_context->Priority.Actions,
+    &scheduler_node_of_owner->Wait.Priority,
+    &priority_queue->Queue.Node,
+    PRIORITY_ACTION_ADD
+  );
+  _Thread_Priority_perform_actions( owner, queue_context );
+  _Thread_queue_Boost_priority( heads, the_thread, owner, queue_context );
+}
+
+static void _Thread_queue_Priority_inherit_do_enqueue_change(
+  Priority_Aggregation *priority_aggregation,
+  bool                  prepend_it,
+  Priority_Actions     *priority_actions,
+  void                 *arg
+)
+{
+  Thread_queue_Queue   *queue;
+  Thread_Control       *owner;
+  Scheduler_Node       *scheduler_node_of_owner;
+  Thread_queue_Context *queue_context;
+
+  queue = arg;
+  owner = queue->owner;
+  scheduler_node_of_owner = _Thread_Scheduler_get_own_node( owner );
+  queue_context = THREAD_QUEUE_CONTEXT_OF_PRIORITY_ACTIONS( priority_actions );
+
+  _Priority_Actions_initialize_one(
+    &queue_context->Priority.Actions,
+    &scheduler_node_of_owner->Wait.Priority,
+    &priority_aggregation->Node,
+    PRIORITY_ACTION_CHANGE
+  );
+  _Thread_Priority_perform_actions( owner, queue_context );
+}
 
-  priority = the_thread->current_priority;
+static void _Thread_queue_Priority_inherit_do_enqueue(
+  Thread_queue_Queue   *queue,
+  Thread_Control       *the_thread,
+  Thread_queue_Context *queue_context,
+  Thread_queue_Heads   *heads
+)
+{
+  Scheduler_Node              *scheduler_node;
+  Priority_Aggregation        *priority_aggregation;
+  Thread_queue_Priority_queue *priority_queue;
+
+  scheduler_node = _Thread_Scheduler_get_own_node( the_thread );
+  priority_aggregation = &scheduler_node->Wait.Priority;
+  priority_queue = _Thread_queue_Priority_queue( heads, priority_aggregation );
+
+#if defined(RTEMS_SMP)
+  if ( _Priority_Is_empty( &priority_queue->Queue ) ) {
+    Thread_Control *owner;
+    Scheduler_Node *scheduler_node_of_owner;
+
+    _Chain_Append_unprotected( &heads->Heads.Fifo, &priority_queue->Node );
+
+    _Priority_Initialize_one(
+      &priority_queue->Queue,
+      &priority_aggregation->Node
+    );
+
+    owner = queue->owner;
+    scheduler_node_of_owner = _Thread_Scheduler_get_own_node( owner );
+
+    _Priority_Actions_initialize_one(
+      &queue_context->Priority.Actions,
+      &scheduler_node_of_owner->Wait.Priority,
+      &priority_queue->Queue.Node,
+      PRIORITY_ACTION_ADD
+    );
+    _Thread_Priority_perform_actions( owner, queue_context );
+    _Thread_queue_Boost_priority( heads, the_thread, owner, queue_context );
+    return;
+  }
 #endif
 
-  if ( priority < owner->current_priority ) {
-    path->update_priority = owner;
+  _Priority_Non_empty_insert(
+    &priority_queue->Queue,
+    &priority_aggregation->Node,
+    &queue_context->Priority.Actions,
+    _Thread_queue_Priority_inherit_do_enqueue_change,
+    queue
+  );
+  _Thread_queue_Boost_priority(
+    heads,
+    the_thread,
+    queue->owner,
+    queue_context
+  );
+}
+
+static void _Thread_queue_Priority_inherit_enqueue(
+  Thread_queue_Queue   *queue,
+  Thread_Control       *the_thread,
+  Thread_queue_Context *queue_context
+)
+{
+  _Thread_queue_Queue_enqueue(
+    queue,
+    the_thread,
+    queue_context,
+    _Thread_queue_Priority_inherit_do_initialize,
+    _Thread_queue_Priority_inherit_do_enqueue
+  );
+}
 
-    owner->priority_restore_hint = true;
-    _Atomic_Fence( ATOMIC_ORDER_ACQ_REL );
+static void _Thread_queue_Priority_inherit_do_extract_action(
+  Priority_Actions     *priority_actions,
+  Thread_Control       *owner,
+  Priority_Node        *priority_action_node,
+  Priority_Action_type  priority_action_type
+)
+{
+  Thread_queue_Context *queue_context;
+  Scheduler_Node       *scheduler_node_of_owner;
 
-    _Scheduler_Thread_set_priority( owner, priority, false );
+  queue_context = THREAD_QUEUE_CONTEXT_OF_PRIORITY_ACTIONS( priority_actions );
+  scheduler_node_of_owner = _Thread_Scheduler_get_own_node( owner );
 
-    ( *owner->Wait.operations->priority_change )(
-      owner->Wait.queue,
+  _Priority_Actions_initialize_one(
+    &queue_context->Priority.Actions,
+    &scheduler_node_of_owner->Wait.Priority,
+    priority_action_node,
+    priority_action_type
+  );
+  _Thread_Priority_perform_actions( owner, queue_context );
+}
+
+static void _Thread_queue_Priority_inherit_do_extract_remove(
+  Priority_Aggregation *priority_aggregation,
+  Priority_Actions     *priority_actions,
+  void                 *arg
+)
+{
+  _Thread_queue_Priority_inherit_do_extract_action(
+    priority_actions,
+    arg,
+    &priority_aggregation->Node,
+    PRIORITY_ACTION_REMOVE
+  );
+}
+
+static void _Thread_queue_Priority_inherit_do_extract_change(
+  Priority_Aggregation *priority_aggregation,
+  bool                  prepend_it,
+  Priority_Actions     *priority_actions,
+  void                 *arg
+)
+{
+  _Thread_queue_Priority_inherit_do_extract_action(
+    priority_actions,
+    arg,
+    &priority_aggregation->Node,
+    PRIORITY_ACTION_CHANGE
+  );
+}
+
+static void _Thread_queue_Priority_inherit_do_extract(
+  Thread_queue_Queue   *queue,
+  Thread_queue_Heads   *heads,
+  Thread_Control       *owner,
+  Thread_queue_Context *queue_context,
+  Thread_Control       *the_thread
+)
+{
+  Scheduler_Node              *scheduler_node;
+  Priority_Aggregation        *priority_aggregation;
+  Thread_queue_Priority_queue *priority_queue;
+
+  scheduler_node = _Thread_Scheduler_get_own_node( the_thread );
+  priority_aggregation = &scheduler_node->Wait.Priority;
+  priority_queue = _Thread_queue_Priority_queue( heads, priority_aggregation );
+
+  _Thread_queue_Path_acquire_critical( queue, the_thread, queue_context );
+
+  _Priority_Extract(
+    &priority_queue->Queue,
+    &scheduler_node->Wait.Priority.Node,
+    &queue_context->Priority.Actions,
+    _Thread_queue_Priority_inherit_do_extract_remove,
+    _Thread_queue_Priority_inherit_do_extract_change,
+    owner
+  );
+
+#if defined(RTEMS_SMP)
+  _Chain_Extract_unprotected( &priority_queue->Node );
+
+  if ( !_Priority_Is_empty( &priority_queue->Queue ) ) {
+    _Chain_Append_unprotected( &heads->Heads.Fifo, &priority_queue->Node );
+  }
+
+  if (
+    _Priority_Node_is_active( &heads->Boost_priority )
+      && ( _Chain_Is_empty( &heads->Heads.Fifo )
+        || _Chain_Has_only_one_node( &heads->Heads.Fifo ) )
+  ) {
+    _Thread_queue_Priority_inherit_do_extract_action(
+      &queue_context->Priority.Actions,
       owner,
-      priority
+      &heads->Boost_priority,
+      PRIORITY_ACTION_REMOVE
     );
-  } else {
-    path->update_priority = NULL;
+    _Priority_Node_set_inactive( &heads->Boost_priority );
   }
+#endif
+
+  _Thread_queue_Path_release_critical( queue_context );
 }
 
-static void _Thread_queue_Boost_priority(
-  Thread_queue_Heads *heads,
-  Thread_Control     *the_thread
+static void _Thread_queue_Priority_inherit_extract(
+  Thread_queue_Queue   *queue,
+  Thread_Control       *the_thread,
+  Thread_queue_Context *queue_context
+)
+{
+  _Thread_queue_Queue_extract(
+    queue,
+    queue->heads,
+    queue->owner,
+    queue_context,
+    the_thread,
+    _Thread_queue_Priority_inherit_do_extract
+  );
+}
+
+static void _Thread_queue_Priority_do_change(
+  Priority_Aggregation *priority_aggregation,
+  bool                  prepend_it,
+  Priority_Actions     *priority_actions,
+  void                 *arg
+)
+{
+  _Thread_queue_Context_add_priority_update(
+    THREAD_QUEUE_CONTEXT_OF_PRIORITY_ACTIONS( priority_actions ),
+    arg
+  );
+  _Scheduler_Node_set_priority(
+    SCHEDULER_NODE_OF_WAIT_PRIORITY_NODE( priority_aggregation ),
+    _Priority_Get_priority( priority_aggregation ),
+    prepend_it
+  );
+}
+
+static void _Thread_queue_Priority_add(
+  Thread_Control       *the_thread,
+  Priority_Aggregation *priority_aggregation,
+  Priority_Node        *priority_node,
+  Thread_queue_Context *queue_context
+)
+{
+  _Priority_Non_empty_insert(
+    priority_aggregation,
+    priority_node,
+    &queue_context->Priority.Actions,
+    _Thread_queue_Priority_do_change,
+    the_thread
+  );
+}
+
+static void _Thread_queue_Priority_remove(
+  Thread_Control       *the_thread,
+  Priority_Aggregation *priority_aggregation,
+  Priority_Node        *priority_node,
+  Thread_queue_Context *queue_context
+)
+{
+  _Priority_Extract_non_empty(
+    priority_aggregation,
+    priority_node,
+    &queue_context->Priority.Actions,
+    _Thread_queue_Priority_do_change,
+    the_thread
+  );
+}
+
+static void _Thread_queue_Priority_inherit_do_surrender(
+  Thread_queue_Queue   *queue,
+  Thread_queue_Heads   *heads,
+  Thread_Control       *previous_owner,
+  Thread_queue_Context *queue_context,
+  Thread_Control       *the_thread
 )
 {
+  Scheduler_Node              *scheduler_node;
+  Scheduler_Node              *scheduler_node_of_previous_owner;
+  Priority_Aggregation        *priority_aggregation;
+  Thread_queue_Priority_queue *priority_queue;
+  ISR_lock_Context             lock_context;
+
+  scheduler_node = _Thread_Scheduler_get_own_node( the_thread );
+  scheduler_node_of_previous_owner = _Thread_Scheduler_get_own_node(
+    previous_owner
+  );
+  priority_aggregation = &scheduler_node->Wait.Priority;
+  priority_queue = _Thread_queue_Priority_queue( heads, priority_aggregation );
+
+  _Thread_Wait_acquire_default_critical( previous_owner, &lock_context );
+
 #if defined(RTEMS_SMP)
-  if ( !_Chain_Has_only_one_node( &heads->Heads.Fifo ) ) {
-    const Scheduler_Control *scheduler;
-    Priority_Control         boost_priority;
+  if ( _Priority_Node_is_active( &heads->Boost_priority ) ) {
+    _Thread_queue_Priority_remove(
+      previous_owner,
+      &scheduler_node_of_previous_owner->Wait.Priority,
+      &heads->Boost_priority,
+      queue_context
+    );
+    _Priority_Node_set_inactive( &heads->Boost_priority );
+  }
+#endif
+
+  _Thread_queue_Priority_remove(
+    previous_owner,
+    &scheduler_node_of_previous_owner->Wait.Priority,
+    &priority_queue->Queue.Node,
+    queue_context
+  );
 
-    the_thread->priority_restore_hint = true;
-    _Atomic_Fence( ATOMIC_ORDER_ACQ_REL );
+  _Thread_Wait_release_default_critical( previous_owner, &lock_context );
 
-    scheduler = _Scheduler_Get_own( the_thread );
-    boost_priority = _Scheduler_Map_priority( scheduler, PRIORITY_PSEUDO_ISR );
+  _Priority_Extract(
+    &priority_queue->Queue,
+    &priority_aggregation->Node,
+    NULL,
+    _Priority_Remove_nothing,
+    _Priority_Change_nothing,
+    previous_owner
+  );
 
-    _Scheduler_Thread_set_priority( the_thread, boost_priority, false );
+  if ( !_Priority_Is_empty( &priority_queue->Queue ) ) {
+    _Thread_queue_Priority_add(
+      the_thread,
+      priority_aggregation,
+      &priority_queue->Queue.Node,
+      queue_context
+    );
+  }
+
+#if defined(RTEMS_SMP)
+  _Chain_Extract_unprotected( &priority_queue->Node );
+
+  if ( !_Priority_Is_empty( &priority_queue->Queue ) ) {
+    _Chain_Append_unprotected( &heads->Heads.Fifo, &priority_queue->Node );
+  }
+
+  if (
+    !_Chain_Is_empty( &heads->Heads.Fifo)
+      && !_Chain_Has_only_one_node( &heads->Heads.Fifo)
+  ) {
+    Priority_Control boost_priority;
+
+    boost_priority = _Scheduler_Map_priority(
+      _Scheduler_Get_own( the_thread ),
+      PRIORITY_PSEUDO_ISR
+    );
+    _Priority_Node_initialize( &heads->Boost_priority, boost_priority );
+    _Thread_queue_Priority_add(
+      the_thread,
+      priority_aggregation,
+      &heads->Boost_priority,
+      queue_context
+    );
   }
-#else
-  (void) heads;
-  (void) the_thread;
 #endif
 }
 
 static Thread_Control *_Thread_queue_Priority_inherit_surrender(
-  Thread_queue_Queue *queue,
-  Thread_queue_Heads *heads,
-  Thread_Control     *previous_owner
+  Thread_queue_Queue   *queue,
+  Thread_queue_Heads   *heads,
+  Thread_Control       *previous_owner,
+  Thread_queue_Context *queue_context
 )
 {
   Thread_Control *first;
 
   first = _Thread_queue_Priority_first( heads );
-  _Thread_queue_Boost_priority( heads, first );
   _Thread_queue_Queue_extract(
     queue,
     heads,
+    previous_owner,
+    queue_context,
     first,
-    _Thread_queue_Priority_do_extract
+    _Thread_queue_Priority_inherit_do_surrender
   );
 
   return first;
 }
 
 const Thread_queue_Operations _Thread_queue_Operations_default = {
-  .priority_change = _Thread_queue_Do_nothing_priority_change,
+  .priority_actions = _Thread_queue_Do_nothing_priority_actions,
   .extract = _Thread_queue_Do_nothing_extract
   /*
    * The default operations are only used in _Thread_Change_priority() and
@@ -516,7 +991,7 @@ const Thread_queue_Operations _Thread_queue_Operations_default = {
 };
 
 const Thread_queue_Operations _Thread_queue_Operations_FIFO = {
-  .priority_change = _Thread_queue_Do_nothing_priority_change,
+  .priority_actions = _Thread_queue_Do_nothing_priority_actions,
   .enqueue = _Thread_queue_FIFO_enqueue,
   .extract = _Thread_queue_FIFO_extract,
   .surrender = _Thread_queue_FIFO_surrender,
@@ -524,7 +999,7 @@ const Thread_queue_Operations _Thread_queue_Operations_FIFO = {
 };
 
 const Thread_queue_Operations _Thread_queue_Operations_priority = {
-  .priority_change = _Thread_queue_Priority_priority_change,
+  .priority_actions = _Thread_queue_Priority_priority_actions,
   .enqueue = _Thread_queue_Priority_enqueue,
   .extract = _Thread_queue_Priority_extract,
   .surrender = _Thread_queue_Priority_surrender,
@@ -532,9 +1007,9 @@ const Thread_queue_Operations _Thread_queue_Operations_priority = {
 };
 
 const Thread_queue_Operations _Thread_queue_Operations_priority_inherit = {
-  .priority_change = _Thread_queue_Priority_priority_change,
+  .priority_actions = _Thread_queue_Priority_inherit_priority_actions,
   .enqueue = _Thread_queue_Priority_inherit_enqueue,
-  .extract = _Thread_queue_Priority_extract,
+  .extract = _Thread_queue_Priority_inherit_extract,
   .surrender = _Thread_queue_Priority_inherit_surrender,
   .first = _Thread_queue_Priority_first
 };
diff --git a/cpukit/score/src/threadrestart.c b/cpukit/score/src/threadrestart.c
index 1498827..6953400 100644
--- a/cpukit/score/src/threadrestart.c
+++ b/cpukit/score/src/threadrestart.c
@@ -50,40 +50,28 @@ static Thread_Zombie_control _Thread_Zombies = {
   .Lock = ISR_LOCK_INITIALIZER( "thread zombies" )
 };
 
-static bool _Thread_Raise_real_priority_filter(
+static void _Thread_Raise_real_priority(
   Thread_Control   *the_thread,
-  Priority_Control *new_priority_ptr,
-  void             *arg
+  Priority_Control  priority
 )
 {
-  Priority_Control real_priority;
-  Priority_Control new_priority;
-  Priority_Control current_priority;
-
-  real_priority = the_thread->real_priority;
-  new_priority = *new_priority_ptr;
-  current_priority = _Thread_Get_priority( the_thread );
-
-  new_priority = _Thread_Priority_highest( real_priority, new_priority );
-  *new_priority_ptr = new_priority;
+  Thread_queue_Context queue_context;
 
-  the_thread->real_priority = new_priority;
+  _Thread_queue_Context_clear_priority_updates( &queue_context );
+  _Thread_Wait_acquire( the_thread, &queue_context );
 
-  return _Thread_Priority_less_than( current_priority, new_priority );
-}
+  if ( priority < the_thread->Real_priority.priority ) {
+    _Thread_Priority_change(
+      the_thread,
+      &the_thread->Real_priority,
+      priority,
+      false,
+      &queue_context
+    );
+  }
 
-static void _Thread_Raise_real_priority(
-  Thread_Control   *the_thread,
-  Priority_Control  priority
-)
-{
-  _Thread_Change_priority(
-    the_thread,
-    priority,
-    NULL,
-    _Thread_Raise_real_priority_filter,
-    false
-  );
+  _Thread_Wait_release( the_thread, &queue_context );
+  _Thread_Priority_update( &queue_context );
 }
 
 typedef struct {
@@ -182,7 +170,7 @@ static void _Thread_Free( Thread_Control *the_thread )
   _ISR_lock_Destroy( &the_thread->Keys.Lock );
   _Scheduler_Node_destroy(
     _Scheduler_Get( the_thread ),
-    _Scheduler_Thread_get_own_node( the_thread )
+    _Thread_Scheduler_get_own_node( the_thread )
   );
   _ISR_lock_Destroy( &the_thread->Timer.Lock );
 
@@ -622,8 +610,8 @@ void _Thread_Restart_self(
   ISR_lock_Context               *lock_context
 )
 {
-  Per_CPU_Control  *cpu_self;
-  Priority_Control  unused;
+  Per_CPU_Control      *cpu_self;
+  Thread_queue_Context  queue_context;
 
   _Assert(
     _Watchdog_Get_state( &executing->Timer.Watchdog ) == WATCHDOG_INACTIVE
@@ -646,13 +634,18 @@ void _Thread_Restart_self(
   cpu_self = _Thread_Dispatch_disable_critical( lock_context );
   _Thread_State_release( executing, lock_context );
 
-  _Thread_Set_priority(
+  _Thread_queue_Context_clear_priority_updates( &queue_context );
+  _Thread_Wait_acquire_default( executing, lock_context );
+  _Thread_Priority_change(
     executing,
+    &executing->Real_priority,
     executing->Start.initial_priority,
-    &unused,
-    true
+    false,
+    &queue_context
   );
+  _Thread_Wait_release_default( executing, lock_context );
 
+  _Thread_Priority_update( &queue_context );
   _Thread_Dispatch_enable( cpu_self );
   RTEMS_UNREACHABLE();
 }
diff --git a/cpukit/score/src/threadsetpriority.c b/cpukit/score/src/threadsetpriority.c
deleted file mode 100644
index d6b8319..0000000
--- a/cpukit/score/src/threadsetpriority.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/**
- *  @file
- *
- *  @brief Set Thread Priority
- *  @ingroup ScoreThread
- */
-
-/*
- *  COPYRIGHT (c) 1989-2011.
- *  On-Line Applications Research Corporation (OAR).
- *
- *  The license and distribution terms for this file may be
- *  found in the file LICENSE in this distribution or at
- *  http://www.rtems.org/license/LICENSE.
- */
-
-#if HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <rtems/score/threadimpl.h>
-
-static bool _Thread_Set_priority_filter(
-  Thread_Control   *the_thread,
-  Priority_Control *new_priority_ptr,
-  void             *arg
-)
-{
-  Priority_Control  current_priority;
-  Priority_Control  new_priority;
-  Priority_Control *old_priority_ptr;
-
-  current_priority = _Thread_Get_priority( the_thread );
-  new_priority = *new_priority_ptr;
-
-  old_priority_ptr = arg;
-  *old_priority_ptr = current_priority;
-
-  the_thread->real_priority = new_priority;
-
-  return _Thread_Priority_less_than( current_priority, new_priority )
-    || !_Thread_Owns_resources( the_thread );
-}
-
-void _Thread_Set_priority(
-  Thread_Control   *the_thread,
-  Priority_Control  new_priority,
-  Priority_Control *old_priority,
-  bool              prepend_it
-)
-{
-  _Thread_Change_priority(
-    the_thread,
-    new_priority,
-    old_priority,
-    _Thread_Set_priority_filter,
-    prepend_it
-  );
-}
diff --git a/cpukit/score/src/threadtimeout.c b/cpukit/score/src/threadtimeout.c
index b6b6cc4..8297c55 100644
--- a/cpukit/score/src/threadtimeout.c
+++ b/cpukit/score/src/threadtimeout.c
@@ -30,6 +30,8 @@ void _Thread_Timeout( Watchdog_Control *watchdog )
   bool                  unblock;
 
   the_thread = RTEMS_CONTAINER_OF( watchdog, Thread_Control, Timer.Watchdog );
+
+  _Thread_queue_Context_clear_priority_updates( &queue_context );
   _Thread_Wait_acquire( the_thread, &queue_context );
 
   wait_flags = _Thread_Wait_flags_get( the_thread );
@@ -66,6 +68,7 @@ void _Thread_Timeout( Watchdog_Control *watchdog )
   }
 
   _Thread_Wait_release( the_thread, &queue_context );
+  _Thread_Priority_update( &queue_context );
 
   if ( unblock ) {
     _Thread_Wait_tranquilize( the_thread );
diff --git a/testsuites/smptests/smpmutex01/init.c b/testsuites/smptests/smpmutex01/init.c
index 5adc2e2..93c059e 100644
--- a/testsuites/smptests/smpmutex01/init.c
+++ b/testsuites/smptests/smpmutex01/init.c
@@ -315,10 +315,9 @@ static void test(void)
   request(ctx, B_5_0, REQ_MTX_RELEASE);
   check_generations(ctx, B_5_0, A_2_1);
   assert_prio(ctx, B_5_0, 5);
-  assert_prio(ctx, A_2_1, 0);
+  assert_prio(ctx, A_2_1, 2);
   request(ctx, A_2_1, REQ_MTX_RELEASE);
   check_generations(ctx, A_2_1, B_5_1);
-  assert_prio(ctx, A_2_1, 2);
   assert_prio(ctx, B_5_1, 5);
   request(ctx, B_5_1, REQ_MTX_RELEASE);
   check_generations(ctx, B_5_1, NONE);
diff --git a/testsuites/smptests/smpscheduler03/init.c b/testsuites/smptests/smpscheduler03/init.c
index c114eb9..50d4894 100644
--- a/testsuites/smptests/smpscheduler03/init.c
+++ b/testsuites/smptests/smpscheduler03/init.c
@@ -40,28 +40,35 @@ typedef struct {
 
 static test_context test_instance;
 
-static bool change_priority_filter(
-  Thread_Control   *thread,
-  Priority_Control *new_priority,
-  void             *arg
+static void apply_priority(
+  Thread_Control *thread,
+  Priority_Control new_priority,
+  bool prepend_it,
+  Thread_queue_Context *queue_context
 )
 {
-  return _Thread_Get_priority( thread ) != *new_priority;
+  _Thread_queue_Context_clear_priority_updates(queue_context);
+  _Thread_Wait_acquire(thread, queue_context);
+  _Thread_Priority_change(
+    thread,
+    &thread->Real_priority,
+    new_priority,
+    prepend_it,
+    queue_context
+  );
+  _Thread_Wait_release(thread, queue_context);
 }
 
 static void change_priority(
-  Thread_Control   *thread,
-  Priority_Control  new_priority,
-  bool              prepend_it
+  Thread_Control *thread,
+  Priority_Control new_priority,
+  bool prepend_it
 )
 {
-  _Thread_Change_priority(
-    thread,
-    new_priority,
-    NULL,
-    change_priority_filter,
-    prepend_it
-  );
+  Thread_queue_Context queue_context;
+
+  apply_priority(thread, new_priority, prepend_it, &queue_context);
+  _Thread_Priority_update(&queue_context);
 }
 
 static void barrier_wait(test_context *ctx)
@@ -197,11 +204,9 @@ static Thread_Control *update_priority_op(
   ISR_lock_Context state_lock_context;
   ISR_lock_Context scheduler_lock_context;
   Thread_Control *needs_help;
-  Scheduler_Node *node;
+  Thread_queue_Context queue_context;
 
-  thread->current_priority = new_priority;
-  node = _Scheduler_Thread_get_node(thread);
-  _Scheduler_Node_set_priority(node, new_priority, prepend_it);
+  apply_priority(thread, new_priority, prepend_it, &queue_context);
 
   _Thread_State_acquire( thread, &state_lock_context );
   scheduler = _Scheduler_Get( thread );
diff --git a/testsuites/sptests/spmutex01/init.c b/testsuites/sptests/spmutex01/init.c
index c363370..72e458f 100644
--- a/testsuites/sptests/spmutex01/init.c
+++ b/testsuites/sptests/spmutex01/init.c
@@ -41,13 +41,14 @@ typedef enum {
   REQ_MTX_0_OBTAIN = RTEMS_EVENT_2,
   REQ_MTX_0_RELEASE = RTEMS_EVENT_3,
   REQ_MTX_1_OBTAIN = RTEMS_EVENT_4,
-  REQ_MTX_1_RELEASE = RTEMS_EVENT_5,
-  REQ_MTX_2_OBTAIN = RTEMS_EVENT_6,
-  REQ_MTX_2_RELEASE = RTEMS_EVENT_7,
-  REQ_MTX_C11_OBTAIN = RTEMS_EVENT_8,
-  REQ_MTX_C11_RELEASE = RTEMS_EVENT_9,
-  REQ_MTX_POSIX_OBTAIN = RTEMS_EVENT_10,
-  REQ_MTX_POSIX_RELEASE = RTEMS_EVENT_11
+  REQ_MTX_1_OBTAIN_TIMEOUT = RTEMS_EVENT_5,
+  REQ_MTX_1_RELEASE = RTEMS_EVENT_6,
+  REQ_MTX_2_OBTAIN = RTEMS_EVENT_7,
+  REQ_MTX_2_RELEASE = RTEMS_EVENT_8,
+  REQ_MTX_C11_OBTAIN = RTEMS_EVENT_9,
+  REQ_MTX_C11_RELEASE = RTEMS_EVENT_10,
+  REQ_MTX_POSIX_OBTAIN = RTEMS_EVENT_11,
+  REQ_MTX_POSIX_RELEASE = RTEMS_EVENT_12
 } request_id;
 
 typedef enum {
@@ -110,6 +111,14 @@ static void send_event(test_context *ctx, task_id id, rtems_event_set events)
   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
 }
 
+static void wait(void)
+{
+  rtems_status_code sc;
+
+  sc = rtems_task_wake_after(4);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+}
+
 static rtems_event_set wait_for_events(void)
 {
   rtems_event_set events;
@@ -141,6 +150,14 @@ static void request(test_context *ctx, task_id id, request_id req)
   sync_with_helper(ctx);
 }
 
+static void obtain_timeout(test_context *ctx, mutex_id id)
+{
+  rtems_status_code sc;
+
+  sc = rtems_semaphore_obtain(ctx->mtx[id], RTEMS_WAIT, 2);
+  rtems_test_assert(sc == RTEMS_TIMEOUT);
+}
+
 static void obtain(test_context *ctx, mutex_id id)
 {
   rtems_status_code sc;
@@ -249,6 +266,22 @@ static void assert_prio(
   rtems_test_assert(expected == actual);
 }
 
+static void change_prio(
+  test_context *ctx,
+  task_id id,
+  rtems_task_priority prio
+)
+{
+  rtems_status_code sc;
+
+  sc = rtems_task_set_priority(
+    ctx->tasks[id],
+    prio,
+    &prio
+  );
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+}
+
 static void helper(rtems_task_argument arg)
 {
   test_context *ctx = &test_instance;
@@ -283,6 +316,11 @@ static void worker(rtems_task_argument arg)
       ++ctx->generation[id];
     }
 
+    if ((events & REQ_MTX_1_OBTAIN_TIMEOUT) != 0) {
+      obtain_timeout(ctx, MTX_1);
+      ++ctx->generation[id];
+    }
+
     if ((events & REQ_MTX_1_RELEASE) != 0) {
       release(ctx, MTX_1);
       ++ctx->generation[id];
@@ -370,10 +408,19 @@ static void set_up(test_context *ctx)
 
 static void test_inherit(test_context *ctx)
 {
+  assert_prio(ctx, M, 3);
   obtain(ctx, MTX_0);
   request(ctx, A_1, REQ_MTX_0_OBTAIN);
   check_generations(ctx, NONE, NONE);
   assert_prio(ctx, M, 1);
+  change_prio(ctx, A_1, 2);
+  assert_prio(ctx, M, 2);
+  change_prio(ctx, A_1, 3);
+  assert_prio(ctx, M, 3);
+  change_prio(ctx, A_1, 4);
+  assert_prio(ctx, M, 3);
+  change_prio(ctx, A_1, 1);
+  assert_prio(ctx, M, 1);
   release(ctx, MTX_0);
   check_generations(ctx, A_1, NONE);
   assert_prio(ctx, M, 3);
@@ -383,6 +430,7 @@ static void test_inherit(test_context *ctx)
 
 static void test_inherit_fifo_for_equal_priority(test_context *ctx)
 {
+  assert_prio(ctx, M, 3);
   obtain(ctx, MTX_0);
   request(ctx, A_2_0, REQ_MTX_0_OBTAIN);
   request(ctx, A_1, REQ_MTX_0_OBTAIN);
@@ -401,6 +449,82 @@ static void test_inherit_fifo_for_equal_priority(test_context *ctx)
   check_generations(ctx, A_2_1, NONE);
 }
 
+static void test_inherit_nested_vertical(test_context *ctx)
+{
+  assert_prio(ctx, M, 3);
+  obtain(ctx, MTX_0);
+  obtain(ctx, MTX_1);
+  request(ctx, A_1, REQ_MTX_1_OBTAIN);
+  check_generations(ctx, NONE, NONE);
+  assert_prio(ctx, M, 1);
+  release(ctx, MTX_1);
+  check_generations(ctx, A_1, NONE);
+  assert_prio(ctx, M, 3);
+  request(ctx, A_1, REQ_MTX_1_RELEASE);
+  check_generations(ctx, A_1, NONE);
+  release(ctx, MTX_0);
+}
+
+static void test_inherit_nested_vertical_timeout(test_context *ctx)
+{
+  assert_prio(ctx, M, 3);
+  obtain(ctx, MTX_0);
+  obtain(ctx, MTX_1);
+  request(ctx, A_1, REQ_MTX_1_OBTAIN_TIMEOUT);
+  check_generations(ctx, NONE, NONE);
+  assert_prio(ctx, M, 1);
+  wait();
+  check_generations(ctx, A_1, NONE);
+  assert_prio(ctx, M, 3);
+  release(ctx, MTX_1);
+  release(ctx, MTX_0);
+}
+
+static void test_inherit_nested_horizontal(test_context *ctx)
+{
+  assert_prio(ctx, M, 3);
+  obtain(ctx, MTX_0);
+  request(ctx, A_2_0, REQ_MTX_1_OBTAIN);
+  check_generations(ctx, A_2_0, NONE);
+  request(ctx, A_2_0, REQ_MTX_0_OBTAIN);
+  check_generations(ctx, NONE, NONE);
+  assert_prio(ctx, M, 2);
+  request(ctx, A_1, REQ_MTX_1_OBTAIN_TIMEOUT);
+  check_generations(ctx, NONE, NONE);
+  assert_prio(ctx, A_2_0, 1);
+  assert_prio(ctx, M, 1);
+  wait();
+  check_generations(ctx, A_1, NONE);
+  assert_prio(ctx, A_2_0, 2);
+  assert_prio(ctx, M, 2);
+  request(ctx, A_1, REQ_MTX_1_OBTAIN);
+  check_generations(ctx, NONE, NONE);
+  assert_prio(ctx, A_2_0, 1);
+  assert_prio(ctx, M, 1);
+  change_prio(ctx, A_1, 2);
+  assert_prio(ctx, M, 2);
+  change_prio(ctx, A_1, 3);
+  assert_prio(ctx, M, 2);
+  change_prio(ctx, A_2_0, 3);
+  assert_prio(ctx, M, 3);
+  change_prio(ctx, A_2_0, 2);
+  assert_prio(ctx, M, 2);
+  change_prio(ctx, A_1, 1);
+  assert_prio(ctx, M, 1);
+  release(ctx, MTX_0);
+  check_generations(ctx, A_2_0, NONE);
+  assert_prio(ctx, A_2_0, 1);
+  assert_prio(ctx, M, 3);
+  request(ctx, A_2_0, REQ_MTX_0_RELEASE);
+  check_generations(ctx, A_2_0, NONE);
+  assert_prio(ctx, A_2_0, 1);
+  request(ctx, A_2_0, REQ_MTX_1_RELEASE);
+  check_generations(ctx, A_1, A_2_0);
+  assert_prio(ctx, A_2_0, 2);
+  request(ctx, A_1, REQ_MTX_1_RELEASE);
+  check_generations(ctx, A_1, NONE);
+}
+
 static void test_deadlock_two_classic(test_context *ctx)
 {
   obtain(ctx, MTX_0);
@@ -547,6 +671,9 @@ static void Init(rtems_task_argument arg)
   set_up(ctx);
   test_inherit(ctx);
   test_inherit_fifo_for_equal_priority(ctx);
+  test_inherit_nested_vertical(ctx);
+  test_inherit_nested_vertical_timeout(ctx);
+  test_inherit_nested_horizontal(ctx);
   test_deadlock_two_classic(ctx);
   test_deadlock_three_classic(ctx);
   test_deadlock_c11_and_classic(ctx);
diff --git a/testsuites/sptests/spsem03/init.c b/testsuites/sptests/spsem03/init.c
index e64a04d..7f573e5 100644
--- a/testsuites/sptests/spsem03/init.c
+++ b/testsuites/sptests/spsem03/init.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 embedded brains GmbH.  All rights reserved.
+ * Copyright (c) 2014, 2016 embedded brains GmbH.  All rights reserved.
  *
  *  embedded brains GmbH
  *  Dornierstr. 4
@@ -88,20 +88,7 @@ static void obtain_sema(rtems_id id)
 
 static void inversion_task(rtems_task_argument arg)
 {
-  test_context *ctx = &test_instance;
-
-  /*
-   * Here we see that the priority of the high priority task blocked on
-   * semaphore B doesn't propagate to the low priority task owning semaphore A
-   * on which the owner of semaphore B depends.
-   */
-  assert_prio(ctx->low, 3);
-  assert_prio(ctx->mid, 1);
-  assert_prio(ctx->high, 1);
-  assert_prio(ctx->inversion, 2);
-
-  TEST_END();
-  rtems_test_exit(0);
+  assert(0);
 }
 
 static void mid_task(rtems_task_argument arg)
@@ -137,6 +124,19 @@ static void Init(rtems_task_argument arg)
   obtain_sema(ctx->sem_a);
   start_task(ctx->mid, mid_task);
   start_task(ctx->high, high_task);
+
+  /*
+   * Here we see that the priority of the high priority task blocked on
+   * semaphore B propagated to the low priority task owning semaphore A
+   * on which the owner of semaphore B depends.
+   */
+  assert_prio(ctx->low, 1);
+  assert_prio(ctx->mid, 1);
+  assert_prio(ctx->high, 1);
+  assert_prio(ctx->inversion, 2);
+
+  TEST_END();
+  rtems_test_exit(0);
 }
 
 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
diff --git a/testsuites/sptests/spsem03/spsem03.doc b/testsuites/sptests/spsem03/spsem03.doc
index 0310965..a13430e 100644
--- a/testsuites/sptests/spsem03/spsem03.doc
+++ b/testsuites/sptests/spsem03/spsem03.doc
@@ -8,5 +8,5 @@ directives:
 
 concepts:
 
-  - Demonstrate that the priority inheritance protocol doesn't propagate to
-    indirectly referenced semaphore owners.
+  - Demonstrate that the priority inheritance protocol works with indirectly
+    referenced semaphore owners.
-- 
1.8.4.5



More information about the devel mailing list