diff options
Diffstat (limited to 'cpukit/score/include')
-rw-r--r-- | cpukit/score/include/rtems/score/percpu.h | 19 | ||||
-rw-r--r-- | cpukit/score/include/rtems/score/scheduler.h | 64 | ||||
-rw-r--r-- | cpukit/score/include/rtems/score/schedulerimpl.h | 176 | ||||
-rw-r--r-- | cpukit/score/include/rtems/score/smpimpl.h | 9 | ||||
-rw-r--r-- | cpukit/score/include/rtems/score/thread.h | 14 | ||||
-rw-r--r-- | cpukit/score/include/rtems/score/threadimpl.h | 1 |
6 files changed, 238 insertions, 45 deletions
diff --git a/cpukit/score/include/rtems/score/percpu.h b/cpukit/score/include/rtems/score/percpu.h index 9a6b1698fb..e491ffa002 100644 --- a/cpukit/score/include/rtems/score/percpu.h +++ b/cpukit/score/include/rtems/score/percpu.h @@ -316,6 +316,12 @@ typedef struct { * @see _Per_CPU_State_change(). */ Per_CPU_State state; + + /** + * @brief Indicates if the processor has been successfully started via + * _CPU_SMP_Start_processor(). + */ + bool started; #endif Per_CPU_Stats Stats; @@ -462,6 +468,19 @@ static inline uint32_t _Per_CPU_Get_index( const Per_CPU_Control *per_cpu ) return ( uint32_t ) ( per_cpu_envelope - &_Per_CPU_Information[ 0 ] ); } +static inline bool _Per_CPU_Is_processor_started( + const Per_CPU_Control *per_cpu +) +{ +#if defined( RTEMS_SMP ) + return per_cpu->started; +#else + (void) per_cpu; + + return true; +#endif +} + #if defined( RTEMS_SMP ) static inline void _Per_CPU_Send_interrupt( const Per_CPU_Control *per_cpu ) diff --git a/cpukit/score/include/rtems/score/scheduler.h b/cpukit/score/include/rtems/score/scheduler.h index 3fd47c78a2..9002ef85d9 100644 --- a/cpukit/score/include/rtems/score/scheduler.h +++ b/cpukit/score/include/rtems/score/scheduler.h @@ -102,7 +102,7 @@ typedef struct { ); /** perform scheduler update actions required at each clock tick */ - void ( *tick )( const Scheduler_Control * ); + void ( *tick )( const Scheduler_Control *, Thread_Control * ); /** * @brief Starts the idle thread for a particular processor. @@ -149,7 +149,12 @@ typedef struct { * this structure at the begin of its context structure. */ typedef struct { - /* No fields yet */ +#if defined(RTEMS_SMP) + /** + * @brief Count of processors owned by this scheduler instance. + */ + uint32_t processor_count; +#endif } Scheduler_Context; /** @@ -198,6 +203,55 @@ extern const Scheduler_Control _Scheduler_Table[]; #define _Scheduler_Count ( (size_t) 1 ) #endif +#if defined(RTEMS_SMP) + /** + * @brief The scheduler assignment default attributes. + */ + #define SCHEDULER_ASSIGN_DEFAULT UINT32_C(0x0) + + /** + * @brief The presence of this processor is optional. + */ + #define SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL SCHEDULER_ASSIGN_DEFAULT + + /** + * @brief The presence of this processor is mandatory. + */ + #define SCHEDULER_ASSIGN_PROCESSOR_MANDATORY UINT32_C(0x1) + + /** + * @brief Scheduler assignment. + */ + typedef struct { + /** + * @brief The scheduler for this processor. + */ + const Scheduler_Control *scheduler; + + /** + * @brief The scheduler assignment attributes. + * + * Use @ref SCHEDULER_ASSIGN_DEFAULT to select default attributes. + * + * The presence of a processor can be + * - @ref SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL, or + * - @ref SCHEDULER_ASSIGN_PROCESSOR_MANDATORY. + */ + uint32_t attributes; + } Scheduler_Assignment; + + /** + * @brief The scheduler assignments. + * + * The length of this array must be equal to the maximum processors. + * + * Application provided via <rtems/confdefs.h>. + * + * @see _Scheduler_Table and rtems_configuration_get_maximum_processors(). + */ + extern const Scheduler_Assignment _Scheduler_Assignments[]; +#endif + /** * @brief Returns an arbitrary non-NULL value. * @@ -253,8 +307,12 @@ void _Scheduler_default_Release_job( * This routine is invoked as part of processing each clock tick. * * @param[in] scheduler The scheduler. + * @param[in] execution An executing thread. */ -void _Scheduler_default_Tick( const Scheduler_Control *scheduler ); +void _Scheduler_default_Tick( + const Scheduler_Control *scheduler, + Thread_Control *executing +); /** * @brief Starts an idle thread. diff --git a/cpukit/score/include/rtems/score/schedulerimpl.h b/cpukit/score/include/rtems/score/schedulerimpl.h index 8b80db78c1..35054dfd3b 100644 --- a/cpukit/score/include/rtems/score/schedulerimpl.h +++ b/cpukit/score/include/rtems/score/schedulerimpl.h @@ -21,6 +21,7 @@ #include <rtems/score/scheduler.h> #include <rtems/score/cpusetimpl.h> +#include <rtems/score/smpimpl.h> #include <rtems/score/threadimpl.h> #ifdef __cplusplus @@ -41,6 +42,28 @@ extern "C" { */ void _Scheduler_Handler_initialization( void ); +RTEMS_INLINE_ROUTINE const Scheduler_Control *_Scheduler_Get_by_CPU_index( + uint32_t cpu_index +) +{ +#if defined(RTEMS_SMP) + return _Scheduler_Assignments[ cpu_index ].scheduler; +#else + (void) cpu_index; + + return &_Scheduler_Table[ 0 ]; +#endif +} + +RTEMS_INLINE_ROUTINE const Scheduler_Control *_Scheduler_Get_by_CPU( + const Per_CPU_Control *cpu +) +{ + uint32_t cpu_index = _Per_CPU_Get_index( cpu ); + + return _Scheduler_Get_by_CPU_index( cpu_index ); +} + /** * The preferred method to add a new scheduler is to define the jump table * entries and add a case to the _Scheduler_Initialize routine. @@ -234,11 +257,19 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Release_job( * scheduler which support standard RTEMS features, this includes * time-slicing management. */ -RTEMS_INLINE_ROUTINE void _Scheduler_Tick( - const Scheduler_Control *scheduler -) +RTEMS_INLINE_ROUTINE void _Scheduler_Tick( void ) { - ( *scheduler->Operations.tick )( scheduler ); + uint32_t cpu_count = _SMP_Get_processor_count(); + uint32_t cpu_index; + + for ( cpu_index = 0 ; cpu_index < cpu_count ; ++cpu_index ) { + const Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index ); + const Scheduler_Control *scheduler = _Scheduler_Get_by_CPU( cpu ); + + if ( scheduler != NULL ) { + ( *scheduler->Operations.tick )( scheduler, cpu->executing ); + } + } } /** @@ -258,6 +289,47 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Start_idle( ( *scheduler->Operations.start_idle )( scheduler, the_thread, cpu ); } +#if defined(RTEMS_SMP) +RTEMS_INLINE_ROUTINE const Scheduler_Assignment *_Scheduler_Get_assignment( + uint32_t cpu_index +) +{ + return &_Scheduler_Assignments[ cpu_index ]; +} + +RTEMS_INLINE_ROUTINE bool _Scheduler_Is_mandatory_processor( + const Scheduler_Assignment *assignment +) +{ + return (assignment->attributes & SCHEDULER_ASSIGN_PROCESSOR_MANDATORY) != 0; +} + +RTEMS_INLINE_ROUTINE bool _Scheduler_Should_start_processor( + const Scheduler_Assignment *assignment +) +{ + return assignment->scheduler != NULL; +} +#endif /* defined(RTEMS_SMP) */ + +RTEMS_INLINE_ROUTINE bool _Scheduler_Has_processor_ownership( + const Scheduler_Control *scheduler, + uint32_t cpu_index +) +{ +#if defined(RTEMS_SMP) + const Scheduler_Assignment *assignment = + _Scheduler_Get_assignment( cpu_index ); + + return assignment->scheduler == scheduler; +#else + (void) scheduler; + (void) cpu_index; + + return true; +#endif +} + #if defined(__RTEMS_HAVE_SYS_CPUSET_H__) RTEMS_INLINE_ROUTINE void _Scheduler_Get_processor_set( @@ -269,12 +341,18 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Get_processor_set( uint32_t cpu_count = _SMP_Get_processor_count(); uint32_t cpu_index; - (void) scheduler; - CPU_ZERO_S( cpusetsize, cpuset ); for ( cpu_index = 0 ; cpu_index < cpu_count ; ++cpu_index ) { +#if defined(RTEMS_SMP) + if ( _Scheduler_Has_processor_ownership( scheduler, cpu_index ) ) { + CPU_SET_S( (int) cpu_index, cpusetsize, cpuset ); + } +#else + (void) scheduler; + CPU_SET_S( (int) cpu_index, cpusetsize, cpuset ); +#endif } } @@ -299,6 +377,44 @@ bool _Scheduler_Get_affinity( cpu_set_t *cpuset ); +RTEMS_INLINE_ROUTINE const Scheduler_Control *_Scheduler_Get( + Thread_Control *the_thread +) +{ +#if defined(RTEMS_SMP) + return the_thread->scheduler; +#else + (void) the_thread; + + return &_Scheduler_Table[ 0 ]; +#endif +} + +RTEMS_INLINE_ROUTINE bool _Scheduler_Set( + const Scheduler_Control *scheduler, + Thread_Control *the_thread +) +{ + bool ok; + + if ( _States_Is_dormant( the_thread->current_state ) ) { +#if defined(RTEMS_SMP) + _Scheduler_Free( _Scheduler_Get( the_thread ), the_thread ); + the_thread->scheduler = scheduler; + _Scheduler_Allocate( scheduler, the_thread ); + _Scheduler_Update( scheduler, the_thread ); +#else + (void) scheduler; +#endif + + ok = true; + } else { + ok = false; + } + + return ok; +} + RTEMS_INLINE_ROUTINE bool _Scheduler_default_Set_affinity_body( const Scheduler_Control *scheduler, Thread_Control *the_thread, @@ -311,22 +427,35 @@ RTEMS_INLINE_ROUTINE bool _Scheduler_default_Set_affinity_body( uint32_t cpu_index; bool ok = true; - (void) scheduler; - (void) the_thread; - for ( cpu_index = 0 ; cpu_index < cpu_count ; ++cpu_index ) { +#if defined(RTEMS_SMP) + const Scheduler_Control *scheduler_of_cpu = + _Scheduler_Get_by_CPU_index( cpu_index ); + + ok = ok + && ( ( CPU_ISSET_S( (int) cpu_index, cpusetsize, cpuset ) + && scheduler == scheduler_of_cpu ) + || ( !CPU_ISSET_S( (int) cpu_index, cpusetsize, cpuset ) + && scheduler != scheduler_of_cpu ) ); +#else + (void) scheduler; + ok = ok && CPU_ISSET_S( (int) cpu_index, cpusetsize, cpuset ); +#endif } for ( ; cpu_index < cpu_max ; ++cpu_index ) { ok = ok && !CPU_ISSET_S( (int) cpu_index, cpusetsize, cpuset ); } + if ( ok ) { + ok = _Scheduler_Set( scheduler, the_thread ); + } + return ok; } bool _Scheduler_Set_affinity( - const Scheduler_Control *scheduler, Thread_Control *the_thread, size_t cpusetsize, const cpu_set_t *cpuset @@ -442,33 +571,6 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Change_priority_if_higher( } } -RTEMS_INLINE_ROUTINE const Scheduler_Control *_Scheduler_Get( - Thread_Control *the_thread -) -{ - (void) the_thread; - - return &_Scheduler_Table[ 0 ]; -} - -RTEMS_INLINE_ROUTINE bool _Scheduler_Set( - const Scheduler_Control *scheduler, - Thread_Control *the_thread -) -{ - bool ok; - - (void) scheduler; - - if ( _States_Is_dormant( the_thread->current_state ) ) { - ok = true; - } else { - ok = false; - } - - return ok; -} - RTEMS_INLINE_ROUTINE Objects_Id _Scheduler_Build_id( uint32_t scheduler_index ) { return _Objects_Build_id( diff --git a/cpukit/score/include/rtems/score/smpimpl.h b/cpukit/score/include/rtems/score/smpimpl.h index 3e808600d3..225da0fde4 100644 --- a/cpukit/score/include/rtems/score/smpimpl.h +++ b/cpukit/score/include/rtems/score/smpimpl.h @@ -49,9 +49,18 @@ extern "C" { typedef enum { SMP_FATAL_SHUTDOWN, SMP_FATAL_SHUTDOWN_EARLY, + SMP_FATAL_BOOT_PROCESSOR_NOT_ASSIGNED_TO_SCHEDULER, + SMP_FATAL_MANDATORY_PROCESSOR_NOT_PRESENT, + SMP_FATAL_MULTITASKING_START_ON_UNASSIGNED_PROCESSOR, + SMP_FATAL_SCHEDULER_WITHOUT_PROCESSORS, SMP_FATAL_START_OF_MANDATORY_PROCESSOR_FAILED } SMP_Fatal_code; +static inline void _SMP_Fatal( SMP_Fatal_code code ) +{ + _Terminate( RTEMS_FATAL_SOURCE_SMP, false, code ); +} + /** * @brief Initialize SMP Handler * diff --git a/cpukit/score/include/rtems/score/thread.h b/cpukit/score/include/rtems/score/thread.h index 77e105bf28..5215d6a8ce 100644 --- a/cpukit/score/include/rtems/score/thread.h +++ b/cpukit/score/include/rtems/score/thread.h @@ -33,13 +33,12 @@ #include <rtems/score/threadq.h> #include <rtems/score/watchdog.h> -#ifdef RTEMS_SMP -#if __RTEMS_HAVE_SYS_CPUSET_H__ -#include <sys/cpuset.h> -#include <rtems/score/cpuset.h> -#endif +#if defined(RTEMS_SMP) + #include <rtems/score/cpuset.h> #endif +struct Scheduler_Control; + #ifdef __cplusplus extern "C" { #endif @@ -517,6 +516,11 @@ struct Thread_Control_struct { * _Thread_Kill_zombies(). */ volatile bool is_executing; + + /** + * @brief The scheduler of this thread. + */ + const struct Scheduler_Control *scheduler; #endif #if __RTEMS_ADA__ diff --git a/cpukit/score/include/rtems/score/threadimpl.h b/cpukit/score/include/rtems/score/threadimpl.h index 41b90e3018..4efc85d8f1 100644 --- a/cpukit/score/include/rtems/score/threadimpl.h +++ b/cpukit/score/include/rtems/score/threadimpl.h @@ -141,6 +141,7 @@ void _Thread_Stack_Free( bool _Thread_Initialize( Objects_Information *information, Thread_Control *the_thread, + const struct Scheduler_Control *scheduler, void *stack_area, size_t stack_size, bool is_fp, |