[PATCH 11/12] smp: Generalize Simple SMP scheduler

Sebastian Huber sebastian.huber at embedded-brains.de
Tue Aug 13 13:42:56 UTC 2013


---
 .../score/include/rtems/score/schedulersmpimpl.h   |  165 ++++++++++++++++++++
 cpukit/score/src/schedulersimplesmp.c              |  158 +++++++++----------
 2 files changed, 239 insertions(+), 84 deletions(-)

diff --git a/cpukit/score/include/rtems/score/schedulersmpimpl.h b/cpukit/score/include/rtems/score/schedulersmpimpl.h
index 40e94cb..625797a 100644
--- a/cpukit/score/include/rtems/score/schedulersmpimpl.h
+++ b/cpukit/score/include/rtems/score/schedulersmpimpl.h
@@ -24,6 +24,8 @@
 #define _RTEMS_SCORE_SCHEDULERSMPIMPL_H
 
 #include <rtems/score/schedulersmp.h>
+#include <rtems/score/schedulersimpleimpl.h>
+#include <rtems/score/chainimpl.h>
 #include <rtems/score/scheduler.h>
 
 #ifdef __cplusplus
@@ -36,6 +38,25 @@ extern "C" {
  * @{
  */
 
+typedef Thread_Control *( *Scheduler_SMP_Get_highest_ready )(
+  Scheduler_SMP_Control *self
+);
+
+typedef void ( *Scheduler_SMP_Extract )(
+  Scheduler_SMP_Control *self,
+  Thread_Control *thread
+);
+
+typedef void ( *Scheduler_SMP_Insert )(
+  Scheduler_SMP_Control *self,
+  Thread_Control *thread_to_insert
+);
+
+typedef void ( *Scheduler_SMP_Move )(
+  Scheduler_SMP_Control *self,
+  Thread_Control *thread_to_move
+);
+
 static inline Scheduler_SMP_Control *_Scheduler_SMP_Instance( void )
 {
   return _Scheduler.information;
@@ -97,6 +118,150 @@ static inline Thread_Control *_Scheduler_SMP_Get_lowest_scheduled(
   return lowest_ready;
 }
 
+static inline void _Scheduler_SMP_Enqueue_ordered(
+  Scheduler_SMP_Control *self,
+  Thread_Control *thread,
+  Chain_Node_order order,
+  Scheduler_SMP_Get_highest_ready get_highest_ready,
+  Scheduler_SMP_Insert insert_ready,
+  Scheduler_SMP_Insert insert_scheduled,
+  Scheduler_SMP_Move move_from_ready_to_scheduled,
+  Scheduler_SMP_Move move_from_scheduled_to_ready
+)
+{
+  if ( thread->is_in_the_air ) {
+    Thread_Control *highest_ready = ( *get_highest_ready )( self );
+
+    thread->is_in_the_air = false;
+
+    /*
+     * The thread has been extracted from the scheduled chain.  We have to
+     * place it now on the scheduled or ready chain.
+     *
+     * XXX: Do not exchange parameters to do the negation of the order check.
+     */
+    if (
+      highest_ready != NULL
+        && !( *order )( &thread->Object.Node, &highest_ready->Object.Node )
+    ) {
+      _Scheduler_SMP_Allocate_processor( highest_ready, thread );
+
+      ( *insert_ready )( self, thread );
+      ( *move_from_ready_to_scheduled )( self, highest_ready );
+    } else {
+      thread->is_scheduled = true;
+
+      ( *insert_scheduled )( self, thread );
+    }
+  } else {
+    Thread_Control *lowest_scheduled = _Scheduler_SMP_Get_lowest_scheduled( self );
+
+    /*
+     * The scheduled chain is empty if nested interrupts change the priority of
+     * all scheduled threads.  These threads are in the air.
+     */
+    if (
+      lowest_scheduled != NULL
+        && ( *order )( &thread->Object.Node, &lowest_scheduled->Object.Node )
+    ) {
+      _Scheduler_SMP_Allocate_processor( thread, lowest_scheduled );
+
+      ( *insert_scheduled )( self, thread );
+      ( *move_from_scheduled_to_ready )( self, lowest_scheduled );
+    } else {
+      ( *insert_ready )( self, thread );
+    }
+  }
+}
+
+static inline void _Scheduler_SMP_Schedule_highest_ready(
+  Scheduler_SMP_Control *self,
+  Thread_Control *victim,
+  Scheduler_SMP_Get_highest_ready get_highest_ready,
+  Scheduler_SMP_Move move_from_ready_to_scheduled
+)
+{
+  Thread_Control *highest_ready = ( *get_highest_ready )( self );
+
+  _Scheduler_SMP_Allocate_processor( highest_ready, victim );
+
+  ( *move_from_ready_to_scheduled )( self, highest_ready );
+}
+
+static inline void _Scheduler_SMP_Block(
+  Scheduler_SMP_Control *self,
+  Thread_Control *thread,
+  Scheduler_SMP_Extract extract,
+  Scheduler_SMP_Get_highest_ready get_highest_ready,
+  Scheduler_SMP_Move move_from_ready_to_scheduled
+)
+{
+  ( *extract )( self, thread );
+
+  if ( thread->is_in_the_air ) {
+    thread->is_in_the_air = false;
+
+    _Scheduler_SMP_Schedule_highest_ready(
+      self,
+      thread,
+      get_highest_ready,
+      move_from_ready_to_scheduled
+    );
+  }
+}
+
+static inline void _Scheduler_SMP_Extract(
+  Scheduler_SMP_Control *self,
+  Thread_Control *thread,
+  Scheduler_SMP_Extract extract
+)
+{
+  ( *extract )( self, thread );
+}
+
+static inline void _Scheduler_SMP_Schedule(
+  Scheduler_SMP_Control *self,
+  Thread_Control *thread,
+  Scheduler_SMP_Get_highest_ready get_highest_ready,
+  Scheduler_SMP_Move move_from_ready_to_scheduled
+)
+{
+  if ( thread->is_in_the_air ) {
+    thread->is_in_the_air = false;
+
+    _Scheduler_SMP_Schedule_highest_ready(
+      self,
+      thread,
+      get_highest_ready,
+      move_from_ready_to_scheduled
+    );
+  }
+}
+
+static inline void _Scheduler_SMP_Insert_scheduled_lifo(
+  Scheduler_SMP_Control *self,
+  Thread_Control *thread
+)
+{
+  _Chain_Insert_ordered_unprotected(
+    &self->scheduled,
+    &thread->Object.Node,
+    _Scheduler_simple_Insert_priority_lifo_order
+  );
+}
+
+static inline void _Scheduler_SMP_Insert_scheduled_fifo(
+  Scheduler_SMP_Control *self,
+  Thread_Control *thread
+)
+{
+  _Chain_Insert_ordered_unprotected(
+    &self->scheduled,
+    &thread->Object.Node,
+    _Scheduler_simple_Insert_priority_fifo_order
+  );
+}
+
 /** @} */
 
 #ifdef __cplusplus
diff --git a/cpukit/score/src/schedulersimplesmp.c b/cpukit/score/src/schedulersimplesmp.c
index f9fc2cc..0aa26170 100644
--- a/cpukit/score/src/schedulersimplesmp.c
+++ b/cpukit/score/src/schedulersimplesmp.c
@@ -19,7 +19,6 @@
 #endif
 
 #include <rtems/score/schedulersimplesmp.h>
-#include <rtems/score/schedulersimpleimpl.h>
 #include <rtems/score/schedulersmpimpl.h>
 #include <rtems/score/wkspace.h>
 
@@ -72,121 +71,111 @@ static void _Scheduler_simple_smp_Move_from_ready_to_scheduled(
   );
 }
 
-static void _Scheduler_simple_smp_Insert(
-  Chain_Control *chain,
-  Thread_Control *thread,
-  Chain_Node_order order
+static void _Scheduler_simple_smp_Insert_ready_lifo(
+  Scheduler_SMP_Control *self,
+  Thread_Control *thread
 )
 {
-  _Chain_Insert_ordered_unprotected( chain, &thread->Object.Node, order );
+  _Chain_Insert_ordered_unprotected(
+    &self->ready[ 0 ],
+    &thread->Object.Node,
+    _Scheduler_simple_Insert_priority_lifo_order
+  );
 }
 
-static void _Scheduler_simple_smp_Schedule_highest_ready(
+static void _Scheduler_simple_smp_Insert_ready_fifo(
   Scheduler_SMP_Control *self,
-  Thread_Control *victim
+  Thread_Control *thread
 )
 {
-  Thread_Control *highest_ready =
-    (Thread_Control *) _Chain_First( &self->ready[ 0 ] );
-
-  _Scheduler_SMP_Allocate_processor( highest_ready, victim );
-
-  _Scheduler_simple_smp_Move_from_ready_to_scheduled( self, highest_ready );
+  _Chain_Insert_ordered_unprotected(
+    &self->ready[ 0 ],
+    &thread->Object.Node,
+    _Scheduler_simple_Insert_priority_fifo_order
+  );
 }
 
-static void _Scheduler_simple_smp_Enqueue_ordered(
-  Thread_Control *thread,
-  Chain_Node_order order
+static void _Scheduler_simple_smp_Do_extract(
+  Scheduler_SMP_Control *self,
+  Thread_Control *thread
 )
 {
-  Scheduler_SMP_Control *self = _Scheduler_SMP_Instance();
-
-  if ( thread->is_in_the_air ) {
-    Thread_Control *highest_ready =
-      _Scheduler_simple_smp_Get_highest_ready( self );
-
-    thread->is_in_the_air = false;
-
-    /*
-     * The thread has been extracted from the scheduled chain.  We have to
-     * place it now on the scheduled or ready chain.
-     *
-     * XXX: Do not exchange parameters to do the negation of the order check.
-     */
-    if (
-      highest_ready != NULL
-        && !( *order )( &thread->Object.Node, &highest_ready->Object.Node )
-    ) {
-      _Scheduler_SMP_Allocate_processor( highest_ready, thread );
-
-      _Scheduler_simple_smp_Insert( &self->ready[ 0 ], thread, order );
-
-      _Scheduler_simple_smp_Move_from_ready_to_scheduled(
-        self,
-        highest_ready
-      );
-    } else {
-      thread->is_scheduled = true;
-
-      _Scheduler_simple_smp_Insert( &self->scheduled, thread, order );
-    }
-  } else {
-    Thread_Control *lowest_scheduled = _Scheduler_SMP_Get_lowest_scheduled( self );
+  ( void ) self;
 
-    /*
-     * The scheduled chain is empty if nested interrupts change the priority of
-     * all scheduled threads.  These threads are in the air.
-     */
-    if (
-      lowest_scheduled != NULL
-        && ( *order )( &thread->Object.Node, &lowest_scheduled->Object.Node )
-    ) {
-      _Scheduler_SMP_Allocate_processor( thread, lowest_scheduled );
+  thread->is_in_the_air = thread->is_scheduled;
+  thread->is_scheduled = false;
 
-      _Scheduler_simple_smp_Insert( &self->scheduled, thread, order );
-
-      _Scheduler_simple_smp_Move_from_scheduled_to_ready(
-        self,
-        lowest_scheduled
-      );
-    } else {
-      _Scheduler_simple_smp_Insert( &self->ready[ 0 ], thread, order );
-    }
-  }
+  _Chain_Extract_unprotected( &thread->Object.Node );
 }
 
 void _Scheduler_simple_smp_Block( Thread_Control *thread )
 {
-  _Chain_Extract_unprotected( &thread->Object.Node );
+  Scheduler_SMP_Control *self = _Scheduler_SMP_Instance();
 
-  if ( thread->is_scheduled ) {
-    Scheduler_SMP_Control *self = _Scheduler_SMP_Instance();
+  _Scheduler_SMP_Block(
+    self,
+    thread,
+    _Scheduler_simple_smp_Do_extract,
+    _Scheduler_simple_smp_Get_highest_ready,
+    _Scheduler_simple_smp_Move_from_ready_to_scheduled
+  );
+}
 
-    _Scheduler_simple_smp_Schedule_highest_ready( self, thread );
-  }
+static void _Scheduler_simple_smp_Enqueue_ordered(
+  Scheduler_SMP_Control *self,
+  Thread_Control *thread,
+  Chain_Node_order order,
+  Scheduler_SMP_Insert insert_ready,
+  Scheduler_SMP_Insert insert_scheduled
+)
+{
+  _Scheduler_SMP_Enqueue_ordered(
+    self,
+    thread,
+    order,
+    _Scheduler_simple_smp_Get_highest_ready,
+    insert_ready,
+    insert_scheduled,
+    _Scheduler_simple_smp_Move_from_ready_to_scheduled,
+    _Scheduler_simple_smp_Move_from_scheduled_to_ready
+  );
 }
 
 void _Scheduler_simple_smp_Enqueue_priority_lifo( Thread_Control *thread )
 {
+  Scheduler_SMP_Control *self = _Scheduler_SMP_Instance();
+
   _Scheduler_simple_smp_Enqueue_ordered(
+    self,
     thread,
-    _Scheduler_simple_Insert_priority_lifo_order
+    _Scheduler_simple_Insert_priority_lifo_order,
+    _Scheduler_simple_smp_Insert_ready_lifo,
+    _Scheduler_SMP_Insert_scheduled_lifo
   );
 }
 
 void _Scheduler_simple_smp_Enqueue_priority_fifo( Thread_Control *thread )
 {
+  Scheduler_SMP_Control *self = _Scheduler_SMP_Instance();
+
   _Scheduler_simple_smp_Enqueue_ordered(
+    self,
     thread,
-    _Scheduler_simple_Insert_priority_fifo_order
+    _Scheduler_simple_Insert_priority_fifo_order,
+    _Scheduler_simple_smp_Insert_ready_fifo,
+    _Scheduler_SMP_Insert_scheduled_fifo
   );
 }
 
 void _Scheduler_simple_smp_Extract( Thread_Control *thread )
 {
-  thread->is_in_the_air = true;
+  Scheduler_SMP_Control *self = _Scheduler_SMP_Instance();
 
-  _Chain_Extract_unprotected( &thread->Object.Node );
+  _Scheduler_SMP_Extract(
+    self,
+    thread,
+    _Scheduler_simple_smp_Do_extract
+  );
 }
 
 void _Scheduler_simple_smp_Yield( Thread_Control *thread )
@@ -203,11 +192,12 @@ void _Scheduler_simple_smp_Yield( Thread_Control *thread )
 
 void _Scheduler_simple_smp_Schedule( Thread_Control *thread )
 {
-  if ( thread->is_in_the_air ) {
-    Scheduler_SMP_Control *self = _Scheduler_SMP_Instance();
-
-    thread->is_in_the_air = false;
+  Scheduler_SMP_Control *self = _Scheduler_SMP_Instance();
 
-    _Scheduler_simple_smp_Schedule_highest_ready( self, thread );
-  }
+  _Scheduler_SMP_Schedule(
+    self,
+    thread,
+    _Scheduler_simple_smp_Get_highest_ready,
+    _Scheduler_simple_smp_Move_from_ready_to_scheduled
+  );
 }
-- 
1.7.7




More information about the devel mailing list