[rtems commit] score: Need for help indicator for scheduler ops

Sebastian Huber sebh at rtems.org
Tue Jul 8 14:57:17 UTC 2014


Module:    rtems
Branch:    master
Commit:    8568341d69d16609a3dcf71716a89839b16ac881
Changeset: http://git.rtems.org/rtems/commit/?id=8568341d69d16609a3dcf71716a89839b16ac881

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Wed Jun 11 14:31:03 2014 +0200

score: Need for help indicator for scheduler ops

Return a thread in need for help for the following scheduler operations

- unblock,
- change priority, and
- yield.

A thread in need for help is a thread that encounters a scheduler state
change from scheduled to ready or a thread that cannot be scheduled in
an unblock operation.  Such a thread can ask threads which depend on
resources owned by this thread 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   |   42 ++
 .../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   |   82 +++--
 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    |   49 ++-
 cpukit/score/src/schedulerprioritychangepriority.c |    4 +-
 cpukit/score/src/schedulerprioritysmp.c            |   54 ++--
 cpukit/score/src/schedulerpriorityunblock.c        |    4 +-
 cpukit/score/src/schedulerpriorityyield.c          |    4 +-
 cpukit/score/src/schedulersimplechangepriority.c   |    4 +-
 cpukit/score/src/schedulersimplesmp.c              |   54 ++--
 cpukit/score/src/schedulersimpleunblock.c          |    4 +-
 cpukit/score/src/schedulersimpleyield.c            |    4 +-
 testsuites/smptests/smpscheduler03/init.c          |  403 +++++++++++++++++++-
 24 files changed, 645 insertions(+), 142 deletions(-)

diff --git a/cpukit/score/include/rtems/score/scheduler.h b/cpukit/score/include/rtems/score/scheduler.h
index bb30a8e..993ae55 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 3b59301..008cc91 100644
--- a/cpukit/score/include/rtems/score/schedulercbs.h
+++ b/cpukit/score/include/rtems/score/schedulercbs.h
@@ -153,7 +153,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 6d759f5..1dda767 100644
--- a/cpukit/score/include/rtems/score/scheduleredf.h
+++ b/cpukit/score/include/rtems/score/scheduleredf.h
@@ -177,12 +177,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,
@@ -204,7 +204,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 edb68b6..5e4e509 100644
--- a/cpukit/score/include/rtems/score/schedulerimpl.h
+++ b/cpukit/score/include/rtems/score/schedulerimpl.h
@@ -116,6 +116,24 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Schedule( Thread_Control *the_thread )
   ( *scheduler->Operations.schedule )( scheduler, the_thread );
 }
 
+#if defined(RTEMS_SMP)
+/**
+ * @brief Ask threads depending on resources owned by the thread for help.
+ *
+ * A thread is in need for help if it lost its assigned processor due to
+ * pre-emption by a higher priority thread or it was not possible to assign it
+ * a processor since its priority is to low on its current scheduler instance.
+ *
+ * @param[in] needs_help The thread needing help.
+ */
+RTEMS_INLINE_ROUTINE void _Scheduler_Ask_for_help_if_necessary(
+  Thread_Control *needs_help
+)
+{
+  (void) needs_help;
+}
+#endif
+
 /**
  * @brief Scheduler yield with a particular thread.
  *
@@ -127,8 +145,16 @@ 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 );
+#if defined(RTEMS_SMP)
+  Thread_Control *needs_help;
 
+  needs_help =
+#endif
   ( *scheduler->Operations.yield )( scheduler, the_thread );
+
+#if defined(RTEMS_SMP)
+  _Scheduler_Ask_for_help_if_necessary( needs_help );
+#endif
 }
 
 /**
@@ -161,8 +187,16 @@ 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 *needs_help;
 
+  needs_help =
+#endif
   ( *scheduler->Operations.unblock )( scheduler, the_thread );
+
+#if defined(RTEMS_SMP)
+  _Scheduler_Ask_for_help_if_necessary( needs_help );
+#endif
 }
 
 /**
@@ -185,13 +219,21 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Change_priority(
 )
 {
   const Scheduler_Control *scheduler = _Scheduler_Get( the_thread );
+#if defined(RTEMS_SMP)
+  Thread_Control *needs_help;
 
+  needs_help =
+#endif
   ( *scheduler->Operations.change_priority )(
     scheduler,
     the_thread,
     new_priority,
     prepend_it
   );
+
+#if defined(RTEMS_SMP)
+  _Scheduler_Ask_for_help_if_necessary( needs_help );
+#endif
 }
 
 /**
diff --git a/cpukit/score/include/rtems/score/schedulerpriority.h b/cpukit/score/include/rtems/score/schedulerpriority.h
index e412bab..805e302 100644
--- a/cpukit/score/include/rtems/score/schedulerpriority.h
+++ b/cpukit/score/include/rtems/score/schedulerpriority.h
@@ -149,12 +149,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,
@@ -180,7 +180,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 e922c2b..a1a1481 100644
--- a/cpukit/score/include/rtems/score/schedulerprioritysmp.h
+++ b/cpukit/score/include/rtems/score/schedulerprioritysmp.h
@@ -106,12 +106,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,
@@ -124,7 +124,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 ef60613..c97ad2f 100644
--- a/cpukit/score/include/rtems/score/schedulersimple.h
+++ b/cpukit/score/include/rtems/score/schedulersimple.h
@@ -101,7 +101,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
 );
@@ -130,12 +130,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 790cedd..de338ab 100644
--- a/cpukit/score/include/rtems/score/schedulersimplesmp.h
+++ b/cpukit/score/include/rtems/score/schedulersimplesmp.h
@@ -87,12 +87,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,
@@ -105,7 +105,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 b7d86a3..55d0697 100644
--- a/cpukit/score/include/rtems/score/schedulersmpimpl.h
+++ b/cpukit/score/include/rtems/score/schedulersmpimpl.h
@@ -306,7 +306,13 @@ 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,
+  Thread_Control    *needs_help
+);
+
+typedef Thread_Control *( *Scheduler_SMP_Enqueue_scheduled )(
   Scheduler_Context *context,
   Scheduler_Node    *node_to_enqueue
 );
@@ -492,6 +498,8 @@ static inline Scheduler_Node *_Scheduler_SMP_Get_lowest_scheduled(
  *
  * @param[in] context The scheduler instance context.
  * @param[in] node The node to enqueue.
+ * @param[in] needs_help The thread needing help in case the node cannot be
+ *   scheduled.
  * @param[in] order The order function.
  * @param[in] insert_ready Function to insert a node into the set of ready
  *   nodes.
@@ -506,9 +514,10 @@ 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,
+  Thread_Control                     *needs_help,
   Chain_Node_order                    order,
   Scheduler_SMP_Insert                insert_ready,
   Scheduler_SMP_Insert                insert_scheduled,
@@ -535,9 +544,13 @@ static inline void _Scheduler_SMP_Enqueue_ordered(
 
     ( *insert_scheduled )( context, node );
     ( *move_from_scheduled_to_ready )( context, lowest_scheduled );
+
+    needs_help = _Scheduler_Node_get_user( lowest_scheduled );
   } else {
     ( *insert_ready )( context, node );
   }
+
+  return needs_help;
 }
 
 /**
@@ -557,7 +570,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,
@@ -569,6 +582,7 @@ static inline void _Scheduler_SMP_Enqueue_scheduled_ordered(
 )
 {
   Scheduler_Node *highest_ready = ( *get_highest_ready )( context, node );
+  Thread_Control *needs_help;
 
   _Assert( highest_ready != NULL );
 
@@ -578,6 +592,8 @@ static inline void _Scheduler_SMP_Enqueue_scheduled_ordered(
    */
   if ( ( *order )( &node->Node, &highest_ready->Node ) ) {
     ( *insert_scheduled )( context, node );
+
+    needs_help = NULL;
   } else {
     _Scheduler_SMP_Node_change_state(
       _Scheduler_SMP_Node_downcast( node ),
@@ -593,7 +609,11 @@ static inline void _Scheduler_SMP_Enqueue_scheduled_ordered(
 
     ( *insert_ready )( context, node );
     ( *move_from_ready_to_scheduled )( context, highest_ready );
+
+    needs_help = _Scheduler_Node_get_user( node );
   }
+
+  return needs_help;
 }
 
 static inline void _Scheduler_SMP_Extract_from_scheduled(
@@ -663,7 +683,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
@@ -673,23 +693,24 @@ 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, thread );
 }
 
-static inline void _Scheduler_SMP_Change_priority(
-  Scheduler_Context     *context,
-  Thread_Control        *thread,
-  Priority_Control       new_priority,
-  bool                   prepend_it,
-  Scheduler_SMP_Extract  extract_from_ready,
-  Scheduler_SMP_Update   update,
-  Scheduler_SMP_Enqueue  enqueue_fifo,
-  Scheduler_SMP_Enqueue  enqueue_lifo,
-  Scheduler_SMP_Enqueue  enqueue_scheduled_fifo,
-  Scheduler_SMP_Enqueue  enqueue_scheduled_lifo
+static inline Thread_Control *_Scheduler_SMP_Change_priority(
+  Scheduler_Context               *context,
+  Thread_Control                  *thread,
+  Priority_Control                 new_priority,
+  bool                             prepend_it,
+  Scheduler_SMP_Extract            extract_from_ready,
+  Scheduler_SMP_Update             update,
+  Scheduler_SMP_Enqueue            enqueue_fifo,
+  Scheduler_SMP_Enqueue            enqueue_lifo,
+  Scheduler_SMP_Enqueue_scheduled  enqueue_scheduled_fifo,
+  Scheduler_SMP_Enqueue_scheduled  enqueue_scheduled_lifo
 )
 {
   Scheduler_SMP_Node *node = _Scheduler_SMP_Thread_get_node( thread );
+  Thread_Control *needs_help;
 
   if ( node->state == SCHEDULER_SMP_NODE_SCHEDULED ) {
     _Scheduler_SMP_Extract_from_scheduled( &node->Base );
@@ -697,9 +718,9 @@ static inline void _Scheduler_SMP_Change_priority(
     ( *update )( context, &node->Base, new_priority );
 
     if ( prepend_it ) {
-      ( *enqueue_scheduled_lifo )( context, &node->Base );
+      needs_help = ( *enqueue_scheduled_lifo )( context, &node->Base );
     } else {
-      ( *enqueue_scheduled_fifo )( context, &node->Base );
+      needs_help = ( *enqueue_scheduled_fifo )( context, &node->Base );
     }
   } else {
     ( *extract_from_ready )( context, &node->Base );
@@ -707,32 +728,37 @@ static inline void _Scheduler_SMP_Change_priority(
     ( *update )( context, &node->Base, new_priority );
 
     if ( prepend_it ) {
-      ( *enqueue_lifo )( context, &node->Base );
+      needs_help = ( *enqueue_lifo )( context, &node->Base, NULL );
     } else {
-      ( *enqueue_fifo )( context, &node->Base );
+      needs_help = ( *enqueue_fifo )( context, &node->Base, NULL );
     }
   }
+
+  return needs_help;
 }
 
-static inline void _Scheduler_SMP_Yield(
-  Scheduler_Context     *context,
-  Thread_Control        *thread,
-  Scheduler_SMP_Extract  extract_from_ready,
-  Scheduler_SMP_Enqueue  enqueue_fifo,
-  Scheduler_SMP_Enqueue  enqueue_scheduled_fifo
+static inline Thread_Control *_Scheduler_SMP_Yield(
+  Scheduler_Context               *context,
+  Thread_Control                  *thread,
+  Scheduler_SMP_Extract            extract_from_ready,
+  Scheduler_SMP_Enqueue            enqueue_fifo,
+  Scheduler_SMP_Enqueue_scheduled  enqueue_scheduled_fifo
 )
 {
   Scheduler_SMP_Node *node = _Scheduler_SMP_Thread_get_node( thread );
+  Thread_Control *needs_help;
 
   if ( node->state == SCHEDULER_SMP_NODE_SCHEDULED ) {
     _Scheduler_SMP_Extract_from_scheduled( &node->Base );
 
-    ( *enqueue_scheduled_fifo )( context, &node->Base );
+    needs_help = ( *enqueue_scheduled_fifo )( context, &node->Base );
   } else {
     ( *extract_from_ready )( context, &node->Base );
 
-    ( *enqueue_fifo )( context, &node->Base );
+    needs_help = ( *enqueue_fifo )( context, &node->Base, NULL );
   }
+
+  return needs_help;
 }
 
 static inline void _Scheduler_SMP_Insert_scheduled_lifo(
diff --git a/cpukit/score/src/schedulercbsunblock.c b/cpukit/score/src/schedulercbsunblock.c
index 5822af2..688253c 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 1422fb1..32b0993 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 0990ac0..5aa2afd 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 e6a662e..14a022e 100644
--- a/cpukit/score/src/schedulerpriorityaffinitysmp.c
+++ b/cpukit/score/src/schedulerpriorityaffinitysmp.c
@@ -288,14 +288,16 @@ 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_Node    *node,
+  Thread_Control    *needs_help
 )
 {
-  _Scheduler_SMP_Enqueue_ordered(
+  return _Scheduler_SMP_Enqueue_ordered(
     context,
     node,
+    needs_help,
     _Scheduler_priority_affinity_SMP_Insert_priority_fifo_order,
     _Scheduler_priority_SMP_Insert_ready_fifo,
     _Scheduler_SMP_Insert_scheduled_fifo,
@@ -374,14 +376,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
@@ -391,23 +394,27 @@ 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,
+  Thread_Control        *needs_help,
   Chain_Node_order       order,
   Scheduler_SMP_Insert   insert_ready,
   Scheduler_SMP_Insert   insert_scheduled
 )
 {
-  _Scheduler_SMP_Enqueue_ordered(
+  return _Scheduler_SMP_Enqueue_ordered(
     context,
     node,
+    needs_help,
     order,
     insert_ready,
     insert_scheduled,
@@ -422,14 +429,16 @@ 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_Node    *node,
+  Thread_Control    *needs_help
 )
 {
-  _Scheduler_priority_affinity_SMP_Enqueue_ordered(
+  return _Scheduler_priority_affinity_SMP_Enqueue_ordered(
     context,
     node,
+    needs_help,
     _Scheduler_priority_affinity_SMP_Insert_priority_lifo_order,
     _Scheduler_priority_SMP_Insert_ready_lifo,
     _Scheduler_SMP_Insert_scheduled_lifo
@@ -441,7 +450,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,
@@ -449,7 +459,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,
@@ -466,12 +476,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,
@@ -485,12 +495,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,
@@ -502,7 +512,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,
@@ -510,8 +520,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,
@@ -528,6 +539,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 4f00af6..06c5f0f 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 1f6d608..b642c5d 100644
--- a/cpukit/score/src/schedulerprioritysmp.c
+++ b/cpukit/score/src/schedulerprioritysmp.c
@@ -97,17 +97,19 @@ void _Scheduler_priority_SMP_Block(
   );
 }
 
-static void _Scheduler_priority_SMP_Enqueue_ordered(
-  Scheduler_Context *context,
-  Scheduler_Node *node,
-  Chain_Node_order order,
-  Scheduler_SMP_Insert insert_ready,
-  Scheduler_SMP_Insert insert_scheduled
+static Thread_Control *_Scheduler_priority_SMP_Enqueue_ordered(
+  Scheduler_Context    *context,
+  Scheduler_Node       *node,
+  Thread_Control       *needs_help,
+  Chain_Node_order      order,
+  Scheduler_SMP_Insert  insert_ready,
+  Scheduler_SMP_Insert  insert_scheduled
 )
 {
-  _Scheduler_SMP_Enqueue_ordered(
+  return _Scheduler_SMP_Enqueue_ordered(
     context,
     node,
+    needs_help,
     order,
     insert_ready,
     insert_scheduled,
@@ -117,35 +119,39 @@ 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_Node    *node,
+  Thread_Control    *needs_help
 )
 {
-  _Scheduler_priority_SMP_Enqueue_ordered(
+  return _Scheduler_priority_SMP_Enqueue_ordered(
     context,
     node,
+    needs_help,
     _Scheduler_SMP_Insert_priority_lifo_order,
     _Scheduler_priority_SMP_Insert_ready_lifo,
     _Scheduler_SMP_Insert_scheduled_lifo
   );
 }
 
-static void _Scheduler_priority_SMP_Enqueue_fifo(
+static Thread_Control *_Scheduler_priority_SMP_Enqueue_fifo(
   Scheduler_Context *context,
-  Scheduler_Node *node
+  Scheduler_Node    *node,
+  Thread_Control    *needs_help
 )
 {
-  _Scheduler_priority_SMP_Enqueue_ordered(
+  return _Scheduler_priority_SMP_Enqueue_ordered(
     context,
     node,
+    needs_help,
     _Scheduler_SMP_Insert_priority_fifo_order,
     _Scheduler_priority_SMP_Insert_ready_fifo,
     _Scheduler_SMP_Insert_scheduled_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 +159,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 +171,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 +185,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 +199,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 +222,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 +236,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 c1f12f4..06d29f3 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 de4b842..2ee2d03 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 7361678..ee540be 100644
--- a/cpukit/score/src/schedulersimplesmp.c
+++ b/cpukit/score/src/schedulersimplesmp.c
@@ -179,17 +179,19 @@ void _Scheduler_simple_SMP_Block(
   );
 }
 
-static void _Scheduler_simple_SMP_Enqueue_ordered(
-  Scheduler_Context *context,
-  Scheduler_Node *node,
-  Chain_Node_order order,
-  Scheduler_SMP_Insert insert_ready,
-  Scheduler_SMP_Insert insert_scheduled
+static Thread_Control *_Scheduler_simple_SMP_Enqueue_ordered(
+  Scheduler_Context    *context,
+  Scheduler_Node       *node,
+  Thread_Control       *needs_help,
+  Chain_Node_order      order,
+  Scheduler_SMP_Insert  insert_ready,
+  Scheduler_SMP_Insert  insert_scheduled
 )
 {
-  _Scheduler_SMP_Enqueue_ordered(
+  return _Scheduler_SMP_Enqueue_ordered(
     context,
     node,
+    needs_help,
     order,
     insert_ready,
     insert_scheduled,
@@ -199,35 +201,39 @@ 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_Node    *node,
+  Thread_Control    *needs_help
 )
 {
-  _Scheduler_simple_SMP_Enqueue_ordered(
+  return _Scheduler_simple_SMP_Enqueue_ordered(
     context,
     node,
+    needs_help,
     _Scheduler_SMP_Insert_priority_lifo_order,
     _Scheduler_simple_SMP_Insert_ready_lifo,
     _Scheduler_SMP_Insert_scheduled_lifo
   );
 }
 
-static void _Scheduler_simple_SMP_Enqueue_fifo(
+static Thread_Control *_Scheduler_simple_SMP_Enqueue_fifo(
   Scheduler_Context *context,
-  Scheduler_Node *node
+  Scheduler_Node    *node,
+  Thread_Control    *needs_help
 )
 {
-  _Scheduler_simple_SMP_Enqueue_ordered(
+  return _Scheduler_simple_SMP_Enqueue_ordered(
     context,
     node,
+    needs_help,
     _Scheduler_SMP_Insert_priority_fifo_order,
     _Scheduler_simple_SMP_Insert_ready_fifo,
     _Scheduler_SMP_Insert_scheduled_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 +241,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 +253,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 +267,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 +281,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 +304,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 +318,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 a66a687..d919482 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,18 +131,7 @@ 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();
 
@@ -119,7 +141,7 @@ static void test_change_priority(void)
   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,360 @@ 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_Control *needs_help;
+  ISR_Level level;
+
+  _ISR_Disable( level );
+  thread->current_priority = new_priority;
+  needs_help = (*scheduler->Operations.change_priority)(
+    scheduler,
+    thread,
+    new_priority,
+    prepend_it
+  );
+  _ISR_Enable( level );
+
+  return needs_help;
+}
+
+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_Thread_get_node(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);
+  Thread_Control *needs_help;
+  ISR_Level level;
+
+  _ISR_Disable( level );
+  needs_help = (*scheduler->Operations.yield)(scheduler, thread);
+  _ISR_Enable( level );
+
+  return needs_help;
+}
+
+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_Thread_get_node(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);
+  ISR_Level level;
+
+  _ISR_Disable( level );
+  (*scheduler->Operations.block)(scheduler, thread);
+  _ISR_Enable( level );
+}
+
+static Thread_Control *unblock_op(Thread_Control *thread)
+{
+  const Scheduler_Control *scheduler = _Scheduler_Get(thread);
+  Thread_Control *needs_help;
+  ISR_Level level;
+
+  _ISR_Disable( level );
+  needs_help = (*scheduler->Operations.unblock)(scheduler, thread);
+  _ISR_Enable( level );
+
+  return needs_help;
+}
+
+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 == executing);
+      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_Thread_get_node(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 +573,7 @@ static void Init(rtems_task_argument arg)
     rtems_test_assert(sc == RTEMS_SUCCESSFUL);
   }
 
-  test_change_priority();
+  tests();
 
   barrier_wait(ctx);
 



More information about the vc mailing list