[PATCH 6/6] score: Need for help indicator for scheduler ops

Sebastian Huber sebastian.huber at embedded-brains.de
Fri Jun 13 14:37:23 UTC 2014


Return the displaced thread for the following scheduler operations

- unblock,
- change priority, and
- yield.

A displaced thread is a thread that encounters a scheduler state change
from scheduled to ready.  Such a displaced thread can ask threads which
depend on resources owned by the displaced thread for help.

In case the unblock operation returns no displaced thread, then this
indicates that the unblocked thread is now in the ready state and has no
processor allocated.  Such a thread can ask now also for help.
---
 cpukit/score/include/rtems/score/scheduler.h       |   27 ++-
 cpukit/score/include/rtems/score/schedulercbs.h    |    2 +-
 cpukit/score/include/rtems/score/scheduleredf.h    |    6 +-
 cpukit/score/include/rtems/score/schedulerimpl.h   |   33 ++
 .../score/include/rtems/score/schedulerpriority.h  |    6 +-
 .../rtems/score/schedulerpriorityaffinitysmp.h     |    4 +-
 .../include/rtems/score/schedulerprioritysmp.h     |    6 +-
 cpukit/score/include/rtems/score/schedulersimple.h |    6 +-
 .../score/include/rtems/score/schedulersimplesmp.h |    6 +-
 .../score/include/rtems/score/schedulersmpimpl.h   |   46 ++-
 cpukit/score/src/schedulercbsunblock.c             |    4 +-
 cpukit/score/src/scheduleredfchangepriority.c      |    4 +-
 cpukit/score/src/scheduleredfunblock.c             |    4 +-
 cpukit/score/src/scheduleredfyield.c               |    4 +-
 cpukit/score/src/schedulerpriorityaffinitysmp.c    |   39 ++-
 cpukit/score/src/schedulerprioritychangepriority.c |    4 +-
 cpukit/score/src/schedulerprioritysmp.c            |   34 +-
 cpukit/score/src/schedulerpriorityunblock.c        |    4 +-
 cpukit/score/src/schedulerpriorityyield.c          |    4 +-
 cpukit/score/src/schedulersimplechangepriority.c   |    4 +-
 cpukit/score/src/schedulersimplesmp.c              |   34 +-
 cpukit/score/src/schedulersimpleunblock.c          |    4 +-
 cpukit/score/src/schedulersimpleyield.c            |    4 +-
 testsuites/smptests/smpscheduler03/init.c          |  385 +++++++++++++++++++-
 24 files changed, 562 insertions(+), 112 deletions(-)

diff --git a/cpukit/score/include/rtems/score/scheduler.h b/cpukit/score/include/rtems/score/scheduler.h
index d9d21d3..d2436ff 100644
--- a/cpukit/score/include/rtems/score/scheduler.h
+++ b/cpukit/score/include/rtems/score/scheduler.h
@@ -44,6 +44,16 @@ typedef struct Scheduler_Control Scheduler_Control;
 
 typedef struct Scheduler_Node Scheduler_Node;
 
+#if defined(RTEMS_SMP)
+  typedef Thread_Control * Scheduler_Void_or_thread;
+
+  #define SCHEDULER_RETURN_VOID_OR_NULL return NULL
+#else
+  typedef void Scheduler_Void_or_thread;
+
+  #define SCHEDULER_RETURN_VOID_OR_NULL return
+#endif
+
 /**
  * @brief The scheduler operations.
  */
@@ -55,16 +65,25 @@ typedef struct {
   void ( *schedule )( const Scheduler_Control *, Thread_Control *);
 
   /** @see _Scheduler_Yield() */
-  void ( *yield )( const Scheduler_Control *, Thread_Control *);
+  Scheduler_Void_or_thread ( *yield )(
+    const Scheduler_Control *,
+    Thread_Control *
+  );
 
   /** @see _Scheduler_Block() */
-  void ( *block )( const Scheduler_Control *, Thread_Control * );
+  void ( *block )(
+    const Scheduler_Control *,
+    Thread_Control *
+  );
 
   /** @see _Scheduler_Unblock() */
-  void ( *unblock )( const Scheduler_Control *, Thread_Control * );
+  Scheduler_Void_or_thread ( *unblock )(
+    const Scheduler_Control *,
+    Thread_Control *
+  );
 
   /** @see _Scheduler_Change_priority() */
-  void ( *change_priority )(
+  Scheduler_Void_or_thread ( *change_priority )(
     const Scheduler_Control *,
     Thread_Control *,
     Priority_Control,
diff --git a/cpukit/score/include/rtems/score/schedulercbs.h b/cpukit/score/include/rtems/score/schedulercbs.h
index 473d6fe..50dfa06 100644
--- a/cpukit/score/include/rtems/score/schedulercbs.h
+++ b/cpukit/score/include/rtems/score/schedulercbs.h
@@ -152,7 +152,7 @@ extern Scheduler_CBS_Server _Scheduler_CBS_Server_list[];
  *
  *  @note This has to be asessed as missed deadline of the current job.
  */
-void _Scheduler_CBS_Unblock(
+Scheduler_Void_or_thread _Scheduler_CBS_Unblock(
   const Scheduler_Control *scheduler,
   Thread_Control          *the_thread
 );
diff --git a/cpukit/score/include/rtems/score/scheduleredf.h b/cpukit/score/include/rtems/score/scheduleredf.h
index 7a20b5b..c28a13b 100644
--- a/cpukit/score/include/rtems/score/scheduleredf.h
+++ b/cpukit/score/include/rtems/score/scheduleredf.h
@@ -176,12 +176,12 @@ void _Scheduler_EDF_Update_priority(
  *
  *  @param[in] the_thread will be unblocked.
  */
-void _Scheduler_EDF_Unblock(
+Scheduler_Void_or_thread _Scheduler_EDF_Unblock(
   const Scheduler_Control *scheduler,
   Thread_Control          *the_thread
 );
 
-void _Scheduler_EDF_Change_priority(
+Scheduler_Void_or_thread _Scheduler_EDF_Change_priority(
   const Scheduler_Control *scheduler,
   Thread_Control          *the_thread,
   Priority_Control         new_priority,
@@ -203,7 +203,7 @@ void _Scheduler_EDF_Change_priority(
  *
  *  @param[in,out] thread The yielding thread.
  */
-void _Scheduler_EDF_Yield(
+Scheduler_Void_or_thread _Scheduler_EDF_Yield(
   const Scheduler_Control *scheduler,
   Thread_Control          *the_thread
 );
diff --git a/cpukit/score/include/rtems/score/schedulerimpl.h b/cpukit/score/include/rtems/score/schedulerimpl.h
index f3284eb..0f7150f 100644
--- a/cpukit/score/include/rtems/score/schedulerimpl.h
+++ b/cpukit/score/include/rtems/score/schedulerimpl.h
@@ -107,6 +107,11 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Schedule( Thread_Control *the_thread )
   ( *scheduler->Operations.schedule )( scheduler, the_thread );
 }
 
+RTEMS_INLINE_ROUTINE void _Scheduler_Ask_for_help( Thread_Control *needs_help )
+{
+  (void) needs_help;
+}
+
 /**
  * @brief Scheduler yield with a particular thread.
  *
@@ -118,8 +123,14 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Schedule( Thread_Control *the_thread )
 RTEMS_INLINE_ROUTINE void _Scheduler_Yield( Thread_Control *the_thread )
 {
   const Scheduler_Control *scheduler = _Scheduler_Get( the_thread );
+  Thread_Control *needs_help;
 
+#if defined(RTEMS_SMP)
+  needs_help =
+#endif
   ( *scheduler->Operations.yield )( scheduler, the_thread );
+
+  _Scheduler_Ask_for_help( needs_help );
 }
 
 /**
@@ -152,8 +163,24 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Block( Thread_Control *the_thread )
 RTEMS_INLINE_ROUTINE void _Scheduler_Unblock( Thread_Control *the_thread )
 {
   const Scheduler_Control *scheduler = _Scheduler_Get( the_thread );
+#if defined(RTEMS_SMP)
+  Thread_Control *displaced;
 
+  displaced =
+#endif
   ( *scheduler->Operations.unblock )( scheduler, the_thread );
+
+#if defined(RTEMS_SMP)
+  if ( displaced != NULL ) {
+    _Scheduler_Ask_for_help( displaced );
+  } else {
+    /*
+     * There is no displaced thread due to this operation, thus the thread is
+     * now in the ready state and has no processor allocated.
+     */
+    _Scheduler_Ask_for_help( the_thread );
+  }
+#endif
 }
 
 /**
@@ -176,13 +203,19 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Change_priority(
 )
 {
   const Scheduler_Control *scheduler = _Scheduler_Get( the_thread );
+  Thread_Control *displaced;
 
+#if defined(RTEMS_SMP)
+  displaced =
+#endif
   ( *scheduler->Operations.change_priority )(
     scheduler,
     the_thread,
     new_priority,
     prepend_it
   );
+
+  _Scheduler_Ask_for_help( displaced );
 }
 
 /**
diff --git a/cpukit/score/include/rtems/score/schedulerpriority.h b/cpukit/score/include/rtems/score/schedulerpriority.h
index 2e4f3ab..5ac9877 100644
--- a/cpukit/score/include/rtems/score/schedulerpriority.h
+++ b/cpukit/score/include/rtems/score/schedulerpriority.h
@@ -157,12 +157,12 @@ void _Scheduler_priority_Update_priority(
  *
  *  @param[in] the_thread will be unblocked
  */
-void _Scheduler_priority_Unblock(
+Scheduler_Void_or_thread _Scheduler_priority_Unblock(
   const Scheduler_Control *scheduler,
   Thread_Control          *the_thread
 );
 
-void _Scheduler_priority_Change_priority(
+Scheduler_Void_or_thread _Scheduler_priority_Change_priority(
   const Scheduler_Control *scheduler,
   Thread_Control          *the_thread,
   Priority_Control         new_priority,
@@ -188,7 +188,7 @@ void _Scheduler_priority_Change_priority(
  *
  *  @param[in,out] thread The yielding thread.
  */
-void _Scheduler_priority_Yield(
+Scheduler_Void_or_thread _Scheduler_priority_Yield(
   const Scheduler_Control *scheduler,
   Thread_Control          *the_thread
 );
diff --git a/cpukit/score/include/rtems/score/schedulerpriorityaffinitysmp.h b/cpukit/score/include/rtems/score/schedulerpriorityaffinitysmp.h
index 831d1d4..3a23510 100644
--- a/cpukit/score/include/rtems/score/schedulerpriorityaffinitysmp.h
+++ b/cpukit/score/include/rtems/score/schedulerpriorityaffinitysmp.h
@@ -101,7 +101,7 @@ void _Scheduler_priority_affinity_SMP_Block(
  * @param[in] scheduler is the scheduler instance information
  * @param[in] thread is the thread to unblock
  */
-void _Scheduler_priority_affinity_SMP_Unblock(
+Thread_Control *_Scheduler_priority_affinity_SMP_Unblock(
   const Scheduler_Control *scheduler,
   Thread_Control          *thread
 );
@@ -132,7 +132,7 @@ bool _Scheduler_priority_affinity_SMP_Get_affinity(
  * @param[in] new_priority The new priority for the thread.
  * @param[in] prepend_it Append or prepend the thread to its priority FIFO.
  */
-void _Scheduler_priority_affinity_SMP_Change_priority(
+Thread_Control *_Scheduler_priority_affinity_SMP_Change_priority(
   const Scheduler_Control *scheduler,
   Thread_Control          *the_thread,
   Priority_Control         new_priority,
diff --git a/cpukit/score/include/rtems/score/schedulerprioritysmp.h b/cpukit/score/include/rtems/score/schedulerprioritysmp.h
index cbb8a58..9c439cb 100644
--- a/cpukit/score/include/rtems/score/schedulerprioritysmp.h
+++ b/cpukit/score/include/rtems/score/schedulerprioritysmp.h
@@ -107,12 +107,12 @@ void _Scheduler_priority_SMP_Block(
   Thread_Control *thread
 );
 
-void _Scheduler_priority_SMP_Unblock(
+Thread_Control *_Scheduler_priority_SMP_Unblock(
   const Scheduler_Control *scheduler,
   Thread_Control *thread
 );
 
-void _Scheduler_priority_SMP_Change_priority(
+Thread_Control *_Scheduler_priority_SMP_Change_priority(
   const Scheduler_Control *scheduler,
   Thread_Control          *the_thread,
   Priority_Control         new_priority,
@@ -125,7 +125,7 @@ void _Scheduler_priority_SMP_Update_priority(
   Priority_Control new_priority
 );
 
-void _Scheduler_priority_SMP_Yield(
+Thread_Control *_Scheduler_priority_SMP_Yield(
   const Scheduler_Control *scheduler,
   Thread_Control *thread
 );
diff --git a/cpukit/score/include/rtems/score/schedulersimple.h b/cpukit/score/include/rtems/score/schedulersimple.h
index 68ed527..d5588ef 100644
--- a/cpukit/score/include/rtems/score/schedulersimple.h
+++ b/cpukit/score/include/rtems/score/schedulersimple.h
@@ -100,7 +100,7 @@ void _Scheduler_simple_Schedule(
  *
  *  @param[in,out] thread The yielding thread.
  */
-void _Scheduler_simple_Yield(
+Scheduler_Void_or_thread _Scheduler_simple_Yield(
   const Scheduler_Control *scheduler,
   Thread_Control          *the_thread
 );
@@ -129,12 +129,12 @@ void _Scheduler_simple_Block(
  *
  *  @param[in] the_thread is the thread that is to be unblocked
  */
-void _Scheduler_simple_Unblock(
+Scheduler_Void_or_thread _Scheduler_simple_Unblock(
   const Scheduler_Control *scheduler,
   Thread_Control          *the_thread
 );
 
-void _Scheduler_simple_Change_priority(
+Scheduler_Void_or_thread _Scheduler_simple_Change_priority(
   const Scheduler_Control *scheduler,
   Thread_Control          *the_thread,
   Priority_Control         new_priority,
diff --git a/cpukit/score/include/rtems/score/schedulersimplesmp.h b/cpukit/score/include/rtems/score/schedulersimplesmp.h
index d12c730..156daba 100644
--- a/cpukit/score/include/rtems/score/schedulersimplesmp.h
+++ b/cpukit/score/include/rtems/score/schedulersimplesmp.h
@@ -88,12 +88,12 @@ void _Scheduler_simple_SMP_Block(
   Thread_Control *thread
 );
 
-void _Scheduler_simple_SMP_Unblock(
+Thread_Control *_Scheduler_simple_SMP_Unblock(
   const Scheduler_Control *scheduler,
   Thread_Control *thread
 );
 
-void _Scheduler_simple_SMP_Change_priority(
+Thread_Control *_Scheduler_simple_SMP_Change_priority(
   const Scheduler_Control *scheduler,
   Thread_Control          *the_thread,
   Priority_Control         new_priority,
@@ -106,7 +106,7 @@ void _Scheduler_simple_SMP_Update_priority(
   Priority_Control         new_priority
 );
 
-void _Scheduler_simple_SMP_Yield(
+Thread_Control *_Scheduler_simple_SMP_Yield(
   const Scheduler_Control *scheduler,
   Thread_Control *thread
 );
diff --git a/cpukit/score/include/rtems/score/schedulersmpimpl.h b/cpukit/score/include/rtems/score/schedulersmpimpl.h
index eaf7e32..093585c 100644
--- a/cpukit/score/include/rtems/score/schedulersmpimpl.h
+++ b/cpukit/score/include/rtems/score/schedulersmpimpl.h
@@ -306,7 +306,7 @@ typedef void ( *Scheduler_SMP_Update )(
   Priority_Control   new_priority
 );
 
-typedef void ( *Scheduler_SMP_Enqueue )(
+typedef Thread_Control *( *Scheduler_SMP_Enqueue )(
   Scheduler_Context *context,
   Scheduler_Node    *node_to_enqueue
 );
@@ -521,7 +521,7 @@ static inline Scheduler_Node *_Scheduler_SMP_Get_lowest_scheduled(
  * @param[in] allocate_processor Function to allocate a processor to a node
  *   based on the rules of the scheduler.
  */
-static inline void _Scheduler_SMP_Enqueue_ordered(
+static inline Thread_Control *_Scheduler_SMP_Enqueue_ordered(
   Scheduler_Context                  *context,
   Scheduler_Node                     *node,
   Chain_Node_order                    order,
@@ -534,6 +534,7 @@ static inline void _Scheduler_SMP_Enqueue_ordered(
 {
   Scheduler_Node *lowest_scheduled =
     ( *get_lowest_scheduled )( context, node, order );
+  Thread_Control *displaced;
 
   if ( ( *order )( &node->Node, &lowest_scheduled->Node ) ) {
     _Scheduler_SMP_Node_change_state(
@@ -543,9 +544,15 @@ static inline void _Scheduler_SMP_Enqueue_ordered(
     ( *allocate_processor )( context, node, lowest_scheduled );
     ( *insert_scheduled )( context, node );
     ( *move_from_scheduled_to_ready )( context, lowest_scheduled );
+
+    displaced = _Scheduler_Node_get_user( lowest_scheduled );
   } else {
     ( *insert_ready )( context, node );
+
+    displaced = NULL;
   }
+
+  return displaced;
 }
 
 /**
@@ -565,7 +572,7 @@ static inline void _Scheduler_SMP_Enqueue_ordered(
  * @param[in] allocate_processor Function to allocate a processor to a node
  *   based on the rules of the scheduler.
  */
-static inline void _Scheduler_SMP_Enqueue_scheduled_ordered(
+static inline Thread_Control *_Scheduler_SMP_Enqueue_scheduled_ordered(
   Scheduler_Context                *context,
   Scheduler_Node                   *node,
   Chain_Node_order                  order,
@@ -577,6 +584,7 @@ static inline void _Scheduler_SMP_Enqueue_scheduled_ordered(
 )
 {
   Scheduler_Node *highest_ready = ( *get_highest_ready )( context, node );
+  Thread_Control *displaced;
 
   _Assert( highest_ready != NULL );
 
@@ -586,6 +594,8 @@ static inline void _Scheduler_SMP_Enqueue_scheduled_ordered(
    */
   if ( ( *order )( &node->Node, &highest_ready->Node ) ) {
     ( *insert_scheduled )( context, node );
+
+    displaced = NULL;
   } else {
     _Scheduler_SMP_Node_change_state(
       _Scheduler_SMP_Node_downcast( node ),
@@ -594,7 +604,11 @@ static inline void _Scheduler_SMP_Enqueue_scheduled_ordered(
     ( *allocate_processor) ( context, highest_ready, node );
     ( *insert_ready )( context, node );
     ( *move_from_ready_to_scheduled )( context, highest_ready );
+
+    displaced = _Scheduler_Node_get_user( node );
   }
+
+  return displaced;
 }
 
 static inline void _Scheduler_SMP_Extract_from_scheduled(
@@ -658,7 +672,7 @@ static inline void _Scheduler_SMP_Block(
   }
 }
 
-static inline void _Scheduler_SMP_Unblock(
+static inline Thread_Control *_Scheduler_SMP_Unblock(
   Scheduler_Context     *context,
   Thread_Control        *thread,
   Scheduler_SMP_Enqueue  enqueue_fifo
@@ -668,10 +682,10 @@ static inline void _Scheduler_SMP_Unblock(
 
   _Scheduler_SMP_Node_change_state( node, SCHEDULER_SMP_NODE_READY );
 
-  ( *enqueue_fifo )( context, &node->Base );
+  return ( *enqueue_fifo )( context, &node->Base );
 }
 
-static inline void _Scheduler_SMP_Change_priority(
+static inline Thread_Control *_Scheduler_SMP_Change_priority(
   Scheduler_Context     *context,
   Thread_Control        *thread,
   Priority_Control       new_priority,
@@ -685,6 +699,7 @@ static inline void _Scheduler_SMP_Change_priority(
 )
 {
   Scheduler_SMP_Node *node = _Scheduler_SMP_Node_get( thread );
+  Thread_Control *displaced;
 
   if ( node->state == SCHEDULER_SMP_NODE_SCHEDULED ) {
     _Scheduler_SMP_Extract_from_scheduled( &node->Base );
@@ -692,9 +707,9 @@ static inline void _Scheduler_SMP_Change_priority(
     ( *update )( context, &node->Base, new_priority );
 
     if ( prepend_it ) {
-      ( *enqueue_scheduled_lifo )( context, &node->Base );
+      displaced = ( *enqueue_scheduled_lifo )( context, &node->Base );
     } else {
-      ( *enqueue_scheduled_fifo )( context, &node->Base );
+      displaced = ( *enqueue_scheduled_fifo )( context, &node->Base );
     }
   } else {
     ( *extract_from_ready )( context, &node->Base );
@@ -702,14 +717,16 @@ static inline void _Scheduler_SMP_Change_priority(
     ( *update )( context, &node->Base, new_priority );
 
     if ( prepend_it ) {
-      ( *enqueue_lifo )( context, &node->Base );
+      displaced = ( *enqueue_lifo )( context, &node->Base );
     } else {
-      ( *enqueue_fifo )( context, &node->Base );
+      displaced = ( *enqueue_fifo )( context, &node->Base );
     }
   }
+
+  return displaced;
 }
 
-static inline void _Scheduler_SMP_Yield(
+static inline Thread_Control *_Scheduler_SMP_Yield(
   Scheduler_Context     *context,
   Thread_Control        *thread,
   Scheduler_SMP_Extract  extract_from_ready,
@@ -718,16 +735,19 @@ static inline void _Scheduler_SMP_Yield(
 )
 {
   Scheduler_SMP_Node *node = _Scheduler_SMP_Node_get( thread );
+  Thread_Control *displaced;
 
   if ( node->state == SCHEDULER_SMP_NODE_SCHEDULED ) {
     _Scheduler_SMP_Extract_from_scheduled( &node->Base );
 
-    ( *enqueue_scheduled_fifo )( context, &node->Base );
+    displaced = ( *enqueue_scheduled_fifo )( context, &node->Base );
   } else {
     ( *extract_from_ready )( context, &node->Base );
 
-    ( *enqueue_fifo )( context, &node->Base );
+    displaced = ( *enqueue_fifo )( context, &node->Base );
   }
+
+  return displaced;
 }
 
 static inline void _Scheduler_SMP_Insert_scheduled_lifo(
diff --git a/cpukit/score/src/schedulercbsunblock.c b/cpukit/score/src/schedulercbsunblock.c
index 1a374f6..91feca0 100644
--- a/cpukit/score/src/schedulercbsunblock.c
+++ b/cpukit/score/src/schedulercbsunblock.c
@@ -25,7 +25,7 @@
 #include <rtems/score/threadimpl.h>
 #include <rtems/score/watchdogimpl.h>
 
-void _Scheduler_CBS_Unblock(
+Scheduler_Void_or_thread _Scheduler_CBS_Unblock(
   const Scheduler_Control *scheduler,
   Thread_Control          *the_thread
 )
@@ -84,4 +84,6 @@ void _Scheduler_CBS_Unblock(
          the_thread->current_priority == 0 )
       _Thread_Dispatch_necessary = true;
   }
+
+  SCHEDULER_RETURN_VOID_OR_NULL;
 }
diff --git a/cpukit/score/src/scheduleredfchangepriority.c b/cpukit/score/src/scheduleredfchangepriority.c
index dfcfef5..1ea48dd 100644
--- a/cpukit/score/src/scheduleredfchangepriority.c
+++ b/cpukit/score/src/scheduleredfchangepriority.c
@@ -20,7 +20,7 @@
 
 #include <rtems/score/scheduleredfimpl.h>
 
-void _Scheduler_EDF_Change_priority(
+Scheduler_Void_or_thread _Scheduler_EDF_Change_priority(
   const Scheduler_Control *scheduler,
   Thread_Control          *the_thread,
   Priority_Control         new_priority,
@@ -33,4 +33,6 @@ void _Scheduler_EDF_Change_priority(
 
   _RBTree_Extract( &context->Ready, &node->Node );
   _RBTree_Insert( &context->Ready, &node->Node );
+
+  SCHEDULER_RETURN_VOID_OR_NULL;
 }
diff --git a/cpukit/score/src/scheduleredfunblock.c b/cpukit/score/src/scheduleredfunblock.c
index 30fa4f0..469655e 100644
--- a/cpukit/score/src/scheduleredfunblock.c
+++ b/cpukit/score/src/scheduleredfunblock.c
@@ -22,7 +22,7 @@
 #include <rtems/score/schedulerimpl.h>
 #include <rtems/score/thread.h>
 
-void _Scheduler_EDF_Unblock(
+Scheduler_Void_or_thread _Scheduler_EDF_Unblock(
   const Scheduler_Control *scheduler,
   Thread_Control          *the_thread
 )
@@ -51,4 +51,6 @@ void _Scheduler_EDF_Unblock(
          the_thread->current_priority == 0 )
       _Thread_Dispatch_necessary = true;
   }
+
+  SCHEDULER_RETURN_VOID_OR_NULL;
 }
diff --git a/cpukit/score/src/scheduleredfyield.c b/cpukit/score/src/scheduleredfyield.c
index d43448b..f6a0f01 100644
--- a/cpukit/score/src/scheduleredfyield.c
+++ b/cpukit/score/src/scheduleredfyield.c
@@ -21,7 +21,7 @@
 
 #include <rtems/score/scheduleredfimpl.h>
 
-void _Scheduler_EDF_Yield(
+Scheduler_Void_or_thread _Scheduler_EDF_Yield(
   const Scheduler_Control *scheduler,
   Thread_Control          *the_thread
 )
@@ -38,4 +38,6 @@ void _Scheduler_EDF_Yield(
   _RBTree_Insert( &context->Ready, &node->Node );
 
   _Scheduler_EDF_Schedule_body( scheduler, the_thread, false );
+
+  SCHEDULER_RETURN_VOID_OR_NULL;
 }
diff --git a/cpukit/score/src/schedulerpriorityaffinitysmp.c b/cpukit/score/src/schedulerpriorityaffinitysmp.c
index f1dcacd..02b1963 100644
--- a/cpukit/score/src/schedulerpriorityaffinitysmp.c
+++ b/cpukit/score/src/schedulerpriorityaffinitysmp.c
@@ -294,12 +294,12 @@ static Scheduler_Node * _Scheduler_priority_affinity_SMP_Get_lowest_scheduled(
  * _Scheduler_priority_affinity_SMP_Get_lowest_scheduled into
  * _Scheduler_SMP_Enqueue_ordered.
  */
-static void _Scheduler_priority_affinity_SMP_Enqueue_fifo(
+static Thread_Control *_Scheduler_priority_affinity_SMP_Enqueue_fifo(
   Scheduler_Context *context,
   Scheduler_Node    *node
 )
 {
-  _Scheduler_SMP_Enqueue_ordered(
+  return _Scheduler_SMP_Enqueue_ordered(
     context,
     node,
     _Scheduler_priority_affinity_SMP_Insert_priority_fifo_order,
@@ -379,14 +379,15 @@ static void _Scheduler_priority_affinity_SMP_Check_for_migrations(
 /*
  * This is the public scheduler specific Unblock operation.
  */
-void _Scheduler_priority_affinity_SMP_Unblock(
+Thread_Control *_Scheduler_priority_affinity_SMP_Unblock(
   const Scheduler_Control *scheduler,
   Thread_Control *thread
 )
 {
   Scheduler_Context *context = _Scheduler_Get_context( scheduler );
+  Thread_Control    *needs_help;
 
-  _Scheduler_SMP_Unblock(
+  needs_help = _Scheduler_SMP_Unblock(
     context,
     thread,
     _Scheduler_priority_affinity_SMP_Enqueue_fifo
@@ -396,13 +397,15 @@ void _Scheduler_priority_affinity_SMP_Unblock(
    * Perform any thread migrations that are needed due to these changes.
    */
   _Scheduler_priority_affinity_SMP_Check_for_migrations( context );
+
+  return needs_help;
 }
 
 /*
  *  This is unique to this scheduler because it passes scheduler specific
  *  get_lowest_scheduled helper to _Scheduler_SMP_Enqueue_ordered.
  */
-static void _Scheduler_priority_affinity_SMP_Enqueue_ordered(
+static Thread_Control *_Scheduler_priority_affinity_SMP_Enqueue_ordered(
   Scheduler_Context     *context,
   Scheduler_Node        *node,
   Chain_Node_order       order,
@@ -410,7 +413,7 @@ static void _Scheduler_priority_affinity_SMP_Enqueue_ordered(
   Scheduler_SMP_Insert   insert_scheduled
 )
 {
-  _Scheduler_SMP_Enqueue_ordered(
+  return _Scheduler_SMP_Enqueue_ordered(
     context,
     node,
     order,
@@ -427,12 +430,12 @@ static void _Scheduler_priority_affinity_SMP_Enqueue_ordered(
  *  to _Scheduler_priority_affinity_SMP_Enqueue_ordered() which
  *  invokes a scheduler unique get_lowest_scheduled helper.
  */
-static void _Scheduler_priority_affinity_SMP_Enqueue_lifo(
+static Thread_Control *_Scheduler_priority_affinity_SMP_Enqueue_lifo(
   Scheduler_Context *context,
   Scheduler_Node    *node
 )
 {
-  _Scheduler_priority_affinity_SMP_Enqueue_ordered(
+  return _Scheduler_priority_affinity_SMP_Enqueue_ordered(
     context,
     node,
     _Scheduler_priority_affinity_SMP_Insert_priority_lifo_order,
@@ -446,7 +449,8 @@ static void _Scheduler_priority_affinity_SMP_Enqueue_lifo(
  * invoke _Scheduler_SMP_Enqueue_scheduled_ordered() with
  * this scheduler's get_highest_ready() helper.
  */
-static void _Scheduler_priority_affinity_SMP_Enqueue_scheduled_ordered(
+static Thread_Control *
+_Scheduler_priority_affinity_SMP_Enqueue_scheduled_ordered(
   Scheduler_Context    *context,
   Scheduler_Node       *node,
   Chain_Node_order      order,
@@ -454,7 +458,7 @@ static void _Scheduler_priority_affinity_SMP_Enqueue_scheduled_ordered(
   Scheduler_SMP_Insert  insert_scheduled
 )
 {
-  _Scheduler_SMP_Enqueue_scheduled_ordered(
+  return _Scheduler_SMP_Enqueue_scheduled_ordered(
     context,
     node,
     order,
@@ -471,12 +475,12 @@ static void _Scheduler_priority_affinity_SMP_Enqueue_scheduled_ordered(
  *  to _Scheduler_priority_affinity_SMP_Enqueue_scheduled__ordered() which
  *  invokes a scheduler unique get_lowest_scheduled helper.
  */
-static void _Scheduler_priority_affinity_SMP_Enqueue_scheduled_lifo(
+static Thread_Control *_Scheduler_priority_affinity_SMP_Enqueue_scheduled_lifo(
   Scheduler_Context *context,
   Scheduler_Node    *node
 )
 {
-  _Scheduler_priority_affinity_SMP_Enqueue_scheduled_ordered(
+  return _Scheduler_priority_affinity_SMP_Enqueue_scheduled_ordered(
     context,
     node,
     _Scheduler_SMP_Insert_priority_lifo_order,
@@ -490,12 +494,12 @@ static void _Scheduler_priority_affinity_SMP_Enqueue_scheduled_lifo(
  *  to _Scheduler_priority_affinity_SMP_Enqueue_scheduled__ordered() which
  *  invokes a scheduler unique get_lowest_scheduled helper.
  */
-static void _Scheduler_priority_affinity_SMP_Enqueue_scheduled_fifo(
+static Thread_Control *_Scheduler_priority_affinity_SMP_Enqueue_scheduled_fifo(
   Scheduler_Context *context,
   Scheduler_Node    *node
 )
 {
-  _Scheduler_priority_affinity_SMP_Enqueue_scheduled_ordered(
+  return _Scheduler_priority_affinity_SMP_Enqueue_scheduled_ordered(
     context,
     node,
     _Scheduler_SMP_Insert_priority_fifo_order,
@@ -507,7 +511,7 @@ static void _Scheduler_priority_affinity_SMP_Enqueue_scheduled_fifo(
 /*
  * This is the public scheduler specific Change Priority operation.
  */
-void _Scheduler_priority_affinity_SMP_Change_priority(
+Thread_Control *_Scheduler_priority_affinity_SMP_Change_priority(
   const Scheduler_Control *scheduler,
   Thread_Control          *thread,
   Priority_Control         new_priority,
@@ -515,8 +519,9 @@ void _Scheduler_priority_affinity_SMP_Change_priority(
 )
 {
   Scheduler_Context *context = _Scheduler_Get_context( scheduler );
+  Thread_Control    *displaced;
 
-  _Scheduler_SMP_Change_priority(
+  displaced = _Scheduler_SMP_Change_priority(
     context,
     thread,
     new_priority,
@@ -533,6 +538,8 @@ void _Scheduler_priority_affinity_SMP_Change_priority(
    * Perform any thread migrations that are needed due to these changes.
    */
   _Scheduler_priority_affinity_SMP_Check_for_migrations( context );
+
+  return displaced;
 }
 
 /*
diff --git a/cpukit/score/src/schedulerprioritychangepriority.c b/cpukit/score/src/schedulerprioritychangepriority.c
index 91b9fa7..9f2690f 100644
--- a/cpukit/score/src/schedulerprioritychangepriority.c
+++ b/cpukit/score/src/schedulerprioritychangepriority.c
@@ -21,7 +21,7 @@
 
 #include <rtems/score/schedulerpriorityimpl.h>
 
-void _Scheduler_priority_Change_priority(
+Scheduler_Void_or_thread _Scheduler_priority_Change_priority(
   const Scheduler_Control *scheduler,
   Thread_Control          *the_thread,
   Priority_Control         new_priority,
@@ -58,4 +58,6 @@ void _Scheduler_priority_Change_priority(
       &context->Bit_map
     );
   }
+
+  SCHEDULER_RETURN_VOID_OR_NULL;
 }
diff --git a/cpukit/score/src/schedulerprioritysmp.c b/cpukit/score/src/schedulerprioritysmp.c
index f340b83..c602342 100644
--- a/cpukit/score/src/schedulerprioritysmp.c
+++ b/cpukit/score/src/schedulerprioritysmp.c
@@ -97,7 +97,7 @@ void _Scheduler_priority_SMP_Block(
   );
 }
 
-static void _Scheduler_priority_SMP_Enqueue_ordered(
+static Thread_Control *_Scheduler_priority_SMP_Enqueue_ordered(
   Scheduler_Context *context,
   Scheduler_Node *node,
   Chain_Node_order order,
@@ -105,7 +105,7 @@ static void _Scheduler_priority_SMP_Enqueue_ordered(
   Scheduler_SMP_Insert insert_scheduled
 )
 {
-  _Scheduler_SMP_Enqueue_ordered(
+  return _Scheduler_SMP_Enqueue_ordered(
     context,
     node,
     order,
@@ -117,12 +117,12 @@ static void _Scheduler_priority_SMP_Enqueue_ordered(
   );
 }
 
-static void _Scheduler_priority_SMP_Enqueue_lifo(
+static Thread_Control *_Scheduler_priority_SMP_Enqueue_lifo(
   Scheduler_Context *context,
   Scheduler_Node *node
 )
 {
-  _Scheduler_priority_SMP_Enqueue_ordered(
+  return _Scheduler_priority_SMP_Enqueue_ordered(
     context,
     node,
     _Scheduler_SMP_Insert_priority_lifo_order,
@@ -131,12 +131,12 @@ static void _Scheduler_priority_SMP_Enqueue_lifo(
   );
 }
 
-static void _Scheduler_priority_SMP_Enqueue_fifo(
+static Thread_Control *_Scheduler_priority_SMP_Enqueue_fifo(
   Scheduler_Context *context,
   Scheduler_Node *node
 )
 {
-  _Scheduler_priority_SMP_Enqueue_ordered(
+  return _Scheduler_priority_SMP_Enqueue_ordered(
     context,
     node,
     _Scheduler_SMP_Insert_priority_fifo_order,
@@ -145,7 +145,7 @@ static void _Scheduler_priority_SMP_Enqueue_fifo(
   );
 }
 
-static void _Scheduler_priority_SMP_Enqueue_scheduled_ordered(
+static Thread_Control *_Scheduler_priority_SMP_Enqueue_scheduled_ordered(
   Scheduler_Context *context,
   Scheduler_Node *node,
   Chain_Node_order order,
@@ -153,7 +153,7 @@ static void _Scheduler_priority_SMP_Enqueue_scheduled_ordered(
   Scheduler_SMP_Insert insert_scheduled
 )
 {
-  _Scheduler_SMP_Enqueue_scheduled_ordered(
+  return _Scheduler_SMP_Enqueue_scheduled_ordered(
     context,
     node,
     order,
@@ -165,12 +165,12 @@ static void _Scheduler_priority_SMP_Enqueue_scheduled_ordered(
   );
 }
 
-static void _Scheduler_priority_SMP_Enqueue_scheduled_lifo(
+static Thread_Control *_Scheduler_priority_SMP_Enqueue_scheduled_lifo(
   Scheduler_Context *context,
   Scheduler_Node *node
 )
 {
-  _Scheduler_priority_SMP_Enqueue_scheduled_ordered(
+  return _Scheduler_priority_SMP_Enqueue_scheduled_ordered(
     context,
     node,
     _Scheduler_SMP_Insert_priority_lifo_order,
@@ -179,12 +179,12 @@ static void _Scheduler_priority_SMP_Enqueue_scheduled_lifo(
   );
 }
 
-static void _Scheduler_priority_SMP_Enqueue_scheduled_fifo(
+static Thread_Control *_Scheduler_priority_SMP_Enqueue_scheduled_fifo(
   Scheduler_Context *context,
   Scheduler_Node *node
 )
 {
-  _Scheduler_priority_SMP_Enqueue_scheduled_ordered(
+  return _Scheduler_priority_SMP_Enqueue_scheduled_ordered(
     context,
     node,
     _Scheduler_SMP_Insert_priority_fifo_order,
@@ -193,21 +193,21 @@ static void _Scheduler_priority_SMP_Enqueue_scheduled_fifo(
   );
 }
 
-void _Scheduler_priority_SMP_Unblock(
+Thread_Control *_Scheduler_priority_SMP_Unblock(
   const Scheduler_Control *scheduler,
   Thread_Control *thread
 )
 {
   Scheduler_Context *context = _Scheduler_Get_context( scheduler );
 
-  _Scheduler_SMP_Unblock(
+  return _Scheduler_SMP_Unblock(
     context,
     thread,
     _Scheduler_priority_SMP_Enqueue_fifo
   );
 }
 
-void _Scheduler_priority_SMP_Change_priority(
+Thread_Control *_Scheduler_priority_SMP_Change_priority(
   const Scheduler_Control *scheduler,
   Thread_Control          *thread,
   Priority_Control         new_priority,
@@ -216,7 +216,7 @@ void _Scheduler_priority_SMP_Change_priority(
 {
   Scheduler_Context *context = _Scheduler_Get_context( scheduler );
 
-  _Scheduler_SMP_Change_priority(
+  return _Scheduler_SMP_Change_priority(
     context,
     thread,
     new_priority,
@@ -230,7 +230,7 @@ void _Scheduler_priority_SMP_Change_priority(
   );
 }
 
-void _Scheduler_priority_SMP_Yield(
+Thread_Control *_Scheduler_priority_SMP_Yield(
   const Scheduler_Control *scheduler,
   Thread_Control *thread
 )
diff --git a/cpukit/score/src/schedulerpriorityunblock.c b/cpukit/score/src/schedulerpriorityunblock.c
index ef46df8..771f43a 100644
--- a/cpukit/score/src/schedulerpriorityunblock.c
+++ b/cpukit/score/src/schedulerpriorityunblock.c
@@ -22,7 +22,7 @@
 
 #include <rtems/score/schedulerpriorityimpl.h>
 
-void _Scheduler_priority_Unblock (
+Scheduler_Void_or_thread _Scheduler_priority_Unblock (
   const Scheduler_Control *scheduler,
   Thread_Control          *the_thread
 )
@@ -57,4 +57,6 @@ void _Scheduler_priority_Unblock (
         the_thread->current_priority == 0 )
       _Thread_Dispatch_necessary = true;
   }
+
+  SCHEDULER_RETURN_VOID_OR_NULL;
 }
diff --git a/cpukit/score/src/schedulerpriorityyield.c b/cpukit/score/src/schedulerpriorityyield.c
index 60bab39..2dd3923 100644
--- a/cpukit/score/src/schedulerpriorityyield.c
+++ b/cpukit/score/src/schedulerpriorityyield.c
@@ -21,7 +21,7 @@
 #include <rtems/score/schedulerpriorityimpl.h>
 #include <rtems/score/threadimpl.h>
 
-void _Scheduler_priority_Yield(
+Scheduler_Void_or_thread _Scheduler_priority_Yield(
   const Scheduler_Control *scheduler,
   Thread_Control          *the_thread
 )
@@ -43,4 +43,6 @@ void _Scheduler_priority_Yield(
   } else if ( !_Thread_Is_heir( the_thread ) ) {
     _Thread_Dispatch_necessary = true;
   }
+
+  SCHEDULER_RETURN_VOID_OR_NULL;
 }
diff --git a/cpukit/score/src/schedulersimplechangepriority.c b/cpukit/score/src/schedulersimplechangepriority.c
index 010f1df..b8638ad 100644
--- a/cpukit/score/src/schedulersimplechangepriority.c
+++ b/cpukit/score/src/schedulersimplechangepriority.c
@@ -21,7 +21,7 @@
 
 #include <rtems/score/schedulersimpleimpl.h>
 
-void _Scheduler_simple_Change_priority(
+Scheduler_Void_or_thread _Scheduler_simple_Change_priority(
   const Scheduler_Control *scheduler,
   Thread_Control          *the_thread,
   Priority_Control         new_priority,
@@ -38,4 +38,6 @@ void _Scheduler_simple_Change_priority(
   } else {
     _Scheduler_simple_Insert_priority_fifo( &context->Ready, the_thread );
   }
+
+  SCHEDULER_RETURN_VOID_OR_NULL;
 }
diff --git a/cpukit/score/src/schedulersimplesmp.c b/cpukit/score/src/schedulersimplesmp.c
index 4b0ce0a..ab515bf 100644
--- a/cpukit/score/src/schedulersimplesmp.c
+++ b/cpukit/score/src/schedulersimplesmp.c
@@ -179,7 +179,7 @@ void _Scheduler_simple_SMP_Block(
   );
 }
 
-static void _Scheduler_simple_SMP_Enqueue_ordered(
+static Thread_Control *_Scheduler_simple_SMP_Enqueue_ordered(
   Scheduler_Context *context,
   Scheduler_Node *node,
   Chain_Node_order order,
@@ -187,7 +187,7 @@ static void _Scheduler_simple_SMP_Enqueue_ordered(
   Scheduler_SMP_Insert insert_scheduled
 )
 {
-  _Scheduler_SMP_Enqueue_ordered(
+  return _Scheduler_SMP_Enqueue_ordered(
     context,
     node,
     order,
@@ -199,12 +199,12 @@ static void _Scheduler_simple_SMP_Enqueue_ordered(
   );
 }
 
-static void _Scheduler_simple_SMP_Enqueue_lifo(
+static Thread_Control *_Scheduler_simple_SMP_Enqueue_lifo(
   Scheduler_Context *context,
   Scheduler_Node *node
 )
 {
-  _Scheduler_simple_SMP_Enqueue_ordered(
+  return _Scheduler_simple_SMP_Enqueue_ordered(
     context,
     node,
     _Scheduler_SMP_Insert_priority_lifo_order,
@@ -213,12 +213,12 @@ static void _Scheduler_simple_SMP_Enqueue_lifo(
   );
 }
 
-static void _Scheduler_simple_SMP_Enqueue_fifo(
+static Thread_Control *_Scheduler_simple_SMP_Enqueue_fifo(
   Scheduler_Context *context,
   Scheduler_Node *node
 )
 {
-  _Scheduler_simple_SMP_Enqueue_ordered(
+  return _Scheduler_simple_SMP_Enqueue_ordered(
     context,
     node,
     _Scheduler_SMP_Insert_priority_fifo_order,
@@ -227,7 +227,7 @@ static void _Scheduler_simple_SMP_Enqueue_fifo(
   );
 }
 
-static void _Scheduler_simple_SMP_Enqueue_scheduled_ordered(
+static Thread_Control *_Scheduler_simple_SMP_Enqueue_scheduled_ordered(
   Scheduler_Context *context,
   Scheduler_Node *node,
   Chain_Node_order order,
@@ -235,7 +235,7 @@ static void _Scheduler_simple_SMP_Enqueue_scheduled_ordered(
   Scheduler_SMP_Insert insert_scheduled
 )
 {
-  _Scheduler_SMP_Enqueue_scheduled_ordered(
+  return _Scheduler_SMP_Enqueue_scheduled_ordered(
     context,
     node,
     order,
@@ -247,12 +247,12 @@ static void _Scheduler_simple_SMP_Enqueue_scheduled_ordered(
   );
 }
 
-static void _Scheduler_simple_SMP_Enqueue_scheduled_lifo(
+static Thread_Control *_Scheduler_simple_SMP_Enqueue_scheduled_lifo(
   Scheduler_Context *context,
   Scheduler_Node *node
 )
 {
-  _Scheduler_simple_SMP_Enqueue_scheduled_ordered(
+  return _Scheduler_simple_SMP_Enqueue_scheduled_ordered(
     context,
     node,
     _Scheduler_SMP_Insert_priority_lifo_order,
@@ -261,12 +261,12 @@ static void _Scheduler_simple_SMP_Enqueue_scheduled_lifo(
   );
 }
 
-static void _Scheduler_simple_SMP_Enqueue_scheduled_fifo(
+static Thread_Control *_Scheduler_simple_SMP_Enqueue_scheduled_fifo(
   Scheduler_Context *context,
   Scheduler_Node *node
 )
 {
-  _Scheduler_simple_SMP_Enqueue_scheduled_ordered(
+  return _Scheduler_simple_SMP_Enqueue_scheduled_ordered(
     context,
     node,
     _Scheduler_SMP_Insert_priority_fifo_order,
@@ -275,21 +275,21 @@ static void _Scheduler_simple_SMP_Enqueue_scheduled_fifo(
   );
 }
 
-void _Scheduler_simple_SMP_Unblock(
+Thread_Control *_Scheduler_simple_SMP_Unblock(
   const Scheduler_Control *scheduler,
   Thread_Control *thread
 )
 {
   Scheduler_Context *context = _Scheduler_Get_context( scheduler );
 
-  _Scheduler_SMP_Unblock(
+  return _Scheduler_SMP_Unblock(
     context,
     thread,
     _Scheduler_simple_SMP_Enqueue_fifo
   );
 }
 
-void _Scheduler_simple_SMP_Change_priority(
+Thread_Control *_Scheduler_simple_SMP_Change_priority(
   const Scheduler_Control *scheduler,
   Thread_Control          *thread,
   Priority_Control         new_priority,
@@ -298,7 +298,7 @@ void _Scheduler_simple_SMP_Change_priority(
 {
   Scheduler_Context *context = _Scheduler_Get_context( scheduler );
 
-  _Scheduler_SMP_Change_priority(
+  return _Scheduler_SMP_Change_priority(
     context,
     thread,
     new_priority,
@@ -312,7 +312,7 @@ void _Scheduler_simple_SMP_Change_priority(
   );
 }
 
-void _Scheduler_simple_SMP_Yield(
+Thread_Control *_Scheduler_simple_SMP_Yield(
   const Scheduler_Control *scheduler,
   Thread_Control *thread
 )
diff --git a/cpukit/score/src/schedulersimpleunblock.c b/cpukit/score/src/schedulersimpleunblock.c
index 4e49bd6..6f9b2f7 100644
--- a/cpukit/score/src/schedulersimpleunblock.c
+++ b/cpukit/score/src/schedulersimpleunblock.c
@@ -21,7 +21,7 @@
 #include <rtems/score/schedulersimpleimpl.h>
 #include <rtems/score/thread.h>
 
-void _Scheduler_simple_Unblock(
+Scheduler_Void_or_thread _Scheduler_simple_Unblock(
   const Scheduler_Control *scheduler,
   Thread_Control          *the_thread
 )
@@ -49,4 +49,6 @@ void _Scheduler_simple_Unblock(
         the_thread->current_priority == 0 )
       _Thread_Dispatch_necessary = true;
   }
+
+  SCHEDULER_RETURN_VOID_OR_NULL;
 }
diff --git a/cpukit/score/src/schedulersimpleyield.c b/cpukit/score/src/schedulersimpleyield.c
index b807530..66e4450 100644
--- a/cpukit/score/src/schedulersimpleyield.c
+++ b/cpukit/score/src/schedulersimpleyield.c
@@ -20,7 +20,7 @@
 
 #include <rtems/score/schedulersimpleimpl.h>
 
-void _Scheduler_simple_Yield(
+Scheduler_Void_or_thread _Scheduler_simple_Yield(
   const Scheduler_Control *scheduler,
   Thread_Control          *the_thread
 )
@@ -31,4 +31,6 @@ void _Scheduler_simple_Yield(
   _Chain_Extract_unprotected( &the_thread->Object.Node );
   _Scheduler_simple_Insert_priority_fifo( &context->Ready, the_thread );
   _Scheduler_simple_Schedule_body( scheduler, the_thread, false );
+
+  SCHEDULER_RETURN_VOID_OR_NULL;
 }
diff --git a/testsuites/smptests/smpscheduler03/init.c b/testsuites/smptests/smpscheduler03/init.c
index 4fddc8d..4004d2a 100644
--- a/testsuites/smptests/smpscheduler03/init.c
+++ b/testsuites/smptests/smpscheduler03/init.c
@@ -53,7 +53,40 @@ static void task(rtems_task_argument arg)
   rtems_test_assert(0);
 }
 
-static void test_case(
+static rtems_id start_task(rtems_task_priority prio)
+{
+  rtems_status_code sc;
+  rtems_id task_id;
+
+  sc = rtems_task_create(
+    rtems_build_name('T', 'A', 'S', 'K'),
+    prio,
+    RTEMS_MINIMUM_STACK_SIZE,
+    RTEMS_DEFAULT_MODES,
+    RTEMS_DEFAULT_ATTRIBUTES,
+    &task_id
+  );
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  sc = rtems_task_start(task_id, task, 0);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  return task_id;
+}
+
+static Thread_Control *get_thread_by_id(rtems_id task_id)
+{
+  Objects_Locations location;
+  Thread_Control *thread;
+
+  thread = _Thread_Get(task_id, &location);
+  rtems_test_assert(location == OBJECTS_LOCAL);
+  _Thread_Enable_dispatch();
+
+  return thread;
+}
+
+static void test_case_change_priority(
   Thread_Control *executing,
   Scheduler_SMP_Node *node,
   Scheduler_SMP_Node_state start_state,
@@ -98,28 +131,17 @@ static void test_change_priority(void)
   size_t j;
   size_t k;
 
-  sc = rtems_task_create(
-    rtems_build_name('T', 'A', 'S', 'K'),
-    3,
-    RTEMS_MINIMUM_STACK_SIZE,
-    RTEMS_DEFAULT_MODES,
-    RTEMS_DEFAULT_ATTRIBUTES,
-    &task_id
-  );
-  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
-
-  sc = rtems_task_start(task_id, task, 0);
-  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+  task_id = start_task(3);
 
   _Thread_Disable_dispatch();
 
   executing = _Thread_Executing;
-  node = _Scheduler_SMP_Node_get( executing );
+  node = _Scheduler_SMP_Node_get(executing);
 
   for (i = 0; i < RTEMS_ARRAY_SIZE(states); ++i) {
     for (j = 0; j < RTEMS_ARRAY_SIZE(priorities); ++j) {
       for (k = 0; k < RTEMS_ARRAY_SIZE(prepend_it); ++k) {
-        test_case(
+        test_case_change_priority(
           executing,
           node,
           states[i],
@@ -140,11 +162,340 @@ static void test_change_priority(void)
   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
 }
 
+static Thread_Control *change_priority_op(
+  Thread_Control *thread,
+  Priority_Control new_priority,
+  bool prepend_it
+)
+{
+  const Scheduler_Control *scheduler = _Scheduler_Get(thread);
+
+  thread->current_priority = new_priority;
+
+  return (*scheduler->Operations.change_priority)(
+    scheduler,
+    thread,
+    new_priority,
+    prepend_it
+  );
+}
+
+static void test_case_change_priority_op(
+  Thread_Control *executing,
+  Scheduler_SMP_Node *executing_node,
+  Thread_Control *other,
+  Scheduler_SMP_Node_state start_state,
+  Priority_Control prio,
+  bool prepend_it,
+  Scheduler_SMP_Node_state new_state
+)
+{
+  Thread_Control *needs_help;
+
+  switch (start_state) {
+    case SCHEDULER_SMP_NODE_SCHEDULED:
+      _Thread_Change_priority(executing, 1, true);
+      break;
+    case SCHEDULER_SMP_NODE_READY:
+      _Thread_Change_priority(executing, 4, true);
+      break;
+    default:
+      rtems_test_assert(0);
+      break;
+  }
+  rtems_test_assert(executing_node->state == start_state);
+
+  needs_help = change_priority_op(executing, prio, prepend_it);
+  rtems_test_assert(executing_node->state == new_state);
+
+  if (start_state != new_state) {
+    switch (start_state) {
+      case SCHEDULER_SMP_NODE_SCHEDULED:
+        rtems_test_assert(needs_help == executing);
+        break;
+      case SCHEDULER_SMP_NODE_READY:
+        rtems_test_assert(needs_help == other);
+        break;
+      default:
+        rtems_test_assert(0);
+        break;
+    }
+  } else {
+    rtems_test_assert(needs_help == NULL);
+  }
+}
+
+static void test_change_priority_op(void)
+{
+  rtems_status_code sc;
+  rtems_id task_id;
+  Thread_Control *executing;
+  Scheduler_SMP_Node *executing_node;
+  Thread_Control *other;
+  size_t i;
+  size_t j;
+  size_t k;
+
+  task_id = start_task(3);
+
+  _Thread_Disable_dispatch();
+
+  executing = _Thread_Executing;
+  executing_node = _Scheduler_SMP_Node_get(executing);
+
+  other = get_thread_by_id(task_id);
+
+  for (i = 0; i < RTEMS_ARRAY_SIZE(states); ++i) {
+    for (j = 0; j < RTEMS_ARRAY_SIZE(priorities); ++j) {
+      for (k = 0; k < RTEMS_ARRAY_SIZE(prepend_it); ++k) {
+        test_case_change_priority_op(
+          executing,
+          executing_node,
+          other,
+          states[i],
+          priorities[j],
+          prepend_it[k],
+          states[j]
+        );
+      }
+    }
+  }
+
+  _Thread_Change_priority(executing, 1, true);
+  rtems_test_assert(executing_node->state == SCHEDULER_SMP_NODE_SCHEDULED);
+
+  _Thread_Enable_dispatch();
+
+  sc = rtems_task_delete(task_id);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static Thread_Control *yield_op(Thread_Control *thread)
+{
+  const Scheduler_Control *scheduler = _Scheduler_Get(thread);
+
+  return (*scheduler->Operations.yield)(scheduler, thread);
+}
+
+static void test_case_yield_op(
+  Thread_Control *executing,
+  Scheduler_SMP_Node *executing_node,
+  Thread_Control *other,
+  Scheduler_SMP_Node_state start_state,
+  Scheduler_SMP_Node_state new_state
+)
+{
+  Thread_Control *needs_help;
+
+  _Thread_Change_priority(executing, 4, false);
+  _Thread_Change_priority(other, 4, false);
+
+  switch (start_state) {
+    case SCHEDULER_SMP_NODE_SCHEDULED:
+      switch (new_state) {
+        case SCHEDULER_SMP_NODE_SCHEDULED:
+          _Thread_Change_priority(executing, 2, false);
+          _Thread_Change_priority(other, 3, false);
+          break;
+        case SCHEDULER_SMP_NODE_READY:
+          _Thread_Change_priority(executing, 2, false);
+          _Thread_Change_priority(other, 2, false);
+          break;
+        default:
+          rtems_test_assert(0);
+          break;
+      }
+      break;
+    case SCHEDULER_SMP_NODE_READY:
+      switch (new_state) {
+        case SCHEDULER_SMP_NODE_SCHEDULED:
+          rtems_test_assert(0);
+          break;
+        case SCHEDULER_SMP_NODE_READY:
+          _Thread_Change_priority(executing, 3, false);
+          _Thread_Change_priority(other, 2, false);
+          break;
+        default:
+          rtems_test_assert(0);
+          break;
+      }
+      break;
+    default:
+      rtems_test_assert(0);
+      break;
+  }
+  rtems_test_assert(executing_node->state == start_state);
+
+  needs_help = yield_op(executing);
+  rtems_test_assert(executing_node->state == new_state);
+
+  if (start_state != new_state) {
+    switch (start_state) {
+      case SCHEDULER_SMP_NODE_SCHEDULED:
+        rtems_test_assert(needs_help == executing);
+        break;
+      case SCHEDULER_SMP_NODE_READY:
+        rtems_test_assert(needs_help == other);
+        break;
+      default:
+        rtems_test_assert(0);
+        break;
+    }
+  } else {
+    rtems_test_assert(needs_help == NULL);
+  }
+}
+
+static void test_yield_op(void)
+{
+  rtems_status_code sc;
+  rtems_id task_id;
+  Thread_Control *executing;
+  Scheduler_SMP_Node *executing_node;
+  Thread_Control *other;
+  size_t i;
+  size_t j;
+
+  task_id = start_task(2);
+
+  _Thread_Disable_dispatch();
+
+  executing = _Thread_Executing;
+  executing_node = _Scheduler_SMP_Node_get(executing);
+
+  other = get_thread_by_id(task_id);
+
+  for (i = 0; i < RTEMS_ARRAY_SIZE(states); ++i) {
+    for (j = 0; j < RTEMS_ARRAY_SIZE(states); ++j) {
+      if (
+        states[i] != SCHEDULER_SMP_NODE_READY
+          || states[j] != SCHEDULER_SMP_NODE_SCHEDULED
+      ) {
+        test_case_yield_op(
+          executing,
+          executing_node,
+          other,
+          states[i],
+          states[j]
+        );
+      }
+    }
+  }
+
+  _Thread_Change_priority(executing, 1, true);
+  rtems_test_assert(executing_node->state == SCHEDULER_SMP_NODE_SCHEDULED);
+
+  _Thread_Enable_dispatch();
+
+  sc = rtems_task_delete(task_id);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static void block_op(Thread_Control *thread)
+{
+  const Scheduler_Control *scheduler = _Scheduler_Get(thread);
+
+  (*scheduler->Operations.block)(scheduler, thread);
+}
+
+static Thread_Control *unblock_op(Thread_Control *thread)
+{
+  const Scheduler_Control *scheduler = _Scheduler_Get(thread);
+
+  return (*scheduler->Operations.unblock)(scheduler, thread);
+}
+
+static void test_case_unblock_op(
+  Thread_Control *executing,
+  Scheduler_SMP_Node *executing_node,
+  Thread_Control *other,
+  Scheduler_SMP_Node_state new_state
+)
+{
+  Thread_Control *needs_help;
+
+  switch (new_state) {
+    case SCHEDULER_SMP_NODE_SCHEDULED:
+      _Thread_Change_priority(executing, 2, false);
+      rtems_test_assert(executing_node->state == SCHEDULER_SMP_NODE_SCHEDULED);
+      break;
+    case SCHEDULER_SMP_NODE_READY:
+      _Thread_Change_priority(executing, 4, false);
+      rtems_test_assert(executing_node->state == SCHEDULER_SMP_NODE_READY);
+      break;
+    default:
+      rtems_test_assert(0);
+      break;
+  }
+
+  block_op(executing);
+  rtems_test_assert(executing_node->state == SCHEDULER_SMP_NODE_BLOCKED);
+
+  needs_help = unblock_op(executing);
+  rtems_test_assert(executing_node->state == new_state);
+
+  switch (new_state) {
+    case SCHEDULER_SMP_NODE_SCHEDULED:
+      rtems_test_assert(needs_help == other);
+      break;
+    case SCHEDULER_SMP_NODE_READY:
+      rtems_test_assert(needs_help == NULL);
+      break;
+    default:
+      rtems_test_assert(0);
+      break;
+  }
+}
+
+static void test_unblock_op(void)
+{
+  rtems_status_code sc;
+  rtems_id task_id;
+  Thread_Control *executing;
+  Scheduler_SMP_Node *executing_node;
+  Thread_Control *other;
+  size_t i;
+
+  task_id = start_task(3);
+
+  _Thread_Disable_dispatch();
+
+  executing = _Thread_Executing;
+  executing_node = _Scheduler_SMP_Node_get(executing);
+
+  other = get_thread_by_id(task_id);
+
+  for (i = 0; i < RTEMS_ARRAY_SIZE(states); ++i) {
+    test_case_unblock_op(
+      executing,
+      executing_node,
+      other,
+      states[i]
+    );
+  }
+
+  _Thread_Change_priority(executing, 1, true);
+  rtems_test_assert(executing_node->state == SCHEDULER_SMP_NODE_SCHEDULED);
+
+  _Thread_Enable_dispatch();
+
+  sc = rtems_task_delete(task_id);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static void tests(void)
+{
+  test_change_priority();
+  test_change_priority_op();
+  test_yield_op();
+  test_unblock_op();
+}
+
 static void test_task(rtems_task_argument arg)
 {
   test_context *ctx = &test_instance;
 
-  test_change_priority();
+  tests();
 
   ctx->cpu_index[arg] = rtems_get_current_processor();
 
@@ -202,7 +553,7 @@ static void Init(rtems_task_argument arg)
     rtems_test_assert(sc == RTEMS_SUCCESSFUL);
   }
 
-  test_change_priority();
+  tests();
 
   barrier_wait(ctx);
 
-- 
1.7.7



More information about the devel mailing list