summaryrefslogtreecommitdiffstats
path: root/cpukit/score/include
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/score/include')
-rw-r--r--cpukit/score/include/rtems/score/percpu.h19
-rw-r--r--cpukit/score/include/rtems/score/scheduler.h64
-rw-r--r--cpukit/score/include/rtems/score/schedulerimpl.h176
-rw-r--r--cpukit/score/include/rtems/score/smpimpl.h9
-rw-r--r--cpukit/score/include/rtems/score/thread.h14
-rw-r--r--cpukit/score/include/rtems/score/threadimpl.h1
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,