[PATCH 11/12] scheduler: New simple SMP scheduler implementation

Sebastian Huber sebastian.huber at embedded-brains.de
Wed Jun 12 15:29:35 UTC 2013


The new Simple SMP Scheduler allocates a processor for the processor
count highest priority ready threads.  The thread priority and position
in the ready chain are the only information to determine the scheduling
decision.  Threads with an allocated processor are in the scheduled
chain.  After initialization the scheduled chain has exactly processor
count nodes.  Each processor has exactly one allocated thread after
initialization.  All enqueue and extract operations may exchange threads
with the scheduled chain.  One thread will be added and another will be
removed.  The scheduled and ready chain is ordered according to the
thread priority order.  The chain insert operations are O(count of ready
threads), thus this scheduler is unsuitable for most real-time
applications.

The thread preempt mode will be ignored.
---
 cpukit/sapi/include/confdefs.h                     |    2 +-
 cpukit/score/Makefile.am                           |    6 +-
 .../score/include/rtems/score/schedulersimplesmp.h |  133 +++++-----
 cpukit/score/include/rtems/score/thread.h          |   10 +
 cpukit/score/src/schedulersimplesmp.c              |  182 +++++++++++++
 cpukit/score/src/schedulersimplesmpblock.c         |   31 ---
 cpukit/score/src/schedulersimplesmpschedule.c      |  271 --------------------
 cpukit/score/src/schedulersimplesmpunblock.c       |   34 ---
 cpukit/score/src/smp.c                             |    3 +
 cpukit/score/src/threaddispatch.c                  |    5 +-
 cpukit/score/src/threadinitialize.c                |    6 +
 cpukit/score/src/threadstartmultitasking.c         |    5 +
 12 files changed, 276 insertions(+), 412 deletions(-)
 create mode 100644 cpukit/score/src/schedulersimplesmp.c
 delete mode 100644 cpukit/score/src/schedulersimplesmpblock.c
 delete mode 100644 cpukit/score/src/schedulersimplesmpschedule.c
 delete mode 100644 cpukit/score/src/schedulersimplesmpunblock.c

diff --git a/cpukit/sapi/include/confdefs.h b/cpukit/sapi/include/confdefs.h
index 2bd1444..bf9f5e8 100644
--- a/cpukit/sapi/include/confdefs.h
+++ b/cpukit/sapi/include/confdefs.h
@@ -683,7 +683,7 @@ const rtems_libio_helper rtems_fs_init_helper =
    * NOTE: This is the same as the Simple Scheduler
    */
   #define CONFIGURE_MEMORY_FOR_SCHEDULER ( \
-    _Configure_From_workspace( sizeof(Chain_Control) ) \
+    _Configure_From_workspace( sizeof( Scheduler_simple_smp_Control ) ) \
   )
   #define CONFIGURE_MEMORY_PER_TASK_FOR_SCHEDULER (0)
 #endif
diff --git a/cpukit/score/Makefile.am b/cpukit/score/Makefile.am
index dc018f0..0795021 100644
--- a/cpukit/score/Makefile.am
+++ b/cpukit/score/Makefile.am
@@ -136,9 +136,9 @@ libscore_a_SOURCES += src/mpci.c src/objectmp.c src/threadmp.c
 endif
 
 if HAS_SMP
-libscore_a_SOURCES += src/isrsmp.c src/smp.c \
-    src/schedulersimplesmpblock.c src/schedulersimplesmpschedule.c \
-    src/schedulersimplesmpunblock.c
+libscore_a_SOURCES += src/isrsmp.c
+libscore_a_SOURCES += src/schedulersimplesmp.c
+libscore_a_SOURCES += src/smp.c
 endif
 
 ## CORE_APIMUTEX_C_FILES
diff --git a/cpukit/score/include/rtems/score/schedulersimplesmp.h b/cpukit/score/include/rtems/score/schedulersimplesmp.h
index baac7b2..ce13c1c 100644
--- a/cpukit/score/include/rtems/score/schedulersimplesmp.h
+++ b/cpukit/score/include/rtems/score/schedulersimplesmp.h
@@ -1,19 +1,16 @@
 /**
- *  @file  rtems/score/schedulersimplesmp.h
+ * @file
  *
- *  @brief Manipulation of Threads on a Simple-Priority-Based Ready Queue
+ * @brief Simple SMP Scheduler API
  *
- *  This include file contains all the constants and structures associated
- *  with the manipulation of threads on a simple-priority-based ready queue.
- *  This implementation is SMP-aware and schedules across multiple cores.
- *
- *  The implementation relies heavily on the Simple Scheduler and
- *  only replaces a few routines from that scheduler.
+ * @ingroup ScoreSchedulerSMP
  */
 
 /*
  *  Copyright (C) 2011 On-Line Applications Research Corporation (OAR).
  *
+ *  Copyright (c) 2013 embedded brains GmbH.
+ *
  *  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.
@@ -22,20 +19,6 @@
 #ifndef _RTEMS_SCORE_SCHEDULERSIMPLE_SMP_H
 #define _RTEMS_SCORE_SCHEDULERSIMPLE_SMP_H
 
-/**
- *  @defgroup ScoreSchedulerSMP Simple SMP Scheduler
- *
- *  @ingroup ScoreScheduler
- *
- *  The Simple SMP Scheduler attempts to faithfully implement the
- *  behaviour of the Deterministic Priority Scheduler while spreading
- *  the threads across multiple cores.  It takes into account thread
- *  priority, preemption, and how long a thread has been executing
- *  on a core as factors.  From an implementation perspective, it
- *  relies heavily on the Simple Priority Scheduler.
- */
-/**@{*/
-
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -45,68 +28,76 @@ extern "C" {
 #include <rtems/score/schedulerpriority.h>
 
 /**
- *  Entry points for Scheduler Simple SMP
+ * @defgroup ScoreSchedulerSMP Simple SMP Scheduler
+ *
+ * @ingroup ScoreScheduler
+ *
+ * The Simple SMP Scheduler allocates a processor for the processor count
+ * highest priority ready threads.  The thread priority and position in the
+ * ready chain are the only information to determine the scheduling decision.
+ * Threads with an allocated processor are in the scheduled chain.  After
+ * initialization the scheduled chain has exactly processor count nodes.  Each
+ * processor has exactly one allocated thread after initialization.  All
+ * enqueue and extract operations may exchange threads with the scheduled
+ * chain.  One thread will be added and another will be removed.  The scheduled
+ * and ready chain is ordered according to the thread priority order.  The
+ * chain insert operations are O(count of ready threads), thus this scheduler
+ * is unsuitable for most real-time applications.
+ *
+ * The thread preempt mode will be ignored.
+ *
+ * @{
+ */
+
+typedef struct {
+  Chain_Control ready;
+  Chain_Control scheduled;
+} Scheduler_simple_smp_Control;
+
+/**
+ * @brief Entry points for the Simple SMP Scheduler.
  */
 #define SCHEDULER_SIMPLE_SMP_ENTRY_POINTS \
   { \
-    _Scheduler_simple_Initialize,         /* initialize entry point */ \
-    _Scheduler_simple_smp_Schedule,       /* schedule entry point */ \
-    _Scheduler_simple_Yield,              /* yield entry point */ \
-    _Scheduler_simple_smp_Block,          /* block entry point */ \
-    _Scheduler_simple_smp_Unblock,        /* unblock entry point */ \
-    _Scheduler_simple_Allocate,           /* allocate entry point */ \
-    _Scheduler_simple_Free,               /* free entry point */ \
-    _Scheduler_simple_Update,             /* update entry point */ \
-    _Scheduler_simple_Enqueue,            /* enqueue entry point */ \
-    _Scheduler_simple_Enqueue_first,      /* enqueue_first entry point */ \
-    _Scheduler_simple_Extract,            /* extract entry point */ \
-    _Scheduler_priority_Priority_compare, /* compares two priorities */ \
-    _Scheduler_priority_Release_job,      /* new period of task */ \
-    _Scheduler_default_Tick               /* tick entry point */ \
+    _Scheduler_simple_smp_Initialize, \
+    _Scheduler_simple_smp_Schedule, \
+    _Scheduler_simple_smp_Yield, \
+    _Scheduler_simple_smp_Extract, \
+    _Scheduler_simple_smp_Enqueue_as_last, \
+    _Scheduler_simple_Allocate, \
+    _Scheduler_simple_Free, \
+    _Scheduler_simple_Update, \
+    _Scheduler_simple_smp_Enqueue_as_last, \
+    _Scheduler_simple_smp_Enqueue_as_first, \
+    _Scheduler_simple_smp_Extract, \
+    _Scheduler_priority_Priority_compare, \
+    _Scheduler_priority_Release_job, \
+    _Scheduler_default_Tick, \
+    _Scheduler_simple_smp_Start_idle \
   }
 
-/**
- *  @brief Allocates ready SMP threads to individual cores in an SMP system.
- *
- *  This routine allocates ready threads to individual cores in an SMP
- *  system.  If the allocation results in a new heir which requires
- *  a dispatch, then the dispatch needed flag for that core is set.
- */
+void _Scheduler_simple_smp_Initialize( void );
+
+void _Scheduler_simple_smp_Enqueue_as_last( Thread_Control *thread );
+
+void _Scheduler_simple_smp_Enqueue_as_first( Thread_Control *thread );
+
+void _Scheduler_simple_smp_Extract( Thread_Control *thread );
+
+void _Scheduler_simple_smp_Yield( Thread_Control *thread );
+
 void _Scheduler_simple_smp_Schedule( void );
 
-/**
- *  @brief Remove SMP @a the_thread from the ready queue.
- *
- *  This routine removes @a the_thread from the scheduling decision,
- *  that is, removes it from the ready queue.  It performs
- *  any necessary scheduling operations including the selection of
- *  a new heir thread.
- *
- *  @param[in] the_thread is the thread that is to be blocked
- */
-void _Scheduler_simple_smp_Block(
-  Thread_Control *the_thread
+void _Scheduler_simple_smp_Start_idle(
+  Thread_Control *thread,
+  Per_CPU_Control *cpu
 );
 
-/**
- *  @brief Adds SMP @a the_thread to the ready queue and updates any
- *  appropriate scheduling variables, for example the heir thread.
- *
- *  This routine adds @a the_thread to the scheduling decision,
- *  that is, adds it to the ready queue and updates any appropriate
- *  scheduling variables, for example the heir thread.
- *
- *  @param[in] the_thread is the thread that is to be unblocked
- */
-void _Scheduler_simple_smp_Unblock(
-  Thread_Control *the_thread
-);
+/** @} */
 
 #ifdef __cplusplus
 }
 #endif
 
-/**@}*/
-
 #endif
 /* end of include file */
diff --git a/cpukit/score/include/rtems/score/thread.h b/cpukit/score/include/rtems/score/thread.h
index 60583a7..4f61251 100644
--- a/cpukit/score/include/rtems/score/thread.h
+++ b/cpukit/score/include/rtems/score/thread.h
@@ -384,6 +384,12 @@ struct Thread_Control_struct {
 #endif
   /** This field is true if the thread is preemptible. */
   bool                                  is_preemptible;
+#if defined(RTEMS_SMP)
+  /** This field is true if the thread is scheduled. */
+  bool                                  is_scheduled;
+  /** This field is true if the thread is executing. */
+  bool                                  is_executing;
+#endif
 #if __RTEMS_ADA__
   /** This field is the GNAT self context pointer. */
   void                                 *rtems_ada_self;
@@ -408,6 +414,10 @@ struct Thread_Control_struct {
   /** This pointer holds per-thread data for the scheduler and ready queue. */
   void                                 *scheduler_info;
 
+#ifdef RTEMS_SMP
+  Per_CPU_Control                      *cpu;
+#endif
+
   /** This field contains information about the starting state of
    *  this thread.
    */
diff --git a/cpukit/score/src/schedulersimplesmp.c b/cpukit/score/src/schedulersimplesmp.c
new file mode 100644
index 0000000..a4831a7
--- /dev/null
+++ b/cpukit/score/src/schedulersimplesmp.c
@@ -0,0 +1,182 @@
+/**
+ * @file
+ *
+ * @brief Simple SMP Scheduler Implementation
+ *
+ * @ingroup ScoreSchedulerSMP
+ */
+
+/*
+ * Copyright (c) 2013 embedded brains GmbH.
+ *
+ * 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/schedulersimplesmp.h>
+
+static Scheduler_simple_smp_Control *_Scheduler_simple_smp_Instance( void )
+{
+  return _Scheduler.information;
+}
+
+void _Scheduler_simple_smp_Initialize( void )
+{
+  Scheduler_simple_smp_Control *self =
+    _Workspace_Allocate_or_fatal_error( sizeof( *self ) );
+
+  _Chain_Initialize_empty( &self->ready );
+  _Chain_Initialize_empty( &self->scheduled );
+
+  _Scheduler.information = self;
+}
+
+static void _Scheduler_simple_smp_Allocate_processor(
+  Thread_Control *scheduled,
+  Thread_Control *victim
+)
+{
+  Per_CPU_Control *cpu_of_scheduled = scheduled->cpu;
+  Per_CPU_Control *cpu_of_victim = victim->cpu;
+  Thread_Control *heir;
+
+  scheduled->is_scheduled = true;
+  victim->is_scheduled = false;
+
+  if ( scheduled->is_executing ) {
+    heir = cpu_of_scheduled->heir;
+    cpu_of_scheduled->heir = scheduled;
+  } else {
+    heir = scheduled;
+  }
+
+  if ( heir != victim ) {
+    heir->cpu = cpu_of_victim;
+    cpu_of_victim->heir = heir;
+    cpu_of_victim->dispatch_necessary = true;
+  }
+}
+
+static void _Scheduler_simple_smp_Move_from_scheduled_to_ready(
+  Chain_Control *ready_chain,
+  Thread_Control *scheduled_to_ready
+)
+{
+  _Chain_Extract_unprotected( &scheduled_to_ready->Object.Node );
+  _Scheduler_simple_Insert_as_first( ready_chain, scheduled_to_ready );
+}
+
+static void _Scheduler_simple_smp_Move_from_ready_to_scheduled(
+  Chain_Control *scheduled_chain,
+  Thread_Control *ready_to_scheduled
+)
+{
+  _Chain_Extract_unprotected( &ready_to_scheduled->Object.Node );
+  _Scheduler_simple_Insert_as_last( scheduled_chain, ready_to_scheduled );
+}
+
+static void _Scheduler_simple_smp_Insert(
+  Chain_Control *chain,
+  Thread_Control *thread,
+  Chain_Node_order order
+)
+{
+  _Chain_Insert_ordered_unprotected( chain, &thread->Object.Node, order );
+}
+
+static void _Scheduler_simple_smp_Enqueue_ordered(
+  Thread_Control *thread,
+  Chain_Node_order order
+)
+{
+  Scheduler_simple_smp_Control *self = _Scheduler_simple_smp_Instance();
+
+  /*
+   * The scheduled chain has exactly processor count nodes after
+   * initialization, thus the lowest priority scheduled thread exists.
+   */
+  Thread_Control *lowest_scheduled =
+    (Thread_Control *) _Chain_Last( &self->scheduled );
+
+  if ( ( *order )( &thread->Object.Node, &lowest_scheduled->Object.Node ) ) {
+    _Scheduler_simple_smp_Allocate_processor( thread, lowest_scheduled );
+
+    _Scheduler_simple_smp_Insert( &self->scheduled, thread, order );
+
+    _Scheduler_simple_smp_Move_from_scheduled_to_ready(
+      &self->ready,
+      lowest_scheduled
+    );
+  } else {
+    _Scheduler_simple_smp_Insert( &self->ready, thread, order );
+  }
+}
+
+void _Scheduler_simple_smp_Enqueue_as_first( Thread_Control *thread )
+{
+  _Scheduler_simple_smp_Enqueue_ordered(
+    thread,
+    _Scheduler_simple_Insert_as_first_order
+  );
+}
+
+void _Scheduler_simple_smp_Enqueue_as_last( Thread_Control *thread )
+{
+  _Scheduler_simple_smp_Enqueue_ordered(
+    thread,
+    _Scheduler_simple_Insert_as_last_order
+  );
+}
+
+void _Scheduler_simple_smp_Extract( Thread_Control *thread )
+{
+  Scheduler_simple_smp_Control *self = _Scheduler_simple_smp_Instance();
+
+  _Chain_Extract_unprotected( &thread->Object.Node );
+
+  if ( thread->is_scheduled ) {
+    Thread_Control *highest_ready =
+      (Thread_Control *) _Chain_First( &self->ready );
+
+    _Scheduler_simple_smp_Allocate_processor( highest_ready, thread );
+
+    _Scheduler_simple_smp_Move_from_ready_to_scheduled(
+      &self->scheduled,
+      highest_ready
+    );
+  }
+}
+
+void _Scheduler_simple_smp_Yield( Thread_Control *thread )
+{
+  ISR_Level level;
+
+  _ISR_Disable( level );
+
+  _Scheduler_simple_smp_Extract( thread );
+  _Scheduler_simple_smp_Enqueue_as_last( thread );
+
+  _ISR_Enable( level );
+}
+
+void _Scheduler_simple_smp_Schedule( void )
+{
+  /* Nothing to do */
+}
+
+void _Scheduler_simple_smp_Start_idle(
+  Thread_Control *thread,
+  Per_CPU_Control *cpu
+)
+{
+  Scheduler_simple_smp_Control *self = _Scheduler_simple_smp_Instance();
+
+  thread->is_scheduled = true;
+  thread->cpu = cpu;
+  _Chain_Append_unprotected( &self->scheduled, &thread->Object.Node );
+}
diff --git a/cpukit/score/src/schedulersimplesmpblock.c b/cpukit/score/src/schedulersimplesmpblock.c
deleted file mode 100644
index 9d6d979..0000000
--- a/cpukit/score/src/schedulersimplesmpblock.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * @file
- *
- * @brief Scheduler Simple Block
- * @ingroup ScoreScheduler
- */
-
-/*
- *  COPYRIGHT (c) 2011.
- *  On-Line Applications Research Corporation (OAR).
- *
- *  The license and distribution terms for this file may be
- *  found in 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/system.h>
-#include <rtems/score/schedulersimplesmp.h>
-
-void _Scheduler_simple_smp_Block(
-  Thread_Control   *the_thread
-)
-{
-  _Scheduler_simple_Extract( the_thread );
-
-  _Scheduler_simple_smp_Schedule();
-}
diff --git a/cpukit/score/src/schedulersimplesmpschedule.c b/cpukit/score/src/schedulersimplesmpschedule.c
deleted file mode 100644
index 471f710..0000000
--- a/cpukit/score/src/schedulersimplesmpschedule.c
+++ /dev/null
@@ -1,271 +0,0 @@
-/**
- *  @file
- *
- *  Scheduler Simple SMP Handler / Schedule
- */
-
-/*
- *  COPYRIGHT (c) 2011- 2012.
- *  On-Line Applications Research Corporation (OAR).
- *
- *  The license and distribution terms for this file may be
- *  found in 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/system.h>
-#include <rtems/score/smp.h>
-#include <rtems/score/schedulersimplesmp.h>
-
-#include <stdio.h>
-
-/*
- *  The following is very useful on the scheduler simulator when debugging
- *  this algorithm.  You are not likely to be able to print like this when
- *  running on a real system.
- *
- *  NOTE: This is NOT using RTEMS_DEBUG because this is not consistency
- *        checking and is VERY VERY noisy.  It is just for debugging
- *        the algorithm.
- */
-#if 0
-#define D(format,...) printk( format, __VA_ARGS__)
-#else
-#define D(format,...)
-#endif
-
-/* Declaration to avoid warnings */
-bool _Scheduler_simple_smp_Assign(
-  Thread_Control *consider
-);
-
-/**
- *  @brief Assign Heir Thread to CPU
- *
- *  This method attempts to find a core for the thread under consideration
- *  (@a consider) to become heir of.  The placement takes into account
- *  priority, preemptibility, and length of time on core.
- *
- *  Combined with the loop in _Scheduler_simple_smp_Schedule, it attempts
- *  to faithfully implement the behaviour of the Deterministic Priority
- *  Scheduler while spreading the threads across multiple cores.
- *
- *  @param[in] consider is the thread under consideration.  This means
- *             that the method is looking for the best core to place it
- *             as heir.
- *
- *  @return This method returns true if it was able to make @a consider
- *          the heir on a core and false otherwise.  When this returns
- *          false, there is no point in attempting to place an heir of
- *          of lower priority.
- */
-bool _Scheduler_simple_smp_Assign(
-  Thread_Control *consider
-)
-{
-  bool            found;       /* have we found a cpu to place it on? */
-  uint32_t        found_cpu;   /* CPU to place this thread */
-  bool            blocked;     /* CPU has blocked thread? */
-  Thread_Control *pheir;       /* heir on found cpu to potentially replace */
-  Thread_Control *h;
-  Thread_Control *e;
-  uint32_t        cpu;
-
-  /*
-   *  Initialize various variables to indicate we have not found
-   *  a potential core for the thread under consideration.
-   */
-  found     = false;
-  blocked   = false;
-  found_cpu = 0;
-  pheir     = NULL;
-
-  for ( cpu=0 ; cpu < _SMP_Processor_count ; cpu++ ) {
-    D( "SCHED CPU=%d consider=0x%08x ASSIGN\n", cpu, consider->Object.id );
-
-    /*
-     *  If the thread under consideration is already executing or
-     *  heir, then we don't have a better option for it.
-     */
-    e = _Per_CPU_Information[cpu].executing;
-    if ( e == consider ) {
-      D( "SCHED CPU=%d Executing=0x%08x considering=0x%08x ASSIGNED\n",
-        cpu, e->Object.id, consider->Object.id );
-      return true;
-    }
-
-    if ( !_States_Is_ready( e->current_state ) ) {
-      pheir     = e;
-      found_cpu = cpu;
-      found     = true;
-      blocked   = true;
-      D( "SCHED CPU=%d PHeir=0x%08x considering=0x%08x BLOCKED\n",
-        cpu, e->Object.id, consider->Object.id );
-      continue;
-    }
-
-    h = _Per_CPU_Information[cpu].heir;
-    if ( h == consider ) {
-      D( "SCHED CPU=%d Heir=0x%08x considering=0x%08x ASSIGNED\n",
-        cpu, h->Object.id, consider->Object.id );
-      return true;
-    }
-
-    if ( blocked )
-      continue;
-
-    /*
-     *  If we haven't found a potential CPU to locate the thread
-     *  under consideration on, we need to consider if this is a
-     *  more important threads first (e.g. priority <).
-     *
-     *  But when a thread changes its priority and ends up at the end of
-     *  the priority group for the new heir, we also need to schedule
-     *  a new heir.  This is the "=" part of the check.
-     */
-    if ( !found ) {
-      if ( consider->current_priority <= h->current_priority ) {
-        pheir     = h;
-        found_cpu = cpu;
-        found     = true;
-        D( "SCHED CPU=%d PHeir=0x%08x considering=0x%08x MAYBE #1\n",
-          cpu, h->Object.id, consider->Object.id );
-      }
-
-      continue;
-    }
-
-    /*
-     *  ASSERTION: (found == true)
-     *
-     *  Past this point, we have found a potential heir and are considering
-     *  whether the thread is better placed on another core. It is desirable
-     *  to preempt the lowest priority thread using time on core and
-     *  preemptibility as additional factors.
-     */
-
-    /*
-     *  If we have found a potential CPU on which to make the
-     *  thread under consideration the heir, then we need to
-     *  check if the current CPU is a more appropriate place
-     *  for this thread to be placed.
-     *
-     *  Check 1: heir of potential CPU is more important
-     *           then heir of current CPU.  We want to
-     *           replace the least important thread possible.
-     */
-    if ( h->current_priority > pheir->current_priority ) {
-      pheir = h;
-      found_cpu = cpu;
-      D( "SCHED CPU=%d PHeir=0x%08x considering=0x%08x MAYBE #2\n",
-        cpu, h->Object.id, consider->Object.id );
-      continue;
-    }
-
-    /*
-     *  If the current heir is more important than the potential
-     *  heir, then we should not consider it further in scheduling.
-     */
-    if ( h->current_priority < pheir->current_priority )
-      continue;
-
-    /*
-     *  ASSERTION: (h->current_priority == pheir->current_priority).
-     *
-     *  Past this point, this means we are considering the length of time
-     *  the thread has spent on the time on the CPU core and if it is
-     *  preemptible.
-     */
-
-    /*
-     *  If heir of potential CPU and of the current CPU are of the SAME
-     *  priority, then which has been running longer?
-     *
-     *           Which CPU has had its executing thread longer?
-     */
-    if ( _Timestamp_Less_than(
-           &_Per_CPU_Information[cpu].time_of_last_context_switch,
-           &_Per_CPU_Information[found_cpu].time_of_last_context_switch
-         ) ) {
-      pheir = h;
-      found_cpu = cpu;
-      D( "SCHED CPU=%d PHeir=0x%08x considering=0x%08x LONGER\n",
-        cpu, h->Object.id, consider->Object.id );
-      continue;
-    }
-
-    /*
-     *  If we are looking at a core with a non-preemptible thread
-     *  for potential placement, then favor a core with a preeemtible
-     *  thread of the same priority.  This should help avoid priority
-     *  inversions and let threads run earlier.
-     */
-    if ( !pheir->is_preemptible && h->is_preemptible ) {
-      D( "SCHED CPU=%d PHeir==0x%08x is NOT PREEMPTIBLE\n", 
-        cpu, pheir->Object.id );
-      pheir = h;
-      found_cpu = cpu;
-      D( "SCHED CPU=%d PHeir=0x%08x considering=0x%08x PREEMPTIBLE\n",
-        cpu, h->Object.id, consider->Object.id );
-      continue;
-
-    }
-  }
-
-  /*
-   *  If we found a cpu to make this thread heir of, then we
-   *  need to consider whether we need a dispatch on that CPU.
-   */
-  if ( found ) {
-    e = _Per_CPU_Information[found_cpu].executing;
-    D( "SCHED CPU=%d executing=0x%08x considering=0x%08x FOUND\n",
-      found_cpu, e->Object.id, consider->Object.id );
-    _Per_CPU_Information[found_cpu].heir = consider;
-    if ( !_States_Is_ready( e->current_state ) ) {
-       D( "SCHED CPU=%d executing not ready dispatch needed\n", found_cpu);
-      _Per_CPU_Information[found_cpu].dispatch_necessary = true;
-    } else if ( consider->current_priority < e->current_priority ) {
-      if ( e->is_preemptible || consider->current_priority == 0 ) {
-         D( "SCHED CPU=%d preempting\n", found_cpu);
-        _Per_CPU_Information[found_cpu].dispatch_necessary = true;
-      }
-    }
-  }
-
-  /*
-   *  Return true to indicate we changed an heir.  This indicates
-   *  scheduling needs to examine more threads.
-   */
-  return found;
-}
-
-/*
- *  Reschedule threads -- select heirs for all cores
- */
-void _Scheduler_simple_smp_Schedule(void)
-{
-  Chain_Control  *c;
-  Chain_Node     *n;
-  Thread_Control *t;
-  uint32_t        cpu;
-
-  c   = (Chain_Control *)_Scheduler.information;
-  cpu = 0;
-
-  /*
-   *  Iterate over the first N (where N is the number of CPU cores) threads
-   *  on the ready chain.  Attempt to assign each as heir on a core.  When
-   *  unable to assign a thread as a new heir, then stop.
-   */
-  for (n = _Chain_First(c); !_Chain_Is_tail(c, n); n = _Chain_Next(n)) {
-    t = (Thread_Control *)n;
-    if ( !_Scheduler_simple_smp_Assign( t ) )
-      break;
-    if ( ++cpu >= _SMP_Processor_count )
-      break;
-  }
-}
diff --git a/cpukit/score/src/schedulersimplesmpunblock.c b/cpukit/score/src/schedulersimplesmpunblock.c
deleted file mode 100644
index ef61d48..0000000
--- a/cpukit/score/src/schedulersimplesmpunblock.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * @file
- *
- * @brief Scheduler Simple SMP Unblock Method
- * @ingroup ScoreScheduler
- */
- 
-/*
- *  COPYRIGHT (c) 2011.
- *  On-Line Applications Research Corporation (OAR).
- *
- *  The license and distribution terms for this file may be
- *  found in 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/system.h>
-#include <rtems/score/schedulersimplesmp.h>
-
-void _Scheduler_simple_smp_Unblock(
-  Thread_Control    *the_thread
-)
-{
-  _Scheduler_simple_Ready_queue_enqueue(the_thread);
-
-  /*
-   *  Evaluate all CPUs and pick heirs
-   */
-  _Scheduler_simple_smp_Schedule();
-}
diff --git a/cpukit/score/src/smp.c b/cpukit/score/src/smp.c
index 4ef538d..5c6516c 100644
--- a/cpukit/score/src/smp.c
+++ b/cpukit/score/src/smp.c
@@ -51,7 +51,10 @@ void rtems_smp_secondary_cpu_initialize( void )
    *  THIS core.
    */
   heir = per_cpu->heir;
+  heir->is_executing = true;
+  per_cpu->executing->is_executing = false;
   per_cpu->executing = heir;
+  per_cpu->dispatch_necessary = false;
 
   /*
    * Threads begin execution in the _Thread_Handler() function.   This function
diff --git a/cpukit/score/src/threaddispatch.c b/cpukit/score/src/threaddispatch.c
index 4856f8e..4cd449d 100644
--- a/cpukit/score/src/threaddispatch.c
+++ b/cpukit/score/src/threaddispatch.c
@@ -94,7 +94,10 @@ void _Thread_Dispatch( void )
   _ISR_Disable( level );
   while ( _Thread_Dispatch_necessary == true ) {
     heir = _Thread_Heir;
-    #ifndef RTEMS_SMP
+    #if defined(RTEMS_SMP)
+      executing->is_executing = false;
+      heir->is_executing = true;
+    #else
       _Thread_Dispatch_set_disable_level( 1 );
     #endif
     _Thread_Dispatch_necessary = false;
diff --git a/cpukit/score/src/threadinitialize.c b/cpukit/score/src/threadinitialize.c
index fb22578..4c40ae8 100644
--- a/cpukit/score/src/threadinitialize.c
+++ b/cpukit/score/src/threadinitialize.c
@@ -180,6 +180,12 @@ bool _Thread_Initialize(
 
   the_thread->Start.isr_level         = isr_level;
 
+#if defined(RTEMS_SMP)
+  the_thread->is_scheduled            = false;
+  the_thread->is_executing            = false;
+  the_thread->cpu                     = NULL;
+#endif
+
   the_thread->current_state           = STATES_DORMANT;
   the_thread->Wait.queue              = NULL;
   the_thread->resource_count          = 0;
diff --git a/cpukit/score/src/threadstartmultitasking.c b/cpukit/score/src/threadstartmultitasking.c
index 32a594b..16d1328 100644
--- a/cpukit/score/src/threadstartmultitasking.c
+++ b/cpukit/score/src/threadstartmultitasking.c
@@ -43,6 +43,11 @@ void _Thread_Start_multitasking( void )
 
   _Thread_Dispatch_necessary = false;
 
+  #if defined(RTEMS_SMP)
+    _Thread_Executing->is_executing = false;
+    _Thread_Heir->is_executing = true;
+  #endif
+
   _Thread_Executing = _Thread_Heir;
 
    /*
-- 
1.7.7




More information about the devel mailing list