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

Gedare Bloom gedare at rtems.org
Thu Jun 13 16:30:51 UTC 2013


I don't have time to review this code now. A quick skim left me with
some questions:
* What is the difference between a thread that is "scheduled" and "executing"?
* Should the new fields in the TCB be part of the *scheduler_info for
the SMP scheduler?
* If yes, should we add scheduler hooks in Thread_Dispatch and
Thread_Start_multitasking?
* If no, should we define the new fields whether or not in SMP mode
(at least the is_executing might be useful for debugging purposes)?.

-Gedare

On Wed, Jun 12, 2013 at 11:29 AM, Sebastian Huber
<sebastian.huber at embedded-brains.de> wrote:
> 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
>
> _______________________________________________
> rtems-devel mailing list
> rtems-devel at rtems.org
> http://www.rtems.org/mailman/listinfo/rtems-devel



More information about the devel mailing list