Index: cpukit/score/include/rtems/score/schedulersimplesmp.h
===================================================================
--- cpukit/score/include/rtems/score/schedulersimplesmp.h	(revision fc2ad63203475ac93668b522c4364036a97e450d)
+++ cpukit/score/include/rtems/score/schedulersimplesmp.h	(revision aea4a919933d721931f65d81391bf2b13b0f79aa)
@@ -58,5 +58,5 @@
     _Scheduler_simple_smp_Schedule, \
     _Scheduler_simple_smp_Yield, \
-    _Scheduler_simple_smp_Extract, \
+    _Scheduler_simple_smp_Block, \
     _Scheduler_simple_smp_Enqueue_priority_fifo, \
     _Scheduler_default_Allocate, \
@@ -73,4 +73,6 @@
 
 void _Scheduler_simple_smp_Initialize( void );
+
+void _Scheduler_simple_smp_Block( Thread_Control *thread );
 
 void _Scheduler_simple_smp_Enqueue_priority_fifo( Thread_Control *thread );
Index: cpukit/score/include/rtems/score/schedulersmpimpl.h
===================================================================
--- cpukit/score/include/rtems/score/schedulersmpimpl.h	(revision fc2ad63203475ac93668b522c4364036a97e450d)
+++ cpukit/score/include/rtems/score/schedulersmpimpl.h	(revision aea4a919933d721931f65d81391bf2b13b0f79aa)
@@ -84,4 +84,18 @@
 }
 
+static inline Thread_Control *_Scheduler_SMP_Get_lowest_scheduled(
+  Scheduler_SMP_Control *self
+)
+{
+  Thread_Control *lowest_ready = NULL;
+  Chain_Control *scheduled = &self->scheduled;
+
+  if ( !_Chain_Is_empty( scheduled ) ) {
+    lowest_ready = (Thread_Control *) _Chain_Last( scheduled );
+  }
+
+  return lowest_ready;
+}
+
 /** @} */
 
Index: cpukit/score/include/rtems/score/thread.h
===================================================================
--- cpukit/score/include/rtems/score/thread.h	(revision fc2ad63203475ac93668b522c4364036a97e450d)
+++ cpukit/score/include/rtems/score/thread.h	(revision aea4a919933d721931f65d81391bf2b13b0f79aa)
@@ -379,4 +379,19 @@
 
   /**
+   * @brief This field is true if the thread is in the air.
+   *
+   * A thread is in the air if it has an allocated processor (it is an
+   * executing or heir thread on exactly one processor) and it is not a member
+   * of the scheduled chain.  The extract operation on a scheduled thread will
+   * produce threads in the air (see also _Thread_Set_transient()).  The next
+   * enqueue or schedule operation will decide what to do based on this state
+   * indication.  It can either place the thread back on the scheduled chain
+   * and the thread can keep its allocated processor, or it can take the
+   * processor away from the thread and give the processor to another thread of
+   * higher priority.
+   */
+  bool                                  is_in_the_air;
+
+  /**
    * @brief This field is true if the thread is executing.
    *
Index: cpukit/score/src/schedulersimplesmp.c
===================================================================
--- cpukit/score/src/schedulersimplesmp.c	(revision fc2ad63203475ac93668b522c4364036a97e450d)
+++ cpukit/score/src/schedulersimplesmp.c	(revision aea4a919933d721931f65d81391bf2b13b0f79aa)
@@ -35,20 +35,40 @@
 }
 
+static Thread_Control *_Scheduler_simple_smp_Get_highest_ready(
+  Scheduler_SMP_Control *self
+)
+{
+  Thread_Control *highest_ready = NULL;
+  Chain_Control *ready = &self->ready[ 0 ];
+
+  if ( !_Chain_Is_empty( ready ) ) {
+    highest_ready = (Thread_Control *) _Chain_First( ready );
+  }
+
+  return highest_ready;
+}
+
 static void _Scheduler_simple_smp_Move_from_scheduled_to_ready(
-  Chain_Control *ready_chain,
+  Scheduler_SMP_Control *self,
   Thread_Control *scheduled_to_ready
 )
 {
   _Chain_Extract_unprotected( &scheduled_to_ready->Object.Node );
-  _Scheduler_simple_Insert_priority_lifo( ready_chain, scheduled_to_ready );
+  _Scheduler_simple_Insert_priority_lifo(
+    &self->ready[ 0 ],
+    scheduled_to_ready
+  );
 }
 
 static void _Scheduler_simple_smp_Move_from_ready_to_scheduled(
-  Chain_Control *scheduled_chain,
+  Scheduler_SMP_Control *self,
   Thread_Control *ready_to_scheduled
 )
 {
   _Chain_Extract_unprotected( &ready_to_scheduled->Object.Node );
-  _Scheduler_simple_Insert_priority_fifo( scheduled_chain, ready_to_scheduled );
+  _Scheduler_simple_Insert_priority_fifo(
+    &self->scheduled,
+    ready_to_scheduled
+  );
 }
 
@@ -62,4 +82,17 @@
 }
 
+static void _Scheduler_simple_smp_Schedule_highest_ready(
+  Scheduler_SMP_Control *self,
+  Thread_Control *victim
+)
+{
+  Thread_Control *highest_ready =
+    (Thread_Control *) _Chain_First( &self->ready[ 0 ] );
+
+  _Scheduler_SMP_Allocate_processor( highest_ready, victim );
+
+  _Scheduler_simple_smp_Move_from_ready_to_scheduled( self, highest_ready );
+}
+
 static void _Scheduler_simple_smp_Enqueue_ordered(
   Thread_Control *thread,
@@ -69,22 +102,66 @@
   Scheduler_SMP_Control *self = _Scheduler_SMP_Instance();
 
-  /*
-   * The scheduled chain has exactly processor count nodes after
-   * initialization, thus the lowest priority scheduled thread exists.
-   */
-  Thread_Control *lowest_scheduled =
-    (Thread_Control *) _Chain_Last( &self->scheduled );
-
-  if ( ( *order )( &thread->Object.Node, &lowest_scheduled->Object.Node ) ) {
-    _Scheduler_SMP_Allocate_processor( thread, lowest_scheduled );
-
-    _Scheduler_simple_smp_Insert( &self->scheduled, thread, order );
-
-    _Scheduler_simple_smp_Move_from_scheduled_to_ready(
-      &self->ready[ 0 ],
-      lowest_scheduled
-    );
+  if ( thread->is_in_the_air ) {
+    Thread_Control *highest_ready =
+      _Scheduler_simple_smp_Get_highest_ready( self );
+
+    thread->is_in_the_air = false;
+
+    /*
+     * The thread has been extracted from the scheduled chain.  We have to
+     * place it now on the scheduled or ready chain.
+     *
+     * NOTE: Do not exchange parameters to do the negation of the order check.
+     */
+    if (
+      highest_ready != NULL
+        && !( *order )( &thread->Object.Node, &highest_ready->Object.Node )
+    ) {
+      _Scheduler_SMP_Allocate_processor( highest_ready, thread );
+
+      _Scheduler_simple_smp_Insert( &self->ready[ 0 ], thread, order );
+
+      _Scheduler_simple_smp_Move_from_ready_to_scheduled(
+        self,
+        highest_ready
+      );
+    } else {
+      thread->is_scheduled = true;
+
+      _Scheduler_simple_smp_Insert( &self->scheduled, thread, order );
+    }
   } else {
-    _Scheduler_simple_smp_Insert( &self->ready[ 0 ], thread, order );
+    Thread_Control *lowest_scheduled = _Scheduler_SMP_Get_lowest_scheduled( self );
+
+    /*
+     * The scheduled chain is empty if nested interrupts change the priority of
+     * all scheduled threads.  These threads are in the air.
+     */
+    if (
+      lowest_scheduled != NULL
+        && ( *order )( &thread->Object.Node, &lowest_scheduled->Object.Node )
+    ) {
+      _Scheduler_SMP_Allocate_processor( thread, lowest_scheduled );
+
+      _Scheduler_simple_smp_Insert( &self->scheduled, thread, order );
+
+      _Scheduler_simple_smp_Move_from_scheduled_to_ready(
+        self,
+        lowest_scheduled
+      );
+    } else {
+      _Scheduler_simple_smp_Insert( &self->ready[ 0 ], thread, order );
+    }
+  }
+}
+
+void _Scheduler_simple_smp_Block( Thread_Control *thread )
+{
+  _Chain_Extract_unprotected( &thread->Object.Node );
+
+  if ( thread->is_scheduled ) {
+    Scheduler_SMP_Control *self = _Scheduler_SMP_Instance();
+
+    _Scheduler_simple_smp_Schedule_highest_ready( self, thread );
   }
 }
@@ -108,19 +185,7 @@
 void _Scheduler_simple_smp_Extract( Thread_Control *thread )
 {
-  Scheduler_SMP_Control *self = _Scheduler_SMP_Instance();
+  thread->is_in_the_air = true;
 
   _Chain_Extract_unprotected( &thread->Object.Node );
-
-  if ( thread->is_scheduled ) {
-    Thread_Control *highest_ready =
-      (Thread_Control *) _Chain_First( &self->ready[ 0 ] );
-
-    _Scheduler_SMP_Allocate_processor( highest_ready, thread );
-
-    _Scheduler_simple_smp_Move_from_ready_to_scheduled(
-      &self->scheduled,
-      highest_ready
-    );
-  }
 }
 
@@ -139,4 +204,10 @@
 void _Scheduler_simple_smp_Schedule( Thread_Control *thread )
 {
-  ( void ) thread;
-}
+  if ( thread->is_in_the_air ) {
+    Scheduler_SMP_Control *self = _Scheduler_SMP_Instance();
+
+    thread->is_in_the_air = false;
+
+    _Scheduler_simple_smp_Schedule_highest_ready( self, thread );
+  }
+}
Index: cpukit/score/src/threadinitialize.c
===================================================================
--- cpukit/score/src/threadinitialize.c	(revision fc2ad63203475ac93668b522c4364036a97e450d)
+++ cpukit/score/src/threadinitialize.c	(revision aea4a919933d721931f65d81391bf2b13b0f79aa)
@@ -181,4 +181,5 @@
 #if defined(RTEMS_SMP)
   the_thread->is_scheduled            = false;
+  the_thread->is_in_the_air           = false;
   the_thread->is_executing            = false;
 
Index: testsuites/smptests/smpmigration01/smpmigration01.scn
===================================================================
--- testsuites/smptests/smpmigration01/smpmigration01.scn	(revision fc2ad63203475ac93668b522c4364036a97e450d)
+++ testsuites/smptests/smpmigration01/smpmigration01.scn	(revision aea4a919933d721931f65d81391bf2b13b0f79aa)
@@ -1,17 +1,17 @@
 *** TEST SMPMIGRATION 1 ***
 runner 0
-        cpu 0 tokens 411501
-        cpu 0 cycles 9464534
-        cpu 1 tokens 411501
-        cpu 1 cycles 9464802
+        cpu 0 tokens 530399
+        cpu 0 cycles 10077490
+        cpu 1 tokens 530399
+        cpu 1 cycles 10071429
 runner 1
-        cpu 0 tokens 411500
-        cpu 0 cycles 41936630
-        cpu 1 tokens 411501
-        cpu 1 cycles 42009945
+        cpu 0 tokens 530399
+        cpu 0 cycles 5978212
+        cpu 1 tokens 530399
+        cpu 1 cycles 7951897
 runner 2
-        cpu 0 tokens 411501
-        cpu 0 cycles 6583983
-        cpu 1 tokens 411500
-        cpu 1 cycles 6583701
+        cpu 0 tokens 530399
+        cpu 0 cycles 10070929
+        cpu 1 tokens 530398
+        cpu 1 cycles 10106437
 *** END OF TEST SMPMIGRATION 1 ***
