Index: cpukit/score/include/rtems/score/threaddispatch.h
===================================================================
--- cpukit/score/include/rtems/score/threaddispatch.h	(revision 6157743d67c79d21996ec2cc9742fd8e4e985be7)
+++ cpukit/score/include/rtems/score/threaddispatch.h	(revision 222dc775838c73708054db6283723027c5deb56c)
@@ -194,22 +194,36 @@
 
 /**
- *  @brief Dispatch thread.
- *
- *  This routine is responsible for transferring control of the
- *  processor from the executing thread to the heir thread. Once the
- *  heir is running an attempt is made to dispatch any ASRs.
- *  As part of this process, it is responsible for the following actions:
- *     + saving the context of the executing thread
- *     + restoring the context of the heir thread
- *     + dispatching any signals for the resulting executing thread
-
- *  ALTERNATE ENTRY POINTS:
- *    void _Thread_Enable_dispatch();
- *
- *  - INTERRUPT LATENCY:
- *    + dispatch thread
- *    + no dispatch thread
+ * @brief Performs a thread dispatch if necessary.
+ *
+ * This routine is responsible for transferring control of the processor from
+ * the executing thread to the heir thread.  Once the heir is running an
+ * attempt is made to run the pending post-switch thread actions.
+ *
+ * As part of this process, it is responsible for the following actions
+ *   - update timing information of the executing thread,
+ *   - save the context of the executing thread,
+ *   - invokation of the thread switch user extensions,
+ *   - restore the context of the heir thread, and
+ *   - run of pending post-switch thread actions of the resulting executing
+ *     thread.
+ *
+ * On entry the thread dispatch level must be equal to zero.
  */
 void _Thread_Dispatch( void );
+
+/**
+ * @brief Performs a thread dispatch on the current processor.
+ *
+ * On entry the thread dispatch disable level must be equal to one and
+ * interrupts must be disabled.
+ *
+ * This function assumes that a thread dispatch is necessary.
+ *
+ * @param[in] cpu_self The current processor.
+ * @param[in] level The previous interrupt level.
+ *
+ * @see _Thread_Dispatch().
+ */
+void _Thread_Do_dispatch( Per_CPU_Control *cpu_self, ISR_Level level );
 
 /**
@@ -229,6 +243,31 @@
 RTEMS_INLINE_ROUTINE void _Thread_Enable_dispatch_body( void )
 {
-  if ( _Thread_Dispatch_decrement_disable_level() == 0 )
-    _Thread_Dispatch();
+  Per_CPU_Control *cpu_self;
+  uint32_t         disable_level;
+
+  cpu_self = _Per_CPU_Get();
+
+#if defined( RTEMS_SMP )
+  _Giant_Release( cpu_self );
+#endif
+
+  disable_level = cpu_self->thread_dispatch_disable_level;
+
+  if ( disable_level == 1 ) {
+    ISR_Level level;
+
+    _ISR_Disable_without_giant( level );
+
+    if ( cpu_self->dispatch_necessary ) {
+      _Thread_Do_dispatch( cpu_self, level );
+    } else {
+      cpu_self->thread_dispatch_disable_level = 0;
+      _Profiling_Thread_dispatch_enable( cpu_self, 0 );
+    }
+
+    _ISR_Enable_without_giant( level );
+  } else {
+    cpu_self->thread_dispatch_disable_level = disable_level - 1;
+  }
 }
 
Index: cpukit/score/src/threaddispatch.c
===================================================================
--- cpukit/score/src/threaddispatch.c	(revision 6157743d67c79d21996ec2cc9742fd8e4e985be7)
+++ cpukit/score/src/threaddispatch.c	(revision 222dc775838c73708054db6283723027c5deb56c)
@@ -61,38 +61,13 @@
 }
 
-void _Thread_Dispatch( void )
+void _Thread_Do_dispatch( Per_CPU_Control *cpu_self, ISR_Level level )
 {
-  Per_CPU_Control  *cpu_self;
-  Thread_Control   *executing;
-  ISR_Level         level;
+  Thread_Control *executing;
 
-#if defined( RTEMS_SMP )
-  /*
-   * On SMP the complete context switch must be atomic with respect to one
-   * processor.  See also _Thread_Handler() since _Context_switch() may branch
-   * to this function.
-   */
-  _ISR_Disable_without_giant( level );
-#endif
+  _Assert( cpu_self->thread_dispatch_disable_level == 1 );
 
-  cpu_self = _Per_CPU_Get();
-  _Assert( cpu_self->thread_dispatch_disable_level == 0 );
-  _Profiling_Thread_dispatch_disable( cpu_self, 0 );
-  cpu_self->thread_dispatch_disable_level = 1;
-
-  /*
-   *  Now determine if we need to perform a dispatch on the current CPU.
-   */
   executing = cpu_self->executing;
 
-#if !defined( RTEMS_SMP )
-  _ISR_Disable( level );
-#endif
-
-#if defined( RTEMS_SMP )
-  if ( cpu_self->dispatch_necessary ) {
-#else
-  while ( cpu_self->dispatch_necessary ) {
-#endif
+  do {
     Thread_Control *heir = _Thread_Get_heir_and_make_it_executing( cpu_self );
 
@@ -116,4 +91,9 @@
       heir->cpu_time_budget = rtems_configuration_get_ticks_per_timeslice();
 
+    /*
+     * On SMP the complete context switch must be atomic with respect to one
+     * processor.  See also _Thread_Handler() since _Context_switch() may branch
+     * to this function.
+     */
 #if !defined( RTEMS_SMP )
     _ISR_Enable( level );
@@ -159,5 +139,11 @@
     _ISR_Disable( level );
 #endif
-  }
+  } while (
+#if defined( RTEMS_SMP )
+    false
+#else
+    cpu_self->dispatch_necessary
+#endif
+  );
 
 post_switch:
@@ -170,2 +156,20 @@
   _Thread_Run_post_switch_actions( executing );
 }
+
+void _Thread_Dispatch( void )
+{
+  ISR_Level        level;
+  Per_CPU_Control *cpu_self;
+
+  _ISR_Disable_without_giant( level );
+
+  cpu_self = _Per_CPU_Get();
+
+  if ( cpu_self->dispatch_necessary ) {
+    _Profiling_Thread_dispatch_disable( cpu_self, 0 );
+    cpu_self->thread_dispatch_disable_level = 1;
+    _Thread_Do_dispatch( cpu_self, level );
+  } else {
+    _ISR_Enable_without_giant( level );
+  }
+}
Index: cpukit/score/src/threadhandler.c
===================================================================
--- cpukit/score/src/threadhandler.c	(revision 6157743d67c79d21996ec2cc9742fd8e4e985be7)
+++ cpukit/score/src/threadhandler.c	(revision 222dc775838c73708054db6283723027c5deb56c)
@@ -27,7 +27,7 @@
 void _Thread_Handler( void )
 {
-  Thread_Control *executing = _Thread_Executing;
-  ISR_Level       level;
-
+  Thread_Control  *executing = _Thread_Executing;
+  ISR_Level        level;
+  Per_CPU_Control *cpu_self;
 
   /*
@@ -38,12 +38,17 @@
   _Context_Initialization_at_thread_begin();
 
-  #if !defined(RTEMS_SMP)
-    /*
-     * have to put level into a register for those cpu's that use
-     * inline asm here
-     */
-    level = executing->Start.isr_level;
-    _ISR_Set_level( level );
+  #if defined(RTEMS_SMP)
+    /* On SMP we enter _Thread_Handler() with interrupts disabled */
+    _Assert( _ISR_Get_level() != 0 );
+
+    _Thread_Debug_set_real_processor( executing, _Per_CPU_Get() );
   #endif
+
+  /*
+   * have to put level into a register for those cpu's that use
+   * inline asm here
+   */
+  level = executing->Start.isr_level;
+  _ISR_Set_level( level );
 
   /*
@@ -62,35 +67,22 @@
 
   /*
+   * Do not use the level of the thread control block, since it has a
+   * different format.
+   */
+  _ISR_Disable_without_giant( level );
+
+  /*
    *  At this point, the dispatch disable level BETTER be 1.
    */
-  #if defined(RTEMS_SMP)
-    {
-      /*
-       * On SMP we enter _Thread_Handler() with interrupts disabled and
-       * _Thread_Dispatch() obtained the per-CPU lock for us.  We have to
-       * release it here and set the desired interrupt level of the thread.
-       */
-      Per_CPU_Control *cpu_self = _Per_CPU_Get();
+  cpu_self = _Per_CPU_Get();
+  _Assert( cpu_self->thread_dispatch_disable_level == 1 );
 
-      _Assert( cpu_self->thread_dispatch_disable_level == 1 );
-      _Assert( _ISR_Get_level() != 0 );
-
-      _Thread_Debug_set_real_processor( executing, cpu_self );
-
-      cpu_self->thread_dispatch_disable_level = 0;
-      _Profiling_Thread_dispatch_enable( cpu_self, 0 );
-
-      level = executing->Start.isr_level;
-      _ISR_Set_level( level);
-
-      /*
-       * The thread dispatch level changed from one to zero.  Make sure we lose
-       * no thread dispatch necessary update.
-       */
-      _Thread_Dispatch();
-    }
-  #else
-    _Thread_Enable_dispatch();
-  #endif
+  /*
+   * Make sure we lose no thread dispatch necessary update and execute the
+   * post-switch actions.  As a side-effect change the thread dispatch level
+   * from one to zero.  Do not use _Thread_Enable_dispatch() since there is no
+   * valid thread dispatch necessary indicator in this context.
+   */
+  _Thread_Do_dispatch( cpu_self, level );
 
   /*
Index: testsuites/tmtests/tm26/task1.c
===================================================================
--- testsuites/tmtests/tm26/task1.c	(revision 6157743d67c79d21996ec2cc9742fd8e4e985be7)
+++ testsuites/tmtests/tm26/task1.c	(revision 222dc775838c73708054db6283723027c5deb56c)
@@ -100,4 +100,8 @@
   _Thread_Dispatch_necessary = dispatch_necessary;
 
+  if ( !dispatch_necessary ) {
+    _Thread_Heir = _Thread_Executing;
+  }
+
 #if defined( PREVENT_SMP_ASSERT_FAILURES )
   _ISR_Enable_without_giant( level );
