Index: cpukit/score/include/rtems/score/threadimpl.h
===================================================================
--- cpukit/score/include/rtems/score/threadimpl.h	(revision 3995e6d9c213515f0d636dc2f211bf3c0d997631)
+++ cpukit/score/include/rtems/score/threadimpl.h	(revision dafa5d88435853809040761b79ab9d8f2217281b)
@@ -436,4 +436,35 @@
   Priority_Control  new_priority
 );
+
+/**
+ * @brief Inherit the priority of a thread.
+ *
+ * It changes the current priority of the inheritor thread to the current priority
+ * of the ancestor thread if it is higher than the current priority of the inheritor
+ * thread.  In this case the inheritor thread is appended to its new priority group
+ * in its scheduler instance.
+ *
+ * On SMP configurations, the priority is changed to PRIORITY_PSEUDO_ISR in
+ * case the own schedulers of the inheritor and ancestor thread differ (priority
+ * boosting).
+ *
+ * @param[in] inheritor The thread to inherit the priority.
+ * @param[in] ancestor The thread to bequeath its priority to the inheritor
+ *   thread.
+ */
+#if defined(RTEMS_SMP)
+void _Thread_Inherit_priority(
+  Thread_Control *inheritor,
+  Thread_Control *ancestor
+);
+#else
+RTEMS_INLINE_ROUTINE void _Thread_Inherit_priority(
+  Thread_Control *inheritor,
+  Thread_Control *ancestor
+)
+{
+  _Thread_Raise_priority( inheritor, ancestor->current_priority );
+}
+#endif
 
 /**
Index: cpukit/score/include/rtems/score/threadqimpl.h
===================================================================
--- cpukit/score/include/rtems/score/threadqimpl.h	(revision 3995e6d9c213515f0d636dc2f211bf3c0d997631)
+++ cpukit/score/include/rtems/score/threadqimpl.h	(revision dafa5d88435853809040761b79ab9d8f2217281b)
@@ -523,4 +523,29 @@
 
 /**
+ * @brief Boosts the priority of the thread if threads of another scheduler
+ * instance are enqueued on the thread queue.
+ *
+ * The thread queue must use the priority waiting discipline.
+ *
+ * @param[in] queue The actual thread queue.
+ * @param[in] the_thread The thread to boost the priority if necessary.
+ */
+#if defined(RTEMS_SMP)
+void _Thread_queue_Boost_priority(
+  Thread_queue_Queue *queue,
+  Thread_Control     *the_thread
+);
+#else
+RTEMS_INLINE_ROUTINE void _Thread_queue_Boost_priority(
+  Thread_queue_Queue *queue,
+  Thread_Control     *the_thread
+)
+{
+  (void) queue;
+  (void) the_thread;
+}
+#endif
+
+/**
  * @brief Compare two thread's priority for RBTree Insertion.
  *
Index: cpukit/score/src/coremutexseize.c
===================================================================
--- cpukit/score/src/coremutexseize.c	(revision 3995e6d9c213515f0d636dc2f211bf3c0d997631)
+++ cpukit/score/src/coremutexseize.c	(revision dafa5d88435853809040761b79ab9d8f2217281b)
@@ -76,5 +76,5 @@
 #endif
 
-    _Thread_Raise_priority( holder, executing->current_priority );
+    _Thread_Inherit_priority( holder, executing );
 
 #if !defined(RTEMS_SMP)
Index: cpukit/score/src/coremutexsurrender.c
===================================================================
--- cpukit/score/src/coremutexsurrender.c	(revision 3995e6d9c213515f0d636dc2f211bf3c0d997631)
+++ cpukit/score/src/coremutexsurrender.c	(revision dafa5d88435853809040761b79ab9d8f2217281b)
@@ -210,4 +210,5 @@
           _CORE_mutex_Push_priority( the_mutex, the_thread );
           the_thread->resource_count++;
+          _Thread_queue_Boost_priority( &the_mutex->Wait_queue.Queue, the_thread );
           break;
         case CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING:
Index: cpukit/score/src/mutex.c
===================================================================
--- cpukit/score/src/mutex.c	(revision 3995e6d9c213515f0d636dc2f211bf3c0d997631)
+++ cpukit/score/src/mutex.c	(revision dafa5d88435853809040761b79ab9d8f2217281b)
@@ -113,7 +113,5 @@
 )
 {
-  /* Priority inheritance */
-  _Thread_Raise_priority( owner, executing->current_priority );
-
+  _Thread_Inherit_priority( owner, executing );
   _Thread_queue_Enqueue_critical(
     &mutex->Queue.Queue,
@@ -137,5 +135,6 @@
   if (heads != NULL) {
     const Thread_queue_Operations *operations;
-    Thread_Control *first;
+    Thread_Control                *first;
+    bool                           unblock;
 
     operations = MUTEX_TQ_OPERATIONS;
@@ -143,7 +142,13 @@
 
     mutex->owner = first;
-    _Thread_queue_Extract_critical(
+    unblock = _Thread_queue_Extract_locked(
       &mutex->Queue.Queue,
       operations,
+      first
+    );
+    _Thread_queue_Boost_priority( &mutex->Queue.Queue, first );
+    _Thread_queue_Unblock_critical(
+      unblock,
+      &mutex->Queue.Queue,
       first,
       lock_context
Index: cpukit/score/src/threadchangepriority.c
===================================================================
--- cpukit/score/src/threadchangepriority.c	(revision 3995e6d9c213515f0d636dc2f211bf3c0d997631)
+++ cpukit/score/src/threadchangepriority.c	(revision dafa5d88435853809040761b79ab9d8f2217281b)
@@ -111,4 +111,38 @@
 }
 
+#if defined(RTEMS_SMP)
+static bool _Thread_Inherit_priority_filter(
+  Thread_Control   *inheritor,
+  Priority_Control *new_priority,
+  void             *arg
+)
+{
+  Thread_Control *ancestor = arg;
+
+  if ( _Scheduler_Get_own( inheritor ) == _Scheduler_Get_own( ancestor ) ) {
+    *new_priority = ancestor->current_priority;
+  }
+
+  return _Thread_Priority_less_than(
+    inheritor->current_priority,
+    *new_priority
+  );
+}
+
+void _Thread_Inherit_priority(
+  Thread_Control *inheritor,
+  Thread_Control *ancestor
+)
+{
+  _Thread_Change_priority(
+    inheritor,
+    PRIORITY_PSEUDO_ISR,
+    ancestor,
+    _Thread_Inherit_priority_filter,
+    false
+  );
+}
+#endif
+
 static bool _Thread_Restore_priority_filter(
   Thread_Control   *the_thread,
Index: cpukit/score/src/threadqops.c
===================================================================
--- cpukit/score/src/threadqops.c	(revision 3995e6d9c213515f0d636dc2f211bf3c0d997631)
+++ cpukit/score/src/threadqops.c	(revision dafa5d88435853809040761b79ab9d8f2217281b)
@@ -294,4 +294,26 @@
 }
 
+#if defined(RTEMS_SMP)
+void _Thread_queue_Boost_priority(
+  Thread_queue_Queue *queue,
+  Thread_Control     *the_thread
+)
+{
+  Thread_queue_Heads *heads = queue->heads;
+
+  if (
+    heads != NULL
+      && (
+        !_Chain_Has_only_one_node( &heads->Heads.Fifo )
+          || _RBTree_Is_empty(
+            &_Thread_queue_Priority_queue( heads, the_thread )->Queue
+          )
+      )
+  ) {
+    _Thread_Raise_priority( the_thread, PRIORITY_PSEUDO_ISR );
+  }
+}
+#endif
+
 const Thread_queue_Operations _Thread_queue_Operations_default = {
   .priority_change = _Thread_queue_Do_nothing_priority_change,
Index: doc/user/glossary.texi
===================================================================
--- doc/user/glossary.texi	(revision 3995e6d9c213515f0d636dc2f211bf3c0d997631)
+++ doc/user/glossary.texi	(revision dafa5d88435853809040761b79ab9d8f2217281b)
@@ -505,4 +505,10 @@
 importance of an element in a set of items.  RTEMS uses priority
 to determine which task should execute.
+
+@item priority boosting
+A simple approach to extend the priority inheritance protocol for clustered
+scheduling is @dfn{priority boosting}.  In case a mutex is owned by a task of
+another cluster, then the priority of the owner task is raised to an
+artificially high priority, the pseudo-interrupt priority.
 
 @item priority inheritance
Index: doc/user/sem.t
===================================================================
--- doc/user/sem.t	(revision 3995e6d9c213515f0d636dc2f211bf3c0d997631)
+++ doc/user/sem.t	(revision dafa5d88435853809040761b79ab9d8f2217281b)
@@ -115,4 +115,9 @@
 the resource, the task holding the resource may have its
 priority increased.
+
+On SMP configurations, in case the task holding the resource and the task that
+blocks attempting to obtain the resource are in different scheduler instances,
+the priority of the holder is raised to the pseudo-interrupt priority (priority
+boosting).  The pseudo-interrupt priority is the highest priority.
 
 RTEMS supports priority inheritance for local, binary
Index: doc/user/smp.t
===================================================================
--- doc/user/smp.t	(revision 3995e6d9c213515f0d636dc2f211bf3c0d997631)
+++ doc/user/smp.t	(revision dafa5d88435853809040761b79ab9d8f2217281b)
@@ -165,10 +165,12 @@
 traffic.  It is easy to implement.  The problem is to provide synchronization
 primitives for inter-cluster synchronization (more than one cluster is involved
-in the synchronization process). In RTEMS there are currently three means
+in the synchronization process). In RTEMS there are currently four means
 available
 
 @itemize @bullet
 @item events,
-@item message queues, and
+@item message queues,
+@item semaphores using the @ref{Semaphore Manager Priority Inheritance}
+protocol (priority boosting), and
 @item semaphores using the @ref{Semaphore Manager Multiprocessor Resource
 Sharing Protocol} (MrsP).
Index: testsuites/smptests/smpmutex01/init.c
===================================================================
--- testsuites/smptests/smpmutex01/init.c	(revision 3995e6d9c213515f0d636dc2f211bf3c0d997631)
+++ testsuites/smptests/smpmutex01/init.c	(revision dafa5d88435853809040761b79ab9d8f2217281b)
@@ -27,5 +27,5 @@
 #define PART_COUNT 2
 
-#define TASK_COUNT 8
+#define TASK_COUNT 9
 
 typedef enum {
@@ -44,5 +44,6 @@
   B_5_0,
   B_5_1,
-  H,
+  H_A,
+  H_B,
   NONE
 } task_id;
@@ -112,13 +113,19 @@
 }
 
-static void sync_with_helper(test_context *ctx)
+static void sync_with_helper_by_id(test_context *ctx, task_id id)
 {
   rtems_event_set events;
 
-  send_event(ctx, H, REQ_WAKE_UP_HELPER);
+  send_event(ctx, id, REQ_WAKE_UP_HELPER);
   events = wait_for_events();
   rtems_test_assert(events == REQ_WAKE_UP_MASTER);
 }
 
+static void sync_with_helper(test_context *ctx)
+{
+  sync_with_helper_by_id(ctx, H_A);
+  sync_with_helper_by_id(ctx, H_B);
+}
+
 static void request(test_context *ctx, task_id id, request_id req)
 {
@@ -158,4 +165,22 @@
     rtems_test_assert(ctx->generation[i] == ctx->expected_generation[i]);
   }
+}
+
+static void assert_prio(
+  test_context *ctx,
+  task_id id,
+  rtems_task_priority expected
+)
+{
+  rtems_task_priority actual;
+  rtems_status_code sc;
+
+  sc = rtems_task_set_priority(
+    ctx->tasks[id],
+    RTEMS_CURRENT_PRIORITY,
+    &actual
+  );
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+  rtems_test_assert(expected == actual);
 }
 
@@ -203,5 +228,6 @@
   start_task(ctx, B_5_0, worker, 5, SCHED_B);
   start_task(ctx, B_5_1, worker, 5, SCHED_B);
-  start_task(ctx, H, helper, 6, SCHED_B);
+  start_task(ctx, H_A, helper, 3, SCHED_A);
+  start_task(ctx, H_B, helper, 6, SCHED_B);
 
   sc = rtems_semaphore_create(
@@ -217,6 +243,8 @@
   request(ctx, A_1, REQ_MTX_OBTAIN);
   check_generations(ctx, NONE, NONE);
+  assert_prio(ctx, M, 1);
   release(ctx);
   check_generations(ctx, A_1, NONE);
+  assert_prio(ctx, M, 3);
   request(ctx, A_1, REQ_MTX_RELEASE);
   check_generations(ctx, A_1, NONE);
@@ -227,6 +255,9 @@
   request(ctx, A_2_1, REQ_MTX_OBTAIN);
   check_generations(ctx, NONE, NONE);
+  assert_prio(ctx, M, 1);
   release(ctx);
   check_generations(ctx, A_1, NONE);
+  assert_prio(ctx, M, 3);
+  assert_prio(ctx, A_1, 1);
   request(ctx, A_1, REQ_MTX_RELEASE);
   check_generations(ctx, A_1, A_2_0);
@@ -241,6 +272,8 @@
   request(ctx, B_5_1, REQ_MTX_OBTAIN);
   check_generations(ctx, NONE, NONE);
+  assert_prio(ctx, M, 0);
   release(ctx);
   sync_with_helper(ctx);
+  assert_prio(ctx, M, 3);
   check_generations(ctx, B_4, NONE);
   request(ctx, B_4, REQ_MTX_RELEASE);
@@ -253,5 +286,9 @@
   obtain(ctx);
   request(ctx, A_2_0, REQ_MTX_OBTAIN);
+  check_generations(ctx, NONE, NONE);
+  assert_prio(ctx, M, 2);
   request(ctx, B_5_0, REQ_MTX_OBTAIN);
+  check_generations(ctx, NONE, NONE);
+  assert_prio(ctx, M, 0);
   request(ctx, B_5_1, REQ_MTX_OBTAIN);
   request(ctx, B_4, REQ_MTX_OBTAIN);
@@ -260,17 +297,31 @@
   check_generations(ctx, NONE, NONE);
   release(ctx);
+  sync_with_helper(ctx);
   check_generations(ctx, A_1, NONE);
+  assert_prio(ctx, M, 3);
+  assert_prio(ctx, A_1, 0);
   request(ctx, A_1, REQ_MTX_RELEASE);
   check_generations(ctx, A_1, B_4);
+  assert_prio(ctx, A_1, 1);
+  assert_prio(ctx, B_4, 0);
   request(ctx, B_4, REQ_MTX_RELEASE);
   check_generations(ctx, B_4, A_2_0);
+  assert_prio(ctx, B_4, 4);
+  assert_prio(ctx, A_2_0, 0);
   request(ctx, A_2_0, REQ_MTX_RELEASE);
   check_generations(ctx, A_2_0, B_5_0);
+  assert_prio(ctx, A_2_0, 2);
+  assert_prio(ctx, B_5_0, 0);
   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);
   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);
+  assert_prio(ctx, B_5_1, 5);
 }
 
