[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