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 <[email protected]> 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 > [email protected] > http://www.rtems.org/mailman/listinfo/rtems-devel _______________________________________________ rtems-devel mailing list [email protected] http://www.rtems.org/mailman/listinfo/rtems-devel
