[rtems commit] smp: Add Deterministic Priority SMP Scheduler

Sebastian Huber sebh at rtems.org
Tue Aug 20 08:14:19 UTC 2013


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

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Wed Aug  7 15:35:47 2013 +0200

smp: Add Deterministic Priority SMP Scheduler

---

 cpukit/sapi/include/confdefs.h                     |   24 ++-
 cpukit/score/Makefile.am                           |    2 +
 .../include/rtems/score/schedulerpriorityimpl.h    |   17 ++
 .../include/rtems/score/schedulerprioritysmp.h     |   94 +++++++++
 cpukit/score/preinstall.am                         |    4 +
 cpukit/score/src/schedulerprioritysmp.c            |  212 ++++++++++++++++++++
 cpukit/score/src/schedulerpriorityupdate.c         |   10 +-
 doc/user/conf.t                                    |   40 ++++-
 .../smptests/smpmigration01/smpmigration01.scn     |   24 +-
 9 files changed, 402 insertions(+), 25 deletions(-)

diff --git a/cpukit/sapi/include/confdefs.h b/cpukit/sapi/include/confdefs.h
index 31d28ac..dc4fb5e 100644
--- a/cpukit/sapi/include/confdefs.h
+++ b/cpukit/sapi/include/confdefs.h
@@ -606,6 +606,7 @@ const rtems_libio_helper rtems_fs_init_helper =
  * scheduling policy to use.  The supported configurations are:
  *  CONFIGURE_SCHEDULER_USER       - user provided scheduler
  *  CONFIGURE_SCHEDULER_PRIORITY   - Deterministic Priority Scheduler
+ *  CONFIGURE_SCHEDULER_PRIORITY_SMP - Deterministic Priority SMP Scheduler
  *  CONFIGURE_SCHEDULER_SIMPLE     - Light-weight Priority Scheduler
  *  CONFIGURE_SCHEDULER_SIMPLE_SMP - Simple SMP Priority Scheduler
  *  CONFIGURE_SCHEDULER_EDF        - EDF Scheduler
@@ -629,12 +630,13 @@ const rtems_libio_helper rtems_fs_init_helper =
 /* If no scheduler is specified, the priority scheduler is default. */
 #if !defined(CONFIGURE_SCHEDULER_USER) && \
     !defined(CONFIGURE_SCHEDULER_PRIORITY) && \
+    !defined(CONFIGURE_SCHEDULER_PRIORITY_SMP) && \
     !defined(CONFIGURE_SCHEDULER_SIMPLE) && \
     !defined(CONFIGURE_SCHEDULER_SIMPLE_SMP) && \
     !defined(CONFIGURE_SCHEDULER_EDF) && \
     !defined(CONFIGURE_SCHEDULER_CBS)
   #if defined(RTEMS_SMP) && defined(CONFIGURE_SMP_APPLICATION)
-    #define CONFIGURE_SCHEDULER_SIMPLE_SMP
+    #define CONFIGURE_SCHEDULER_PRIORITY_SMP
   #else
     #define CONFIGURE_SCHEDULER_PRIORITY
   #endif
@@ -659,6 +661,26 @@ const rtems_libio_helper rtems_fs_init_helper =
 #endif
 
 /*
+ * If the Deterministic Priority SMP Scheduler is selected, then configure for
+ * it.
+ */
+#if defined(CONFIGURE_SCHEDULER_PRIORITY_SMP)
+  #include <rtems/score/schedulerprioritysmp.h>
+  #define CONFIGURE_SCHEDULER_ENTRY_POINTS SCHEDULER_PRIORITY_SMP_ENTRY_POINTS
+
+  /**
+   * This defines the memory used by the priority scheduler.
+   */
+  #define CONFIGURE_MEMORY_FOR_SCHEDULER ( \
+    _Configure_From_workspace( \
+      sizeof(Scheduler_SMP_Control) +  \
+      ((CONFIGURE_MAXIMUM_PRIORITY) * sizeof(Chain_Control)) ) \
+  )
+  #define CONFIGURE_MEMORY_PER_TASK_FOR_SCHEDULER ( \
+    _Configure_From_workspace(sizeof(Scheduler_priority_Per_thread)) )
+#endif
+
+/*
  * If the Simple Priority Scheduler is selected, then configure for it.
  */
 #if defined(CONFIGURE_SCHEDULER_SIMPLE)
diff --git a/cpukit/score/Makefile.am b/cpukit/score/Makefile.am
index c5af9c7..c9d2d47 100644
--- a/cpukit/score/Makefile.am
+++ b/cpukit/score/Makefile.am
@@ -53,6 +53,7 @@ include_rtems_score_HEADERS += include/rtems/score/scheduleredf.h
 include_rtems_score_HEADERS += include/rtems/score/scheduleredfimpl.h
 include_rtems_score_HEADERS += include/rtems/score/schedulerpriority.h
 include_rtems_score_HEADERS += include/rtems/score/schedulerpriorityimpl.h
+include_rtems_score_HEADERS += include/rtems/score/schedulerprioritysmp.h
 include_rtems_score_HEADERS += include/rtems/score/schedulersimple.h
 include_rtems_score_HEADERS += include/rtems/score/schedulersimpleimpl.h
 include_rtems_score_HEADERS += include/rtems/score/schedulersmp.h
@@ -119,6 +120,7 @@ libscore_a_SOURCES += src/mpci.c src/objectmp.c src/threadmp.c
 endif
 
 if HAS_SMP
+libscore_a_SOURCES += src/schedulerprioritysmp.c
 libscore_a_SOURCES += src/schedulersimplesmp.c
 libscore_a_SOURCES += src/schedulersmpstartidle.c
 libscore_a_SOURCES += src/smp.c
diff --git a/cpukit/score/include/rtems/score/schedulerpriorityimpl.h b/cpukit/score/include/rtems/score/schedulerpriorityimpl.h
index 9f45f21..1c85150 100644
--- a/cpukit/score/include/rtems/score/schedulerpriorityimpl.h
+++ b/cpukit/score/include/rtems/score/schedulerpriorityimpl.h
@@ -186,6 +186,23 @@ RTEMS_INLINE_ROUTINE void _Scheduler_priority_Schedule_body(
   _Scheduler_Update_heir( heir, force_dispatch );
 }
 
+RTEMS_INLINE_ROUTINE void _Scheduler_priority_Update_body(
+  Thread_Control *thread,
+  Chain_Control *ready_queues
+)
+{
+  Scheduler_priority_Per_thread *sched_info_of_thread =
+    _Scheduler_priority_Get_scheduler_info( thread );
+
+  sched_info_of_thread->ready_chain =
+    &ready_queues[ thread->current_priority ];
+
+  _Priority_bit_map_Initialize_information(
+    &sched_info_of_thread->Priority_map,
+    thread->current_priority
+  );
+}
+
 /**
  * @brief Priority comparison.
  *
diff --git a/cpukit/score/include/rtems/score/schedulerprioritysmp.h b/cpukit/score/include/rtems/score/schedulerprioritysmp.h
new file mode 100644
index 0000000..f19f1de
--- /dev/null
+++ b/cpukit/score/include/rtems/score/schedulerprioritysmp.h
@@ -0,0 +1,94 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreSchedulerPrioritySMP
+ *
+ * @brief Deterministic Priority SMP Scheduler API
+ */
+
+/*
+ * Copyright (c) 2013 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Dornierstr. 4
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifndef _RTEMS_SCORE_SCHEDULERPRIORITYSMP_H
+#define _RTEMS_SCORE_SCHEDULERPRIORITYSMP_H
+
+#include <rtems/score/scheduler.h>
+#include <rtems/score/schedulerpriority.h>
+#include <rtems/score/schedulersmp.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup ScoreSchedulerPrioritySMP Deterministic Priority SMP Scheduler
+ *
+ * @ingroup ScoreScheduler
+ *
+ * This is an implementation of the global fixed priority scheduler (G-FP).  It
+ * uses one ready chain per priority to ensure constant time insert operations.
+ * The scheduled chain uses linear insert operations and has at most processor
+ * count entries.  Since the processor and priority count are constants all
+ * scheduler operations complete in a bounded execution time.
+ *
+ * The thread preempt mode will be ignored.
+ *
+ * @{
+ */
+
+/**
+ * @brief Entry points for the Simple SMP Scheduler.
+ */
+#define SCHEDULER_PRIORITY_SMP_ENTRY_POINTS \
+  { \
+    _Scheduler_priority_SMP_Initialize, \
+    _Scheduler_priority_SMP_Schedule, \
+    _Scheduler_priority_SMP_Yield, \
+    _Scheduler_priority_SMP_Block, \
+    _Scheduler_priority_SMP_Enqueue_fifo, \
+    _Scheduler_priority_Allocate, \
+    _Scheduler_priority_Free, \
+    _Scheduler_priority_SMP_Update, \
+    _Scheduler_priority_SMP_Enqueue_fifo, \
+    _Scheduler_priority_SMP_Enqueue_lifo, \
+    _Scheduler_priority_SMP_Extract, \
+    _Scheduler_priority_Priority_compare, \
+    _Scheduler_default_Release_job, \
+    _Scheduler_default_Tick, \
+    _Scheduler_SMP_Start_idle \
+  }
+
+void _Scheduler_priority_SMP_Initialize( void );
+
+void _Scheduler_priority_SMP_Schedule( Thread_Control *thread );
+
+void _Scheduler_priority_SMP_Block( Thread_Control *thread );
+
+void _Scheduler_priority_SMP_Update( Thread_Control *thread );
+
+void _Scheduler_priority_SMP_Enqueue_fifo( Thread_Control *thread );
+
+void _Scheduler_priority_SMP_Enqueue_lifo( Thread_Control *thread );
+
+void _Scheduler_priority_SMP_Extract( Thread_Control *thread );
+
+void _Scheduler_priority_SMP_Yield( Thread_Control *thread );
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _RTEMS_SCORE_SCHEDULERPRIORITYSMP_H */
diff --git a/cpukit/score/preinstall.am b/cpukit/score/preinstall.am
index 4e645f4..79a18b5 100644
--- a/cpukit/score/preinstall.am
+++ b/cpukit/score/preinstall.am
@@ -195,6 +195,10 @@ $(PROJECT_INCLUDE)/rtems/score/schedulerpriorityimpl.h: include/rtems/score/sche
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/schedulerpriorityimpl.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/schedulerpriorityimpl.h
 
+$(PROJECT_INCLUDE)/rtems/score/schedulerprioritysmp.h: include/rtems/score/schedulerprioritysmp.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/schedulerprioritysmp.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/schedulerprioritysmp.h
+
 $(PROJECT_INCLUDE)/rtems/score/schedulersimple.h: include/rtems/score/schedulersimple.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/schedulersimple.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/schedulersimple.h
diff --git a/cpukit/score/src/schedulerprioritysmp.c b/cpukit/score/src/schedulerprioritysmp.c
new file mode 100644
index 0000000..fed94b1
--- /dev/null
+++ b/cpukit/score/src/schedulerprioritysmp.c
@@ -0,0 +1,212 @@
+/**
+ * @file
+ *
+ * @brief Deterministic Priority SMP Scheduler Implementation
+ *
+ * @ingroup ScoreSchedulerSMP
+ */
+
+/*
+ * Copyright (c) 2013 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Dornierstr. 4
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#if HAVE_CONFIG_H
+  #include "config.h"
+#endif
+
+#include <rtems/score/schedulerprioritysmp.h>
+#include <rtems/score/schedulerpriorityimpl.h>
+#include <rtems/score/schedulersmpimpl.h>
+#include <rtems/score/wkspace.h>
+
+void _Scheduler_priority_SMP_Initialize( void )
+{
+  Scheduler_SMP_Control *self = _Workspace_Allocate_or_fatal_error(
+    sizeof( *self ) + PRIORITY_MAXIMUM * sizeof( Chain_Control )
+  );
+
+  _Chain_Initialize_empty( &self->scheduled );
+  _Scheduler_priority_Ready_queue_initialize( &self->ready[ 0 ] );
+
+  _Scheduler.information = self;
+}
+
+void _Scheduler_priority_SMP_Update( Thread_Control *thread )
+{
+  Scheduler_SMP_Control *self = _Scheduler_SMP_Instance();
+
+  _Scheduler_priority_Update_body( thread, &self->ready[ 0 ] );
+}
+
+static Thread_Control *_Scheduler_priority_SMP_Get_highest_ready(
+  Scheduler_SMP_Control *self
+)
+{
+  Thread_Control *highest_ready = NULL;
+
+  if ( !_Priority_bit_map_Is_empty() ) {
+    highest_ready = _Scheduler_priority_Ready_queue_first( &self->ready[ 0 ] );
+  }
+
+  return highest_ready;
+}
+
+static void _Scheduler_priority_SMP_Move_from_scheduled_to_ready(
+  Scheduler_SMP_Control *self,
+  Thread_Control *scheduled_to_ready
+)
+{
+  _Chain_Extract_unprotected( &scheduled_to_ready->Object.Node );
+  _Scheduler_priority_Ready_queue_enqueue_first( scheduled_to_ready );
+}
+
+static void _Scheduler_priority_SMP_Move_from_ready_to_scheduled(
+  Scheduler_SMP_Control *self,
+  Thread_Control *ready_to_scheduled
+)
+{
+  _Scheduler_priority_Ready_queue_extract( ready_to_scheduled );
+  _Scheduler_simple_Insert_priority_fifo(
+    &self->scheduled,
+    ready_to_scheduled
+  );
+}
+
+static void _Scheduler_priority_SMP_Insert_ready_lifo(
+  Scheduler_SMP_Control *self,
+  Thread_Control *thread
+)
+{
+  _Scheduler_priority_Ready_queue_enqueue( thread );
+}
+
+static void _Scheduler_priority_SMP_Insert_ready_fifo(
+  Scheduler_SMP_Control *self,
+  Thread_Control *thread
+)
+{
+  _Scheduler_priority_Ready_queue_enqueue_first( thread );
+}
+
+static void _Scheduler_priority_SMP_Do_extract(
+  Scheduler_SMP_Control *self,
+  Thread_Control *thread
+)
+{
+  bool is_scheduled = thread->is_scheduled;
+
+  ( void ) self;
+
+  thread->is_in_the_air = is_scheduled;
+  thread->is_scheduled = false;
+
+  if ( is_scheduled ) {
+    _Chain_Extract_unprotected( &thread->Object.Node );
+  } else {
+    _Scheduler_priority_Ready_queue_extract( thread );
+  }
+}
+
+void _Scheduler_priority_SMP_Block( Thread_Control *thread )
+{
+  Scheduler_SMP_Control *self = _Scheduler_SMP_Instance();
+
+  _Scheduler_SMP_Block(
+    self,
+    thread,
+    _Scheduler_priority_SMP_Do_extract,
+    _Scheduler_priority_SMP_Get_highest_ready,
+    _Scheduler_priority_SMP_Move_from_ready_to_scheduled
+  );
+}
+
+static void _Scheduler_priority_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_priority_SMP_Get_highest_ready,
+    insert_ready,
+    insert_scheduled,
+    _Scheduler_priority_SMP_Move_from_ready_to_scheduled,
+    _Scheduler_priority_SMP_Move_from_scheduled_to_ready
+  );
+}
+
+void _Scheduler_priority_SMP_Enqueue_lifo( Thread_Control *thread )
+{
+  Scheduler_SMP_Control *self = _Scheduler_SMP_Instance();
+
+  _Scheduler_priority_SMP_Enqueue_ordered(
+    self,
+    thread,
+    _Scheduler_simple_Insert_priority_lifo_order,
+    _Scheduler_priority_SMP_Insert_ready_lifo,
+    _Scheduler_SMP_Insert_scheduled_lifo
+  );
+}
+
+void _Scheduler_priority_SMP_Enqueue_fifo( Thread_Control *thread )
+{
+  Scheduler_SMP_Control *self = _Scheduler_SMP_Instance();
+
+  _Scheduler_priority_SMP_Enqueue_ordered(
+    self,
+    thread,
+    _Scheduler_simple_Insert_priority_fifo_order,
+    _Scheduler_priority_SMP_Insert_ready_fifo,
+    _Scheduler_SMP_Insert_scheduled_fifo
+  );
+}
+
+void _Scheduler_priority_SMP_Extract( Thread_Control *thread )
+{
+  Scheduler_SMP_Control *self = _Scheduler_SMP_Instance();
+
+  _Scheduler_SMP_Extract(
+    self,
+    thread,
+    _Scheduler_priority_SMP_Do_extract
+  );
+}
+
+void _Scheduler_priority_SMP_Yield( Thread_Control *thread )
+{
+  ISR_Level level;
+
+  _ISR_Disable( level );
+
+  _Scheduler_priority_SMP_Extract( thread );
+  _Scheduler_priority_SMP_Enqueue_fifo( thread );
+
+  _ISR_Enable( level );
+}
+
+void _Scheduler_priority_SMP_Schedule( Thread_Control *thread )
+{
+  Scheduler_SMP_Control *self = _Scheduler_SMP_Instance();
+
+  _Scheduler_SMP_Schedule(
+    self,
+    thread,
+    _Scheduler_priority_SMP_Get_highest_ready,
+    _Scheduler_priority_SMP_Move_from_ready_to_scheduled
+  );
+}
diff --git a/cpukit/score/src/schedulerpriorityupdate.c b/cpukit/score/src/schedulerpriorityupdate.c
index de3f026..062b369 100644
--- a/cpukit/score/src/schedulerpriorityupdate.c
+++ b/cpukit/score/src/schedulerpriorityupdate.c
@@ -25,15 +25,7 @@ void _Scheduler_priority_Update(
   Thread_Control    *the_thread
 )
 {
-  Scheduler_priority_Per_thread *sched_info_of_thread =
-    _Scheduler_priority_Get_scheduler_info( the_thread );
   Chain_Control *ready_queues = _Scheduler_priority_Get_ready_queues();
 
-  sched_info_of_thread->ready_chain =
-    &ready_queues[ the_thread->current_priority ];
-
-  _Priority_bit_map_Initialize_information(
-    &sched_info_of_thread->Priority_map,
-    the_thread->current_priority
-  );
+  _Scheduler_priority_Update_body( the_thread, ready_queues );
 }
diff --git a/doc/user/conf.t b/doc/user/conf.t
index 66f31ad..94d523f 100644
--- a/doc/user/conf.t
+++ b/doc/user/conf.t
@@ -3536,6 +3536,43 @@ This scheduler may be explicitly selected by defining
 None.
 
 @c
+ at c === CONFIGURE_SCHEDULER_PRIORITY_SMP ===
+ at c
+ at subsection Use Deterministic Priority SMP Scheduler
+
+ at findex CONFIGURE_SCHEDULER_PRIORITY_SMP
+
+ at table @b
+ at item CONSTANT:
+ at code{CONFIGURE_SCHEDULER_PRIORITY_SMP}
+
+ at item DATA TYPE:
+Boolean feature macro.
+
+ at item RANGE:
+Defined or undefined.
+
+ at item DEFAULT VALUE:
+This is not defined by default.
+
+ at end table
+
+ at subheading DESCRIPTION:
+The Deterministic Priority SMP Scheduler is derived from the Deterministic
+Priority Scheduler but is capable of scheduling threads across multiple
+processors.
+
+In a configuration with SMP enabled at configure time, it may be
+explicitly selected by defining @code{CONFIGURE_SCHEDULER_PRIORITY_SMP}.
+
+ at subheading NOTES:
+This scheduler is only available when RTEMS is configured with SMP
+support enabled.
+
+This scheduler is currently the default in SMP configurations and is
+only selected when @code{CONFIGURE_SMP_APPLICATION} is defined.
+
+ at c
 @c === CONFIGURE_SCHEDULER_SIMPLE_SMP ===
 @c
 @subsection Use Simple SMP Priority Scheduler
@@ -3578,9 +3615,6 @@ explicitly selected by defining @code{CONFIGURE_SCHEDULER_SIMPLE_SMP}.
 This scheduler is only available when RTEMS is configured with SMP
 support enabled.
 
-This scheduler is currently the default in SMP configurations and is
-only selected when @code{CONFIGURE_SMP_APPLICATION} is defined.
-
 @c
 @c === Configuring a User Scheduler ===
 @c
diff --git a/testsuites/smptests/smpmigration01/smpmigration01.scn b/testsuites/smptests/smpmigration01/smpmigration01.scn
index c5a2106..b2b56ff 100644
--- a/testsuites/smptests/smpmigration01/smpmigration01.scn
+++ b/testsuites/smptests/smpmigration01/smpmigration01.scn
@@ -1,17 +1,17 @@
 *** TEST SMPMIGRATION 1 ***
 runner 0
-        cpu 0 tokens 530399
-        cpu 0 cycles 10077490
-        cpu 1 tokens 530399
-        cpu 1 cycles 10071429
+        cpu 0 tokens 453284
+        cpu 0 cycles 14955317
+        cpu 1 tokens 453283
+        cpu 1 cycles 14978390
 runner 1
-        cpu 0 tokens 530399
-        cpu 0 cycles 5978212
-        cpu 1 tokens 530399
-        cpu 1 cycles 7951897
+        cpu 0 tokens 453283
+        cpu 0 cycles 21302793
+        cpu 1 tokens 453283
+        cpu 1 cycles 21318817
 runner 2
-        cpu 0 tokens 530399
-        cpu 0 cycles 10070929
-        cpu 1 tokens 530398
-        cpu 1 cycles 10106437
+        cpu 0 tokens 453283
+        cpu 0 cycles 19973312
+        cpu 1 tokens 453283
+        cpu 1 cycles 21315227
 *** END OF TEST SMPMIGRATION 1 ***




More information about the vc mailing list