[PATCH 8/8] score: Add scheduler assignments for SMP

Sebastian Huber sebastian.huber at embedded-brains.de
Fri Apr 11 15:11:48 UTC 2014


---
 cpukit/rtems/src/clocktick.c                       |    2 +-
 cpukit/rtems/src/schedulergetprocessorset.c        |    6 +-
 cpukit/sapi/include/confdefs.h                     |  116 +++++++++++++
 cpukit/sapi/include/rtems/scheduler.h              |   17 ++
 cpukit/score/include/rtems/score/scheduler.h       |   57 ++++++-
 cpukit/score/include/rtems/score/schedulerimpl.h   |   79 ++++++++-
 cpukit/score/include/rtems/score/smpimpl.h         |    4 +-
 cpukit/score/include/rtems/score/thread.h          |   14 +-
 cpukit/score/src/schedulerdefaulttick.c            |   14 +--
 cpukit/score/src/smp.c                             |   31 +++-
 cpukit/score/src/threadcreateidle.c                |    3 +
 cpukit/score/src/threadinitialize.c                |    8 +-
 cpukit/score/src/threadstart.c                     |    8 +-
 doc/user/conf.t                                    |  119 ++++++++++++--
 testsuites/smptests/Makefile.am                    |    6 +-
 testsuites/smptests/configure.ac                   |    5 +-
 testsuites/smptests/smpfatal04/Makefile.am         |   19 ++
 testsuites/smptests/smpfatal04/init.c              |   71 ++++++++
 testsuites/smptests/smpfatal04/smpfatal04.doc      |   11 ++
 testsuites/smptests/smpfatal04/smpfatal04.scn      |    2 +
 testsuites/smptests/smpfatal05/Makefile.am         |   19 ++
 testsuites/smptests/smpfatal05/init.c              |   90 ++++++++++
 testsuites/smptests/smpfatal05/smpfatal05.doc      |   11 ++
 testsuites/smptests/smpfatal05/smpfatal05.scn      |    2 +
 testsuites/smptests/smpscheduler02/Makefile.am     |   19 ++
 testsuites/smptests/smpscheduler02/init.c          |  181 ++++++++++++++++++++
 .../smptests/smpscheduler02/smpscheduler02.doc     |   12 ++
 .../smptests/smpscheduler02/smpscheduler02.scn     |    2 +
 28 files changed, 870 insertions(+), 58 deletions(-)
 create mode 100644 testsuites/smptests/smpfatal04/Makefile.am
 create mode 100644 testsuites/smptests/smpfatal04/init.c
 create mode 100644 testsuites/smptests/smpfatal04/smpfatal04.doc
 create mode 100644 testsuites/smptests/smpfatal04/smpfatal04.scn
 create mode 100644 testsuites/smptests/smpfatal05/Makefile.am
 create mode 100644 testsuites/smptests/smpfatal05/init.c
 create mode 100644 testsuites/smptests/smpfatal05/smpfatal05.doc
 create mode 100644 testsuites/smptests/smpfatal05/smpfatal05.scn
 create mode 100644 testsuites/smptests/smpscheduler02/Makefile.am
 create mode 100644 testsuites/smptests/smpscheduler02/init.c
 create mode 100644 testsuites/smptests/smpscheduler02/smpscheduler02.doc
 create mode 100644 testsuites/smptests/smpscheduler02/smpscheduler02.scn

diff --git a/cpukit/rtems/src/clocktick.c b/cpukit/rtems/src/clocktick.c
index 1abaa7f..a026b44 100644
--- a/cpukit/rtems/src/clocktick.c
+++ b/cpukit/rtems/src/clocktick.c
@@ -34,7 +34,7 @@ rtems_status_code rtems_clock_tick( void )
 
   _Watchdog_Tickle_ticks();
 
-  _Scheduler_Tick( _Scheduler_Get( NULL ) );
+  _Scheduler_Tick();
 
 #if defined( RTEMS_SMP )
   _Thread_Enable_dispatch();
diff --git a/cpukit/rtems/src/schedulergetprocessorset.c b/cpukit/rtems/src/schedulergetprocessorset.c
index 6fc23f0..b9c8643 100644
--- a/cpukit/rtems/src/schedulergetprocessorset.c
+++ b/cpukit/rtems/src/schedulergetprocessorset.c
@@ -36,12 +36,12 @@ rtems_status_code rtems_scheduler_get_processor_set(
         uint32_t cpu_count = _SMP_Get_processor_count();
         uint32_t cpu_index;
 
-        (void) scheduler;
-
         CPU_ZERO_S( cpusetsize, cpuset );
 
         for ( cpu_index = 0 ; cpu_index < cpu_count ; ++cpu_index ) {
-          CPU_SET_S( (int) cpu_index, cpusetsize, cpuset );
+          if ( _Scheduler_Has_processor_ownership( scheduler, cpu_index ) ) {
+            CPU_SET_S( (int) cpu_index, cpusetsize, cpuset );
+          }
         }
 
         sc = RTEMS_SUCCESSFUL;
diff --git a/cpukit/sapi/include/confdefs.h b/cpukit/sapi/include/confdefs.h
index 5ec0cf2..5a57fbb 100644
--- a/cpukit/sapi/include/confdefs.h
+++ b/cpukit/sapi/include/confdefs.h
@@ -820,6 +820,122 @@ const rtems_libio_helper rtems_fs_init_helper =
   #if defined(RTEMS_SMP)
     const size_t _Scheduler_Count =
       RTEMS_ARRAY_SIZE( _Scheduler_Table );
+
+    const Scheduler_Assignment _Scheduler_Assignments[] = {
+      #if defined(CONFIGURE_SMP_SCHEDULER_ASSIGNMENTS)
+        CONFIGURE_SMP_SCHEDULER_ASSIGNMENTS
+      #else
+        RTEMS_SCHEDULER_ASSIGN(
+          0,
+          RTEMS_SCHEDULER_ASSIGN_PROCESSOR_MANDATORY
+        )
+        #define CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT \
+          RTEMS_SCHEDULER_ASSIGN( \
+            0, \
+            RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL \
+          )
+        #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 2
+          , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+        #endif
+        #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 3
+          , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+        #endif
+        #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 4
+          , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+        #endif
+        #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 5
+          , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+        #endif
+        #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 6
+          , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+        #endif
+        #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 7
+          , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+        #endif
+        #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 8
+          , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+        #endif
+        #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 9
+          , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+        #endif
+        #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 10
+          , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+        #endif
+        #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 11
+          , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+        #endif
+        #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 12
+          , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+        #endif
+        #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 13
+          , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+        #endif
+        #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 14
+          , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+        #endif
+        #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 15
+          , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+        #endif
+        #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 16
+          , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+        #endif
+        #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 17
+          , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+        #endif
+        #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 18
+          , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+        #endif
+        #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 19
+          , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+        #endif
+        #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 20
+          , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+        #endif
+        #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 21
+          , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+        #endif
+        #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 22
+          , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+        #endif
+        #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 23
+          , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+        #endif
+        #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 24
+          , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+        #endif
+        #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 25
+          , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+        #endif
+        #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 26
+          , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+        #endif
+        #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 27
+          , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+        #endif
+        #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 28
+          , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+        #endif
+        #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 29
+          , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+        #endif
+        #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 30
+          , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+        #endif
+        #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 31
+          , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+        #endif
+        #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 32
+          , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+        #endif
+        #undef CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+      #endif
+    };
+
+    RTEMS_STATIC_ASSERT(
+      CONFIGURE_SMP_MAXIMUM_PROCESSORS
+        == RTEMS_ARRAY_SIZE( _Scheduler_Assignments ),
+      _Scheduler_Assignments
+    );
   #endif
 
   #if defined(CONFIGURE_SCHEDULER_EDF)
diff --git a/cpukit/sapi/include/rtems/scheduler.h b/cpukit/sapi/include/rtems/scheduler.h
index 06824e9..f4aff23 100644
--- a/cpukit/sapi/include/rtems/scheduler.h
+++ b/cpukit/sapi/include/rtems/scheduler.h
@@ -26,6 +26,23 @@
 #define RTEMS_SCHEDULER_CONTEXT_NAME( name ) \
   _Configuration_Scheduler_ ## name
 
+#if defined(RTEMS_SMP)
+  #define RTEMS_SCHEDULER_ASSIGN_DEFAULT \
+    SCHEDULER_ASSIGN_DEFAULT
+
+  #define RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL \
+    SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL
+
+  #define RTEMS_SCHEDULER_ASSIGN_PROCESSOR_MANDATORY \
+    SCHEDULER_ASSIGN_PROCESSOR_MANDATORY
+
+  #define RTEMS_SCHEDULER_ASSIGN( index, attr ) \
+    { \
+      &_Scheduler_Table[ ( index ) ], \
+      ( attr ) \
+    }
+#endif
+
 /*
  * This file should be only included in the context of <rtems/confdefs.h>.
  * Define the scheduler configuration macros only in case the corresponding
diff --git a/cpukit/score/include/rtems/score/scheduler.h b/cpukit/score/include/rtems/score/scheduler.h
index 846cd6271..d1df548 100644
--- a/cpukit/score/include/rtems/score/scheduler.h
+++ b/cpukit/score/include/rtems/score/scheduler.h
@@ -102,7 +102,7 @@ typedef struct {
   );
 
   /** perform scheduler update actions required at each clock tick */
-  void ( *tick )( const Scheduler_Control * );
+  void ( *tick )( const Scheduler_Control *, Thread_Control * );
 
   /**
    * @brief Starts the idle thread for a particular processor.
@@ -194,6 +194,55 @@ extern const Scheduler_Control _Scheduler_Table[];
   #define _Scheduler_Count ( (size_t) 1 )
 #endif
 
+#if defined(RTEMS_SMP)
+  /**
+   * @brief The scheduler assignment default attributes.
+   */
+  #define SCHEDULER_ASSIGN_DEFAULT UINT32_C(0x0)
+
+  /**
+   * @brief The presence of this processor is optional.
+   */
+  #define SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL SCHEDULER_ASSIGN_DEFAULT
+
+  /**
+   * @brief The presence of this processor is mandatory.
+   */
+  #define SCHEDULER_ASSIGN_PROCESSOR_MANDATORY UINT32_C(0x1)
+
+  /**
+   * @brief Scheduler assignment.
+   */
+  typedef struct {
+    /**
+     * @brief The scheduler for this processor.
+     */
+    const Scheduler_Control *scheduler;
+
+    /**
+     * @brief The scheduler assignment attributes.
+     *
+     * Use @ref SCHEDULER_ASSIGN_DEFAULT to select default attributes.
+     *
+     * The presence of a processor can be
+     * - @ref SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL, or
+     * - @ref SCHEDULER_ASSIGN_PROCESSOR_MANDATORY.
+     */
+    uint32_t attributes;
+  } Scheduler_Assignment;
+
+  /**
+   * @brief The scheduler assignments.
+   *
+   * The length of this array must be equal to the maximum processors.
+   *
+   * Application provided via <rtems/confdefs.h>.
+   *
+   * @see _Scheduler_Table and rtems_configuration_get_maximum_processors().
+   */
+  extern const Scheduler_Assignment _Scheduler_Assignments[];
+#endif
+
 /**
  * @brief Returns an arbitrary non-NULL value.
  *
@@ -249,8 +298,12 @@ void _Scheduler_default_Release_job(
  * This routine is invoked as part of processing each clock tick.
  *
  * @param[in] scheduler The scheduler.
+ * @param[in] execution An executing thread.
  */
-void _Scheduler_default_Tick( const Scheduler_Control *scheduler );
+void _Scheduler_default_Tick(
+  const Scheduler_Control *scheduler,
+  Thread_Control          *executing
+);
 
 /**
  * @brief Starts an idle thread.
diff --git a/cpukit/score/include/rtems/score/schedulerimpl.h b/cpukit/score/include/rtems/score/schedulerimpl.h
index 7364beb..6d30a23 100644
--- a/cpukit/score/include/rtems/score/schedulerimpl.h
+++ b/cpukit/score/include/rtems/score/schedulerimpl.h
@@ -41,6 +41,15 @@ extern "C" {
  */
 void _Scheduler_Handler_initialization( void );
 
+RTEMS_INLINE_ROUTINE const Scheduler_Control *_Scheduler_Get_by_CPU(
+  const Per_CPU_Control *cpu
+)
+{
+  uint32_t cpu_index = _Per_CPU_Get_index( cpu );
+
+  return _Scheduler_Assignments[ cpu_index ].scheduler;
+}
+
 /**
  * The preferred method to add a new scheduler is to define the jump table
  * entries and add a case to the _Scheduler_Initialize routine.
@@ -234,11 +243,19 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Release_job(
  * scheduler which support standard RTEMS features, this includes
  * time-slicing management.
  */
-RTEMS_INLINE_ROUTINE void _Scheduler_Tick(
-  const Scheduler_Control *scheduler
-)
+RTEMS_INLINE_ROUTINE void _Scheduler_Tick( void )
 {
-  ( *scheduler->Operations.tick )( scheduler );
+  uint32_t cpu_count = _SMP_Get_processor_count();
+  uint32_t cpu_index;
+
+  for ( cpu_index = 0 ; cpu_index < cpu_count ; ++cpu_index ) {
+    const Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index );
+    const Scheduler_Control *scheduler = _Scheduler_Get_by_CPU( cpu );
+
+    if ( scheduler != NULL ) {
+      ( *scheduler->Operations.tick )( scheduler, cpu->executing );
+    }
+  }
 }
 
 /**
@@ -436,9 +453,13 @@ RTEMS_INLINE_ROUTINE const Scheduler_Control *_Scheduler_Get(
   Thread_Control *the_thread
 )
 {
+#if defined(RTEMS_SMP)
+  return the_thread->scheduler;
+#else
   (void) the_thread;
 
   return &_Scheduler_Table[ 0 ];
+#endif
 }
 
 RTEMS_INLINE_ROUTINE bool _Scheduler_Set(
@@ -448,9 +469,16 @@ RTEMS_INLINE_ROUTINE bool _Scheduler_Set(
 {
   bool ok;
 
-  (void) scheduler;
-
   if ( _States_Is_dormant( the_thread->current_state ) ) {
+#if defined(RTEMS_SMP)
+    _Scheduler_Free( _Scheduler_Get( the_thread ), the_thread );
+    the_thread->scheduler = scheduler;
+    _Scheduler_Allocate( scheduler, the_thread );
+    _Scheduler_Update( scheduler, the_thread );
+#else
+    (void) scheduler;
+#endif
+
     ok = true;
   } else {
     ok = false;
@@ -489,6 +517,45 @@ RTEMS_INLINE_ROUTINE uint32_t _Scheduler_Get_index(
   return (uint32_t) (scheduler - &_Scheduler_Table[ 0 ]);
 }
 
+RTEMS_INLINE_ROUTINE const Scheduler_Assignment *_Scheduler_Get_assignment(
+  uint32_t cpu_index
+)
+{
+  return &_Scheduler_Assignments[ cpu_index ];
+}
+
+RTEMS_INLINE_ROUTINE bool _Scheduler_Is_mandatory_processor(
+  const Scheduler_Assignment *assignment
+)
+{
+  return (assignment->attributes & SCHEDULER_ASSIGN_PROCESSOR_MANDATORY) != 0;
+}
+
+RTEMS_INLINE_ROUTINE bool _Scheduler_Should_start_processor(
+  const Scheduler_Assignment *assignment
+)
+{
+  return assignment->scheduler != NULL;
+}
+
+RTEMS_INLINE_ROUTINE bool _Scheduler_Has_processor_ownership(
+  const Scheduler_Control *scheduler,
+  uint32_t cpu_index
+)
+{
+#if defined(RTEMS_SMP)
+  const Scheduler_Assignment *assignment =
+    _Scheduler_Get_assignment( cpu_index );
+
+  return assignment->scheduler == scheduler;
+#else
+  (void) scheduler;
+  (void) cpu_index;
+
+  return true;
+#endif
+}
+
 /** @} */
 
 #ifdef __cplusplus
diff --git a/cpukit/score/include/rtems/score/smpimpl.h b/cpukit/score/include/rtems/score/smpimpl.h
index 962c7f2..0c809ba 100644
--- a/cpukit/score/include/rtems/score/smpimpl.h
+++ b/cpukit/score/include/rtems/score/smpimpl.h
@@ -49,7 +49,9 @@ extern "C" {
 typedef enum {
   SMP_FATAL_SHUTDOWN,
   SMP_FATAL_SHUTDOWN_EARLY,
-  SMP_FATAL_UNABLE_TO_START_PROCESSOR
+  SMP_FATAL_UNABLE_TO_START_PROCESSOR,
+  SMP_FATAL_MANDATORY_PROCESSOR_NOT_PRESENT,
+  SMP_FATAL_BOOT_PROCESSOR_NOT_ASSIGNED_TO_SCHEDULER
 } SMP_Fatal_code;
 
 /**
diff --git a/cpukit/score/include/rtems/score/thread.h b/cpukit/score/include/rtems/score/thread.h
index 61e6bc0..ba254f3 100644
--- a/cpukit/score/include/rtems/score/thread.h
+++ b/cpukit/score/include/rtems/score/thread.h
@@ -33,11 +33,10 @@
 #include <rtems/score/threadq.h>
 #include <rtems/score/watchdog.h>
 
-#ifdef RTEMS_SMP
-#if __RTEMS_HAVE_SYS_CPUSET_H__
-#include <sys/cpuset.h>
-#include <rtems/score/cpuset.h>
-#endif
+#if defined(RTEMS_SMP)
+  #include <rtems/score/cpuset.h>
+
+  struct Scheduler_Control;
 #endif
 
 #ifdef __cplusplus
@@ -533,6 +532,11 @@ struct Thread_Control_struct {
    * _Thread_Kill_zombies().
    */
   volatile bool                         is_executing;
+
+  /**
+   * @brief The scheduler of this thread.
+   */
+  const struct Scheduler_Control       *scheduler;
 #endif
 
 #if __RTEMS_ADA__
diff --git a/cpukit/score/src/schedulerdefaulttick.c b/cpukit/score/src/schedulerdefaulttick.c
index 6e7ed37..98cd05e 100644
--- a/cpukit/score/src/schedulerdefaulttick.c
+++ b/cpukit/score/src/schedulerdefaulttick.c
@@ -24,7 +24,7 @@
 #include <rtems/score/smp.h>
 #include <rtems/config.h>
 
-static void _Scheduler_default_Tick_for_executing(
+void _Scheduler_default_Tick(
   const Scheduler_Control *scheduler,
   Thread_Control          *executing
 )
@@ -83,15 +83,3 @@ static void _Scheduler_default_Tick_for_executing(
     #endif
   }
 }
-
-void _Scheduler_default_Tick( const Scheduler_Control *scheduler )
-{
-  uint32_t processor_count = _SMP_Get_processor_count();
-  uint32_t processor;
-
-  for ( processor = 0 ; processor < processor_count ; ++processor ) {
-    const Per_CPU_Control *per_cpu = _Per_CPU_Get_by_index( processor );
-
-    _Scheduler_default_Tick_for_executing( scheduler, per_cpu->executing );
-  }
-}
diff --git a/cpukit/score/src/smp.c b/cpukit/score/src/smp.c
index 4b585ee..0894c6e 100644
--- a/cpukit/score/src/smp.c
+++ b/cpukit/score/src/smp.c
@@ -20,16 +20,23 @@
 
 #include <rtems/score/smpimpl.h>
 #include <rtems/score/assert.h>
+#include <rtems/score/schedulerimpl.h>
 #include <rtems/score/threaddispatch.h>
 #include <rtems/score/threadimpl.h>
 #include <rtems/config.h>
 
+static void _Scheduler_Fatal( SMP_Fatal_code code )
+{
+  _Terminate( RTEMS_FATAL_SOURCE_SMP, false, code );
+}
+
 void _SMP_Handler_initialize( void )
 {
   uint32_t cpu_max = rtems_configuration_get_maximum_processors();
   uint32_t cpu_self;
   uint32_t cpu_count;
   uint32_t cpu_index;
+  const Scheduler_Assignment *assignment;
 
   for ( cpu_index = 0 ; cpu_index < cpu_max; ++cpu_index ) {
     Per_CPU_Control *per_cpu = _Per_CPU_Get_by_index( cpu_index );
@@ -47,17 +54,27 @@ void _SMP_Handler_initialize( void )
 
   cpu_self = _SMP_Get_current_processor();
 
+  for ( cpu_index = cpu_count ; cpu_index < cpu_max; ++cpu_index ) {
+    assignment = _Scheduler_Get_assignment( cpu_index );
+
+    if ( _Scheduler_Is_mandatory_processor( assignment ) ) {
+      _Scheduler_Fatal( SMP_FATAL_MANDATORY_PROCESSOR_NOT_PRESENT );
+    }
+  }
+
   for ( cpu_index = 0 ; cpu_index < cpu_count; ++cpu_index ) {
+    assignment = _Scheduler_Get_assignment( cpu_index );
+
     if ( cpu_index != cpu_self ) {
-      bool ok = _CPU_SMP_Start_processor( cpu_index );
+      if ( _Scheduler_Should_start_processor( assignment ) ) {
+        bool ok = _CPU_SMP_Start_processor( cpu_index );
 
-      if ( !ok ) {
-        _Terminate(
-          RTEMS_FATAL_SOURCE_SMP,
-          false,
-          SMP_FATAL_UNABLE_TO_START_PROCESSOR
-        );
+        if ( !ok && _Scheduler_Is_mandatory_processor( assignment ) ) {
+          _Scheduler_Fatal( SMP_FATAL_UNABLE_TO_START_PROCESSOR );
+        }
       }
+    } else if ( !_Scheduler_Should_start_processor( assignment ) ) {
+      _Scheduler_Fatal( SMP_FATAL_BOOT_PROCESSOR_NOT_ASSIGNED_TO_SCHEDULER );
     }
   }
 
diff --git a/cpukit/score/src/threadcreateidle.c b/cpukit/score/src/threadcreateidle.c
index e044b92..97604dc 100644
--- a/cpukit/score/src/threadcreateidle.c
+++ b/cpukit/score/src/threadcreateidle.c
@@ -19,6 +19,7 @@
 #endif
 
 #include <rtems/score/threadimpl.h>
+#include <rtems/score/schedulerimpl.h>
 #include <rtems/score/stackimpl.h>
 #include <rtems/config.h>
 
@@ -57,6 +58,8 @@ static void _Thread_Create_idle_for_cpu( Per_CPU_Control *per_cpu )
   per_cpu->heir      =
   per_cpu->executing = idle;
 
+  _Scheduler_Set( _Scheduler_Get_by_CPU( per_cpu ), idle );
+
   _Thread_Start(
     idle,
     THREAD_START_NUMERIC,
diff --git a/cpukit/score/src/threadinitialize.c b/cpukit/score/src/threadinitialize.c
index 153c1d0..6445ba2 100644
--- a/cpukit/score/src/threadinitialize.c
+++ b/cpukit/score/src/threadinitialize.c
@@ -51,6 +51,7 @@ bool _Thread_Initialize(
   size_t                   i;
   bool                     scheduler_allocated = false;
   const Scheduler_Control *scheduler;
+  Per_CPU_Control         *cpu;
 
   /*
    * Do not use _TLS_Size here since this will lead GCC to assume that this
@@ -182,16 +183,20 @@ bool _Thread_Initialize(
     #endif
   }
 
+  cpu = _Per_CPU_Get_snapshot();
+  scheduler = _Scheduler_Get_by_CPU( cpu );
+
   the_thread->Start.isr_level         = isr_level;
 
 #if defined(RTEMS_SMP)
   the_thread->is_scheduled            = false;
   the_thread->is_in_the_air           = false;
   the_thread->is_executing            = false;
+  the_thread->scheduler               = scheduler;
 #endif
 
   /* Initialize the CPU for the non-SMP schedulers */
-  _Thread_Set_CPU( the_thread, _Per_CPU_Get_by_index( 0 ) );
+  _Thread_Set_CPU( the_thread, cpu );
 
   the_thread->current_state           = STATES_DORMANT;
   the_thread->Wait.queue              = NULL;
@@ -199,7 +204,6 @@ bool _Thread_Initialize(
   the_thread->real_priority           = priority;
   the_thread->Start.initial_priority  = priority;
 
-  scheduler = _Scheduler_Get( _Thread_Get_executing() );
   scheduler_allocated = _Scheduler_Allocate( scheduler, the_thread );
   if ( !scheduler_allocated ) {
     goto failed;
diff --git a/cpukit/score/src/threadstart.c b/cpukit/score/src/threadstart.c
index b65a2c3..dda9495 100644
--- a/cpukit/score/src/threadstart.c
+++ b/cpukit/score/src/threadstart.c
@@ -46,8 +46,12 @@ bool _Thread_Start(
     if ( cpu == NULL ) {
       _Thread_Ready( the_thread );
     } else {
-      the_thread->current_state = STATES_READY;
-      _Scheduler_Start_idle( _Scheduler_Get( the_thread ), the_thread, cpu );
+      const Scheduler_Control *scheduler = _Scheduler_Get_by_CPU( cpu );
+
+      if ( scheduler != NULL ) {
+        the_thread->current_state = STATES_READY;
+        _Scheduler_Start_idle( scheduler, the_thread, cpu );
+      }
     }
 
     _User_extensions_Thread_start( the_thread );
diff --git a/doc/user/conf.t b/doc/user/conf.t
index 9b093f8..e3c3f24 100644
--- a/doc/user/conf.t
+++ b/doc/user/conf.t
@@ -3501,7 +3501,7 @@ configuration parameter is redundant.
 
 @subheading DESCRIPTION:
 The Deterministic Priority Scheduler is the default scheduler in RTEMS
-for single core applications and is designed for predictable performance
+for uni-processor applications and is designed for predictable performance
 under the highest loads.  It can block or unblock a thread in a constant
 amount of time.  This scheduler requires a variable amount of memory
 based upon the number of priorities configured in the system.
@@ -3572,7 +3572,7 @@ This is not defined by default.
 
 @subheading DESCRIPTION:
 The Earliest Deadline First Scheduler (EDF) is an alternative scheduler in
-RTEMS for single core applications. The EDF schedules tasks with dynamic
+RTEMS for uni-processor applications. The EDF schedules tasks with dynamic
 priorities equal to deadlines. The deadlines are declared using only
 Rate Monotonic manager which handles periodic behavior.  Period is always
 equal to deadline. If a task does not have any deadline declared or the
@@ -3612,7 +3612,7 @@ This is not defined by default.
 
 @subheading DESCRIPTION:
 The Constant Bandwidth Server Scheduler (CBS) is an alternative scheduler
-in RTEMS for single core applications. The CBS is a budget aware extension
+in RTEMS for uni-processor applications. The CBS is a budget aware extension
 of EDF scheduler. The goal of this scheduler is to ensure temporal
 isolation of tasks. The CBS is equipped with a set of additional rules
 and provides with an extensive API.
@@ -3685,14 +3685,14 @@ This is not defined by default.
 
 @subheading DESCRIPTION:
 The Simple SMP Priority Scheduler is derived from the Simple Priority
-Scheduler but is capable of scheduling threads across multiple cores.
+Scheduler but is capable of scheduling threads across multiple processors.
 It is designed to provide the same task scheduling behaviour as the
 Deterministic Priority Scheduler while distributing threads across
-multiple cores.  Being based upon the Simple Priority Scheduler, it also
+multiple processors.  Being based upon the Simple Priority Scheduler, it also
 maintains a single sorted list of all ready threads.  Thus blocking or
 unblocking a thread is not a constant time operation with this scheduler.
 
-In addition, when allocating threads to cores, the algorithm is not
+In addition, when allocating threads to processors, the algorithm is not
 constant time. This algorithm was not designed with efficiency as a
 primary design goal.  Its primary design goal was to provide an SMP-aware
 scheduling algorithm that is simple to understand.
@@ -3792,6 +3792,99 @@ guidance.  For guidance on the configuration macros, please examine
 Deterministic Priority Scheduler.
 
 @c
+ at c === Configuring Partitioned/Clustered Schedulers ===
+ at c
+ at subsection Configuring Partitioned/Clustered Schedulers
+
+Partitioned/clustered scheduling helps to control the worst-case latencies in
+the system.  The goal is to reduce the amount of shared state in the system and
+thus prevention of lock contention.  Modern multi-processor systems tend to
+have several layers of data and instruction caches.  With partitioned/clustered
+scheduling it is possible to honor the cache topology of a system and thus
+avoid expensive cache synchronization traffic.
+
+The schedulers in an SMP system are statically configured.  First the
+application must select which scheduling algorithms are available with the
+following defines
+
+ at itemize @bullet
+ at item @code{CONFIGURE_SCHEDULER_PRIORITY_SMP},
+ at item @code{CONFIGURE_SCHEDULER_SIMPLE_SMP}, and
+ at item @code{CONFIGURE_SCHEDULER_PRIORITY_AFFINITY_SMP}.
+ at end itemize
+
+After these definitions the configuration file must
+ at code{#include <rtems/scheduler.h>} to have access to scheduler specific
+configuration macros.  Each scheduler needs a context to store state
+information at run-time.  To provide a context for each scheduler is the next
+step.  Use the following macros to create scheduler contexts
+
+ at itemize @bullet
+ at item @code{RTEMS_SCHEDULER_CONTEXT_PRIORITY_SMP},
+ at item @code{RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP}, and
+ at item @code{RTEMS_SCHEDULER_CONTEXT_PRIORITY_AFFINITY_SMP}.
+ at end itemize
+
+The schedulers are registered in the system via the scheduler table.  To create
+the scheduler table define @code{CONFIGURE_SCHEDULER_CONTROLS} to a list of the
+following scheduler control initializers
+
+ at itemize @bullet
+ at item @code{RTEMS_SCHEDULER_CONTROL_PRIORITY_SMP},
+ at item @code{RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP}, and
+ at item @code{RTEMS_SCHEDULER_CONTROL_PRIORITY_AFFINITY_SMP}.
+ at end itemize
+
+The last step is to define which processor uses which scheduler.  For this
+purpose a scheduler assignment table must be defined.  The entry count of this
+table must be equal to the configured maximum processors
+(@code{CONFIGURE_SMP_MAXIMUM_PROCESSORS}).  A processor assignment to a
+scheduler can be optional or mandatory.  The boot processor must have a
+scheduler assigned.  In case the system needs more mandatory processors than
+available then a fatal run-time error will occur.  To specify the scheduler
+assignments define @code{CONFIGURE_SMP_SCHEDULER_ASSIGNMENTS} to a list of
+ at code{RTEMS_SCHEDULER_ASSIGN} macros.
+
+The following example shows a partitioned scheduler configuration for two
+processors.  Each processor is owned by a Deterministic Priority scheduler
+capable to manage 256 priority levels.  The scheduler with index zero has the
+name @code{"BLUE"}.  The scheduler with index one has the name @code{"WOOD"}.
+The scheduler assignments are mandatory, so the system must have at least two
+processors, otherwise a fatal run-time error will occur during system startup.
+
+ at example
+ at group
+#define CONFIGURE_SMP_APPLICATION
+
+#define CONFIGURE_SMP_MAXIMUM_PROCESSORS 2
+
+#define CONFIGURE_MAXIMUM_PRIORITY 255
+
+#define CONFIGURE_SCHEDULER_PRIORITY_SMP
+
+#include <rtems/scheduler.h>
+
+RTEMS_SCHEDULER_CONTEXT_PRIORITY_SMP(a, CONFIGURE_MAXIMUM_PRIORITY + 1);
+
+RTEMS_SCHEDULER_CONTEXT_PRIORITY_SMP(b, CONFIGURE_MAXIMUM_PRIORITY + 1);
+
+#define CONFIGURE_SCHEDULER_CONTROLS \
+  RTEMS_SCHEDULER_CONTROL_PRIORITY_SMP( \
+    a, \
+    rtems_build_name('B', 'L', 'U', 'E') \
+  ), \
+  RTEMS_SCHEDULER_CONTROL_PRIORITY_SMP( \
+    b, \
+    rtems_build_name('W', 'O', 'O', 'D') \
+  )
+
+#define CONFIGURE_SMP_SCHEDULER_ASSIGNMENTS \
+  RTEMS_SCHEDULER_ASSIGN(0, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_MANDATORY), \
+  RTEMS_SCHEDULER_ASSIGN(1, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_MANDATORY)
+ at end group
+ at end example
+
+ at c
 @c === SMP Specific Configuration Parameters ===
 @c
 @section SMP Specific Configuration Parameters
@@ -3804,7 +3897,7 @@ configuration parameters which apply.
 @c
 @c === CONFIGURE_SMP_APPLICATION ===
 @c
- at subsection Specify Application Uses Multiple Cores (is SMP)
+ at subsection Enable SMP Support for Applications
 
 @findex CONFIGURE_SMP_APPLICATION
 
@@ -3819,16 +3912,16 @@ Boolean feature macro.
 Defined or undefined.
 
 @item DEFAULT VALUE:
-The default value is 1, (if CONFIGURE_SMP_APPLICATION is defined).
+This is not defined by default.
 
 @end table
 
 @subheading DESCRIPTION:
- at code{CONFIGURE_SMP_APPLICATION} must be defined if the application is
-to make use of multiple CPU cores in an SMP target system.
+ at code{CONFIGURE_SMP_APPLICATION} must be defined to enable SMP support for the
+application.
 
 @subheading NOTES:
-None.
+This define may go away in the future in case all RTEMS components are SMP ready.
 
 @c
 @c === CONFIGURE_SMP_MAXIMUM_PROCESSORS ===
@@ -3854,10 +3947,10 @@ The default value is 1, (if CONFIGURE_SMP_APPLICATION is defined).
 
 @subheading DESCRIPTION:
 @code{CONFIGURE_SMP_MAXIMUM_PROCESSORS} must be set to the number of
-CPU cores in the SMP configuration.
+processors in the SMP configuration.
 
 @subheading NOTES:
-If there are more cores available than configured, the rest will be
+If there are more processors available than configured, the rest will be
 ignored.
 
 @c
diff --git a/testsuites/smptests/Makefile.am b/testsuites/smptests/Makefile.am
index 82f5322..69cc103 100644
--- a/testsuites/smptests/Makefile.am
+++ b/testsuites/smptests/Makefile.am
@@ -1,8 +1,6 @@
 ACLOCAL_AMFLAGS = -I ../aclocal
 
 SUBDIRS =
-SUBDIRS += smpload01
-
 if SMPTESTS
 SUBDIRS += smp01
 SUBDIRS += smp02
@@ -16,9 +14,13 @@ SUBDIRS += smpatomic01
 SUBDIRS += smpfatal01
 SUBDIRS += smpfatal02
 SUBDIRS += smpfatal03
+SUBDIRS += smpfatal04
+SUBDIRS += smpfatal05
+SUBDIRS += smpload01
 SUBDIRS += smplock01
 SUBDIRS += smpmigration01
 SUBDIRS += smpscheduler01
+SUBDIRS += smpscheduler02
 SUBDIRS += smpsignal01
 SUBDIRS += smpswitchextension01
 SUBDIRS += smpthreadlife01
diff --git a/testsuites/smptests/configure.ac b/testsuites/smptests/configure.ac
index 97b825b..2da93d1 100644
--- a/testsuites/smptests/configure.ac
+++ b/testsuites/smptests/configure.ac
@@ -57,7 +57,6 @@ AM_CONDITIONAL(HAS_CPUSET,test x"${ac_cv_header_sys_cpuset_h}" = x"yes")
 
 # Explicitly list all Makefiles here
 AC_CONFIG_FILES([Makefile
-smpload01/Makefile
 smp01/Makefile
 smp02/Makefile
 smp03/Makefile
@@ -70,12 +69,16 @@ smpatomic01/Makefile
 smpfatal01/Makefile
 smpfatal02/Makefile
 smpfatal03/Makefile
+smpfatal04/Makefile
+smpfatal05/Makefile
+smpload01/Makefile
 smplock01/Makefile
 smpmigration01/Makefile
 smppsxaffinity01/Makefile
 smppsxaffinity02/Makefile
 smppsxsignal01/Makefile
 smpscheduler01/Makefile
+smpscheduler02/Makefile
 smpsignal01/Makefile
 smpswitchextension01/Makefile
 smpthreadlife01/Makefile
diff --git a/testsuites/smptests/smpfatal04/Makefile.am b/testsuites/smptests/smpfatal04/Makefile.am
new file mode 100644
index 0000000..0ee1f36
--- /dev/null
+++ b/testsuites/smptests/smpfatal04/Makefile.am
@@ -0,0 +1,19 @@
+rtems_tests_PROGRAMS = smpfatal04
+smpfatal04_SOURCES = init.c
+
+dist_rtems_tests_DATA = smpfatal04.scn smpfatal04.doc
+
+include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP at .cfg
+include $(top_srcdir)/../automake/compile.am
+include $(top_srcdir)/../automake/leaf.am
+
+AM_CPPFLAGS += -I$(top_srcdir)/../support/include
+
+LINK_OBJS = $(smpfatal04_OBJECTS)
+LINK_LIBS = $(smpfatal04_LDLIBS)
+
+smpfatal04$(EXEEXT): $(smpfatal04_OBJECTS) $(smpfatal04_DEPENDENCIES)
+	@rm -f smpfatal04$(EXEEXT)
+	$(make-exe)
+
+include $(top_srcdir)/../automake/local.am
diff --git a/testsuites/smptests/smpfatal04/init.c b/testsuites/smptests/smpfatal04/init.c
new file mode 100644
index 0000000..7f9f940
--- /dev/null
+++ b/testsuites/smptests/smpfatal04/init.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2014 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.org/license/LICENSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+  #include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/test.h>
+#include <rtems/score/smpimpl.h>
+
+#include <assert.h>
+#include <stdlib.h>
+
+const char rtems_test_name[] = "SMPFATAL 4";
+
+static void Init(rtems_task_argument arg)
+{
+  assert(0);
+}
+
+static void fatal_extension(
+  rtems_fatal_source source,
+  bool is_internal,
+  rtems_fatal_code code
+)
+{
+  rtems_test_begink();
+
+  if (
+    source == RTEMS_FATAL_SOURCE_SMP
+      && !is_internal
+      && code == SMP_FATAL_BOOT_PROCESSOR_NOT_ASSIGNED_TO_SCHEDULER
+  ) {
+    rtems_test_endk();
+  }
+}
+
+#define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+
+#define CONFIGURE_INITIAL_EXTENSIONS \
+  { .fatal = fatal_extension }, \
+  RTEMS_TEST_INITIAL_EXTENSION
+
+#define CONFIGURE_SMP_APPLICATION
+
+#define CONFIGURE_SMP_MAXIMUM_PROCESSORS 1
+
+#define CONFIGURE_SCHEDULER_CONTROLS
+
+#define CONFIGURE_SMP_SCHEDULER_ASSIGNMENTS { NULL, 0 }
+
+#define CONFIGURE_MAXIMUM_TASKS 1
+
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+
+#define CONFIGURE_INIT
+
+#include <rtems/confdefs.h>
diff --git a/testsuites/smptests/smpfatal04/smpfatal04.doc b/testsuites/smptests/smpfatal04/smpfatal04.doc
new file mode 100644
index 0000000..cac6286
--- /dev/null
+++ b/testsuites/smptests/smpfatal04/smpfatal04.doc
@@ -0,0 +1,11 @@
+This file describes the directives and concepts tested by this test set.
+
+test set name: smpfatal04
+
+directives:
+
+  - _SMP_Handler_initialize()
+
+concepts:
+
+  - Ensure that the boot processor has a scheduler assigned.
diff --git a/testsuites/smptests/smpfatal04/smpfatal04.scn b/testsuites/smptests/smpfatal04/smpfatal04.scn
new file mode 100644
index 0000000..d449a9e
--- /dev/null
+++ b/testsuites/smptests/smpfatal04/smpfatal04.scn
@@ -0,0 +1,2 @@
+*** BEGIN OF TEST SMPFATAL 4 ***
+*** END OF TEST SMPFATAL 4 ***
diff --git a/testsuites/smptests/smpfatal05/Makefile.am b/testsuites/smptests/smpfatal05/Makefile.am
new file mode 100644
index 0000000..066498d
--- /dev/null
+++ b/testsuites/smptests/smpfatal05/Makefile.am
@@ -0,0 +1,19 @@
+rtems_tests_PROGRAMS = smpfatal05
+smpfatal05_SOURCES = init.c
+
+dist_rtems_tests_DATA = smpfatal05.scn smpfatal05.doc
+
+include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP at .cfg
+include $(top_srcdir)/../automake/compile.am
+include $(top_srcdir)/../automake/leaf.am
+
+AM_CPPFLAGS += -I$(top_srcdir)/../support/include
+
+LINK_OBJS = $(smpfatal05_OBJECTS)
+LINK_LIBS = $(smpfatal05_LDLIBS)
+
+smpfatal05$(EXEEXT): $(smpfatal05_OBJECTS) $(smpfatal05_DEPENDENCIES)
+	@rm -f smpfatal05$(EXEEXT)
+	$(make-exe)
+
+include $(top_srcdir)/../automake/local.am
diff --git a/testsuites/smptests/smpfatal05/init.c b/testsuites/smptests/smpfatal05/init.c
new file mode 100644
index 0000000..37b3dee
--- /dev/null
+++ b/testsuites/smptests/smpfatal05/init.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2014 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.org/license/LICENSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+  #include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/test.h>
+#include <rtems/score/smpimpl.h>
+
+#include <assert.h>
+#include <stdlib.h>
+
+const char rtems_test_name[] = "SMPFATAL 5";
+
+static void Init(rtems_task_argument arg)
+{
+  assert(0);
+}
+
+static void fatal_extension(
+  rtems_fatal_source source,
+  bool is_internal,
+  rtems_fatal_code code
+)
+{
+  rtems_test_begink();
+
+  if (
+    source == RTEMS_FATAL_SOURCE_SMP
+      && !is_internal
+      && code == SMP_FATAL_MANDATORY_PROCESSOR_NOT_PRESENT
+  ) {
+    rtems_test_endk();
+  }
+}
+
+#define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+
+#define CONFIGURE_INITIAL_EXTENSIONS \
+  { .fatal = fatal_extension }, \
+  RTEMS_TEST_INITIAL_EXTENSION
+
+#define CONFIGURE_SMP_APPLICATION
+
+/* Lets see when the first RTEMS system hits this limit */
+#define CONFIGURE_SMP_MAXIMUM_PROCESSORS 64
+
+#define CONFIGURE_SCHEDULER_SIMPLE_SMP
+
+#include <rtems/scheduler.h>
+
+RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(a);
+
+#define CONFIGURE_SCHEDULER_CONTROLS \
+  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(a, rtems_build_name('S', 'I', 'M', 'P'))
+
+#define ASSIGN \
+  RTEMS_SCHEDULER_ASSIGN(0, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_MANDATORY)
+
+#define CONFIGURE_SMP_SCHEDULER_ASSIGNMENTS \
+ ASSIGN, ASSIGN, ASSIGN, ASSIGN, ASSIGN, ASSIGN, ASSIGN, ASSIGN, \
+ ASSIGN, ASSIGN, ASSIGN, ASSIGN, ASSIGN, ASSIGN, ASSIGN, ASSIGN, \
+ ASSIGN, ASSIGN, ASSIGN, ASSIGN, ASSIGN, ASSIGN, ASSIGN, ASSIGN, \
+ ASSIGN, ASSIGN, ASSIGN, ASSIGN, ASSIGN, ASSIGN, ASSIGN, ASSIGN, \
+ ASSIGN, ASSIGN, ASSIGN, ASSIGN, ASSIGN, ASSIGN, ASSIGN, ASSIGN, \
+ ASSIGN, ASSIGN, ASSIGN, ASSIGN, ASSIGN, ASSIGN, ASSIGN, ASSIGN, \
+ ASSIGN, ASSIGN, ASSIGN, ASSIGN, ASSIGN, ASSIGN, ASSIGN, ASSIGN, \
+ ASSIGN, ASSIGN, ASSIGN, ASSIGN, ASSIGN, ASSIGN, ASSIGN, ASSIGN
+
+#define CONFIGURE_MAXIMUM_TASKS 1
+
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+
+#define CONFIGURE_INIT
+
+#include <rtems/confdefs.h>
diff --git a/testsuites/smptests/smpfatal05/smpfatal05.doc b/testsuites/smptests/smpfatal05/smpfatal05.doc
new file mode 100644
index 0000000..91c37ad
--- /dev/null
+++ b/testsuites/smptests/smpfatal05/smpfatal05.doc
@@ -0,0 +1,11 @@
+This file describes the directives and concepts tested by this test set.
+
+test set name: smpfatal05
+
+directives:
+
+  - _SMP_Handler_initialize()
+
+concepts:
+
+  - Ensure that all mandatory processors are present.
diff --git a/testsuites/smptests/smpfatal05/smpfatal05.scn b/testsuites/smptests/smpfatal05/smpfatal05.scn
new file mode 100644
index 0000000..d3dcb82
--- /dev/null
+++ b/testsuites/smptests/smpfatal05/smpfatal05.scn
@@ -0,0 +1,2 @@
+*** BEGIN OF TEST SMPFATAL 5 ***
+*** END OF TEST SMPFATAL 5 ***
diff --git a/testsuites/smptests/smpscheduler02/Makefile.am b/testsuites/smptests/smpscheduler02/Makefile.am
new file mode 100644
index 0000000..48a7072
--- /dev/null
+++ b/testsuites/smptests/smpscheduler02/Makefile.am
@@ -0,0 +1,19 @@
+rtems_tests_PROGRAMS = smpscheduler02
+smpscheduler02_SOURCES = init.c
+
+dist_rtems_tests_DATA = smpscheduler02.scn smpscheduler02.doc
+
+include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP at .cfg
+include $(top_srcdir)/../automake/compile.am
+include $(top_srcdir)/../automake/leaf.am
+
+AM_CPPFLAGS += -I$(top_srcdir)/../support/include
+
+LINK_OBJS = $(smpscheduler02_OBJECTS)
+LINK_LIBS = $(smpscheduler02_LDLIBS)
+
+smpscheduler02$(EXEEXT): $(smpscheduler02_OBJECTS) $(smpscheduler02_DEPENDENCIES)
+	@rm -f smpscheduler02$(EXEEXT)
+	$(make-exe)
+
+include $(top_srcdir)/../automake/local.am
diff --git a/testsuites/smptests/smpscheduler02/init.c b/testsuites/smptests/smpscheduler02/init.c
new file mode 100644
index 0000000..55cfc6a
--- /dev/null
+++ b/testsuites/smptests/smpscheduler02/init.c
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2014 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.org/license/LICENSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+  #include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/libcsupport.h>
+
+#include "tmacros.h"
+
+const char rtems_test_name[] = "SMPSCHEDULER 2";
+
+#define CPU_COUNT 2
+
+#define SCHED_A rtems_build_name(' ', ' ', ' ', 'A')
+
+#define SCHED_B rtems_build_name(' ', ' ', ' ', 'B')
+
+static rtems_id main_task_id;
+
+static void task(rtems_task_argument arg)
+{
+  rtems_status_code sc;
+
+  (void) arg;
+
+  rtems_test_assert(rtems_get_current_processor() == 1);
+
+  sc = rtems_event_transient_send(main_task_id);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  while (1) {
+    /* Do nothing */
+  }
+}
+
+static void test(void)
+{
+  rtems_status_code sc;
+  rtems_id task_id;
+  rtems_id scheduler_id;
+  rtems_id scheduler_a_id;
+  rtems_id scheduler_b_id;
+  cpu_set_t cpuset;
+  cpu_set_t expected_cpuset;
+
+  main_task_id = rtems_task_self();
+
+  rtems_test_assert(rtems_get_current_processor() == 0);
+
+  sc = rtems_scheduler_ident(SCHED_A, &scheduler_a_id);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  sc = rtems_scheduler_ident(SCHED_B, &scheduler_b_id);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  rtems_test_assert(scheduler_a_id != scheduler_b_id);
+
+  CPU_ZERO(&cpuset);
+  sc = rtems_scheduler_get_processor_set(
+    scheduler_a_id,
+    sizeof(cpuset),
+    &cpuset
+  );
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  CPU_ZERO(&expected_cpuset);
+  CPU_SET(0, &expected_cpuset);
+  rtems_test_assert(CPU_EQUAL(&cpuset, &expected_cpuset));
+
+  CPU_ZERO(&cpuset);
+  sc = rtems_scheduler_get_processor_set(
+    scheduler_b_id,
+    sizeof(cpuset),
+    &cpuset
+  );
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  CPU_ZERO(&expected_cpuset);
+  CPU_SET(1, &expected_cpuset);
+  rtems_test_assert(CPU_EQUAL(&cpuset, &expected_cpuset));
+
+  sc = rtems_task_create(
+    rtems_build_name('T', 'A', 'S', 'K'),
+    1,
+    RTEMS_MINIMUM_STACK_SIZE,
+    RTEMS_DEFAULT_MODES,
+    RTEMS_DEFAULT_ATTRIBUTES,
+    &task_id
+  );
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  sc = rtems_task_get_scheduler(task_id, &scheduler_id);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  rtems_test_assert(scheduler_id == scheduler_a_id);
+
+  sc = rtems_task_set_scheduler(task_id, scheduler_b_id);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  sc = rtems_task_get_scheduler(task_id, &scheduler_id);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  rtems_test_assert(scheduler_id == scheduler_b_id);
+
+  sc = rtems_task_start(task_id, task, 0);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  sc = rtems_task_set_scheduler(task_id, scheduler_a_id);
+  rtems_test_assert(sc == RTEMS_INCORRECT_STATE);
+
+  sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  sc = rtems_task_delete(task_id);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static void Init(rtems_task_argument arg)
+{
+  rtems_resource_snapshot snapshot;
+
+  TEST_BEGIN();
+
+  rtems_resource_snapshot_take(&snapshot);
+
+  test();
+
+  rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
+
+  TEST_END();
+  rtems_test_exit(0);
+}
+
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+
+#define CONFIGURE_SMP_APPLICATION
+
+#define CONFIGURE_SMP_MAXIMUM_PROCESSORS CPU_COUNT
+
+#define CONFIGURE_MAXIMUM_PRIORITY 255
+
+#define CONFIGURE_SCHEDULER_PRIORITY_SMP
+
+#include <rtems/scheduler.h>
+
+RTEMS_SCHEDULER_CONTEXT_PRIORITY_SMP(a, CONFIGURE_MAXIMUM_PRIORITY + 1);
+
+RTEMS_SCHEDULER_CONTEXT_PRIORITY_SMP(b, CONFIGURE_MAXIMUM_PRIORITY + 1);
+
+#define CONFIGURE_SCHEDULER_CONTROLS \
+  RTEMS_SCHEDULER_CONTROL_PRIORITY_SMP(a, SCHED_A), \
+  RTEMS_SCHEDULER_CONTROL_PRIORITY_SMP(b, SCHED_B)
+
+#define CONFIGURE_SMP_SCHEDULER_ASSIGNMENTS \
+  RTEMS_SCHEDULER_ASSIGN(0, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_MANDATORY), \
+  RTEMS_SCHEDULER_ASSIGN(1, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_MANDATORY)
+
+#define CONFIGURE_MAXIMUM_TASKS CPU_COUNT
+
+#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
+
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+
+#define CONFIGURE_INIT
+
+#include <rtems/confdefs.h>
diff --git a/testsuites/smptests/smpscheduler02/smpscheduler02.doc b/testsuites/smptests/smpscheduler02/smpscheduler02.doc
new file mode 100644
index 0000000..13c35c0
--- /dev/null
+++ b/testsuites/smptests/smpscheduler02/smpscheduler02.doc
@@ -0,0 +1,12 @@
+This file describes the directives and concepts tested by this test set.
+
+test set name: smpscheduler02
+
+directives:
+
+  - rtems_task_set_scheduler()
+  - rtems_task_start()
+
+concepts:
+
+  - Ensure that start of a thread for another partition works.
diff --git a/testsuites/smptests/smpscheduler02/smpscheduler02.scn b/testsuites/smptests/smpscheduler02/smpscheduler02.scn
new file mode 100644
index 0000000..47903c4
--- /dev/null
+++ b/testsuites/smptests/smpscheduler02/smpscheduler02.scn
@@ -0,0 +1,2 @@
+*** BEGIN OF TEST SMPSCHEDULER 2 ***
+*** END OF TEST SMPSCHEDULER 2 ***
-- 
1.7.7




More information about the devel mailing list