summaryrefslogtreecommitdiffstats
path: root/cpukit
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit')
-rw-r--r--cpukit/posix/src/pthreadcreate.c7
-rw-r--r--cpukit/posix/src/pthreadsetaffinitynp.c1
-rw-r--r--cpukit/rtems/src/clocktick.c2
-rw-r--r--cpukit/rtems/src/taskcreate.c2
-rw-r--r--cpukit/rtems/src/tasksetaffinity.c1
-rw-r--r--cpukit/sapi/include/confdefs.h113
-rw-r--r--cpukit/sapi/include/rtems/scheduler.h23
-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
-rw-r--r--cpukit/score/src/percpu.c3
-rw-r--r--cpukit/score/src/schedulerdefaulttick.c14
-rw-r--r--cpukit/score/src/schedulersetaffinity.c31
-rw-r--r--cpukit/score/src/smp.c79
-rw-r--r--cpukit/score/src/threadcreateidle.c6
-rw-r--r--cpukit/score/src/threadinitialize.c4
-rw-r--r--cpukit/score/src/threadstart.c8
20 files changed, 486 insertions, 91 deletions
diff --git a/cpukit/posix/src/pthreadcreate.c b/cpukit/posix/src/pthreadcreate.c
index f85e1efcfd..c448c4253b 100644
--- a/cpukit/posix/src/pthreadcreate.c
+++ b/cpukit/posix/src/pthreadcreate.c
@@ -60,6 +60,7 @@ int pthread_create(
bool is_fp;
bool status;
Thread_Control *the_thread;
+ Thread_Control *executing;
POSIX_API_Control *api;
int schedpolicy = SCHED_RR;
struct sched_param schedparam;
@@ -89,6 +90,8 @@ int pthread_create(
rtems_set_errno_and_return_minus_one( ENOSYS );
#endif
+ executing = _Thread_Get_executing();
+
/*
* P1003.1c/Draft 10, p. 121.
*
@@ -99,7 +102,7 @@ int pthread_create(
*/
switch ( the_attr->inheritsched ) {
case PTHREAD_INHERIT_SCHED:
- api = _Thread_Get_executing()->API_Extensions[ THREAD_API_POSIX ];
+ api = executing->API_Extensions[ THREAD_API_POSIX ];
schedpolicy = api->schedpolicy;
schedparam = api->schedparam;
break;
@@ -176,6 +179,7 @@ int pthread_create(
status = _Thread_Initialize(
&_POSIX_Threads_Information,
the_thread,
+ _Scheduler_Get( executing ),
the_attr->stackaddr,
_POSIX_Threads_Ensure_minimum_stack(the_attr->stacksize),
is_fp,
@@ -194,7 +198,6 @@ int pthread_create(
#if defined(RTEMS_SMP) && __RTEMS_HAVE_SYS_CPUSET_H__
status = _Scheduler_Set_affinity(
- _Scheduler_Get( the_thread ),
the_thread,
the_attr->affinitysetsize,
the_attr->affinityset
diff --git a/cpukit/posix/src/pthreadsetaffinitynp.c b/cpukit/posix/src/pthreadsetaffinitynp.c
index d9df75b8de..711d6dcaeb 100644
--- a/cpukit/posix/src/pthreadsetaffinitynp.c
+++ b/cpukit/posix/src/pthreadsetaffinitynp.c
@@ -48,7 +48,6 @@ int pthread_setaffinity_np(
case OBJECTS_LOCAL:
ok = _Scheduler_Set_affinity(
- _Scheduler_Get( the_thread ),
the_thread,
cpusetsize,
cpuset
diff --git a/cpukit/rtems/src/clocktick.c b/cpukit/rtems/src/clocktick.c
index 1abaa7f20e..a026b44494 100644
--- a/cpukit/rtems/src/clocktick.c
+++ b/cpukit/rtems/src/clocktick.c
@@ -34,7 +34,7 @@ rtems_status_code rtems_clock_tick( void )
_Watchdog_Tickle_ticks();
- _Scheduler_Tick( _Scheduler_Get( NULL ) );
+ _Scheduler_Tick();
#if defined( RTEMS_SMP )
_Thread_Enable_dispatch();
diff --git a/cpukit/rtems/src/taskcreate.c b/cpukit/rtems/src/taskcreate.c
index 35dd37c4e5..65a8d33ff1 100644
--- a/cpukit/rtems/src/taskcreate.c
+++ b/cpukit/rtems/src/taskcreate.c
@@ -23,6 +23,7 @@
#include <rtems/rtems/modesimpl.h>
#include <rtems/rtems/support.h>
#include <rtems/score/apimutex.h>
+#include <rtems/score/schedulerimpl.h>
#include <rtems/score/sysstate.h>
#include <rtems/score/threadimpl.h>
@@ -140,6 +141,7 @@ rtems_status_code rtems_task_create(
status = _Thread_Initialize(
&_RTEMS_tasks_Information,
the_thread,
+ _Scheduler_Get_by_CPU_index( _SMP_Get_current_processor() ),
NULL,
stack_size,
is_fp,
diff --git a/cpukit/rtems/src/tasksetaffinity.c b/cpukit/rtems/src/tasksetaffinity.c
index 6d8def7aca..3294f97639 100644
--- a/cpukit/rtems/src/tasksetaffinity.c
+++ b/cpukit/rtems/src/tasksetaffinity.c
@@ -43,7 +43,6 @@ rtems_status_code rtems_task_set_affinity(
case OBJECTS_LOCAL:
ok = _Scheduler_Set_affinity(
- _Scheduler_Get( the_thread ),
the_thread,
cpusetsize,
cpuset
diff --git a/cpukit/sapi/include/confdefs.h b/cpukit/sapi/include/confdefs.h
index 5ec0cf2516..c8a9d0e3a4 100644
--- a/cpukit/sapi/include/confdefs.h
+++ b/cpukit/sapi/include/confdefs.h
@@ -820,6 +820,119 @@ const rtems_libio_helper rtems_fs_init_helper =
#if defined(RTEMS_SMP)
const size_t _Scheduler_Count =
RTEMS_ARRAY_SIZE( _Scheduler_Table );
+
+ const Scheduler_Assignment _Scheduler_Assignments[] = {
+ #if defined(CONFIGURE_SMP_SCHEDULER_ASSIGNMENTS)
+ CONFIGURE_SMP_SCHEDULER_ASSIGNMENTS
+ #else
+ #define CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT \
+ RTEMS_SCHEDULER_ASSIGN( \
+ 0, \
+ RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL \
+ )
+ CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+ #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 2
+ , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+ #endif
+ #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 3
+ , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+ #endif
+ #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 4
+ , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+ #endif
+ #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 5
+ , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+ #endif
+ #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 6
+ , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+ #endif
+ #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 7
+ , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+ #endif
+ #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 8
+ , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+ #endif
+ #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 9
+ , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+ #endif
+ #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 10
+ , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+ #endif
+ #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 11
+ , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+ #endif
+ #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 12
+ , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+ #endif
+ #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 13
+ , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+ #endif
+ #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 14
+ , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+ #endif
+ #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 15
+ , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+ #endif
+ #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 16
+ , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+ #endif
+ #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 17
+ , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+ #endif
+ #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 18
+ , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+ #endif
+ #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 19
+ , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+ #endif
+ #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 20
+ , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+ #endif
+ #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 21
+ , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+ #endif
+ #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 22
+ , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+ #endif
+ #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 23
+ , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+ #endif
+ #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 24
+ , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+ #endif
+ #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 25
+ , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+ #endif
+ #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 26
+ , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+ #endif
+ #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 27
+ , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+ #endif
+ #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 28
+ , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+ #endif
+ #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 29
+ , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+ #endif
+ #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 30
+ , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+ #endif
+ #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 31
+ , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+ #endif
+ #if CONFIGURE_SMP_MAXIMUM_PROCESSORS >= 32
+ , CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+ #endif
+ #undef CONFIGURE_SMP_SCHEDULER_ASSIGN_OPT
+ #endif
+ };
+
+ RTEMS_STATIC_ASSERT(
+ CONFIGURE_SMP_MAXIMUM_PROCESSORS
+ == RTEMS_ARRAY_SIZE( _Scheduler_Assignments ),
+ _Scheduler_Assignments
+ );
#endif
#if defined(CONFIGURE_SCHEDULER_EDF)
diff --git a/cpukit/sapi/include/rtems/scheduler.h b/cpukit/sapi/include/rtems/scheduler.h
index 06824e9370..ce5455925f 100644
--- a/cpukit/sapi/include/rtems/scheduler.h
+++ b/cpukit/sapi/include/rtems/scheduler.h
@@ -26,6 +26,29 @@
#define RTEMS_SCHEDULER_CONTEXT_NAME( name ) \
_Configuration_Scheduler_ ## name
+#if defined(RTEMS_SMP)
+ /* This object doesn't exist and indicates a configuration error */
+ extern const Scheduler_Control RTEMS_SCHEDULER_INVALID_INDEX;
+
+ #define RTEMS_SCHEDULER_ASSIGN_DEFAULT \
+ SCHEDULER_ASSIGN_DEFAULT
+
+ #define RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL \
+ SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL
+
+ #define RTEMS_SCHEDULER_ASSIGN_PROCESSOR_MANDATORY \
+ SCHEDULER_ASSIGN_PROCESSOR_MANDATORY
+
+ #define RTEMS_SCHEDULER_ASSIGN( index, attr ) \
+ { \
+ ( index ) < RTEMS_ARRAY_SIZE( _Scheduler_Table ) ? \
+ &_Scheduler_Table[ ( index ) ] : &RTEMS_SCHEDULER_INVALID_INDEX, \
+ ( attr ) \
+ }
+
+ #define RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER { NULL, 0 }
+#endif
+
/*
* This file should be only included in the context of <rtems/confdefs.h>.
* Define the scheduler configuration macros only in case the corresponding
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,
diff --git a/cpukit/score/src/percpu.c b/cpukit/score/src/percpu.c
index cb9a470990..c396ace6c9 100644
--- a/cpukit/score/src/percpu.c
+++ b/cpukit/score/src/percpu.c
@@ -22,7 +22,6 @@
#include <rtems/score/assert.h>
#include <rtems/score/smpimpl.h>
#include <rtems/config.h>
-#include <rtems/fatal.h>
#if defined(RTEMS_SMP)
@@ -154,7 +153,7 @@ void _Per_CPU_State_change(
next_state == PER_CPU_STATE_SHUTDOWN
&& new_state != PER_CPU_STATE_SHUTDOWN
) {
- rtems_fatal( RTEMS_FATAL_SOURCE_SMP, SMP_FATAL_SHUTDOWN );
+ _SMP_Fatal( SMP_FATAL_SHUTDOWN );
}
}
diff --git a/cpukit/score/src/schedulerdefaulttick.c b/cpukit/score/src/schedulerdefaulttick.c
index 6e7ed376e3..98cd05e1c0 100644
--- a/cpukit/score/src/schedulerdefaulttick.c
+++ b/cpukit/score/src/schedulerdefaulttick.c
@@ -24,7 +24,7 @@
#include <rtems/score/smp.h>
#include <rtems/config.h>
-static void _Scheduler_default_Tick_for_executing(
+void _Scheduler_default_Tick(
const Scheduler_Control *scheduler,
Thread_Control *executing
)
@@ -83,15 +83,3 @@ static void _Scheduler_default_Tick_for_executing(
#endif
}
}
-
-void _Scheduler_default_Tick( const Scheduler_Control *scheduler )
-{
- uint32_t processor_count = _SMP_Get_processor_count();
- uint32_t processor;
-
- for ( processor = 0 ; processor < processor_count ; ++processor ) {
- const Per_CPU_Control *per_cpu = _Per_CPU_Get_by_index( processor );
-
- _Scheduler_default_Tick_for_executing( scheduler, per_cpu->executing );
- }
-}
diff --git a/cpukit/score/src/schedulersetaffinity.c b/cpukit/score/src/schedulersetaffinity.c
index 2416a195c5..a20888b617 100644
--- a/cpukit/score/src/schedulersetaffinity.c
+++ b/cpukit/score/src/schedulersetaffinity.c
@@ -21,7 +21,6 @@
#if defined(__RTEMS_HAVE_SYS_CPUSET_H__)
bool _Scheduler_Set_affinity(
- const Scheduler_Control *scheduler,
Thread_Control *the_thread,
size_t cpusetsize,
const cpu_set_t *cpuset
@@ -31,15 +30,31 @@ bool _Scheduler_Set_affinity(
if ( _CPU_set_Is_large_enough( cpusetsize ) ) {
#if defined(RTEMS_SMP)
- ok = ( *scheduler->Operations.set_affinity )(
- scheduler,
- the_thread,
- cpusetsize,
- cpuset
- );
+ uint32_t cpu_count = _SMP_Get_processor_count();
+ uint32_t cpu_index;
+
+ ok = false;
+
+ for ( cpu_index = 0 ; cpu_index < cpu_count ; ++cpu_index ) {
+ if ( CPU_ISSET_S( (int) cpu_index, cpusetsize, cpuset ) ) {
+ const Scheduler_Control *scheduler_of_cpu =
+ _Scheduler_Get_by_CPU_index( cpu_index );
+
+ if ( scheduler_of_cpu != NULL ) {
+ ok = ( *scheduler_of_cpu->Operations.set_affinity )(
+ scheduler_of_cpu,
+ the_thread,
+ cpusetsize,
+ cpuset
+ );
+ }
+
+ break;
+ }
+ }
#else
ok = _Scheduler_default_Set_affinity_body(
- scheduler,
+ _Scheduler_Get( the_thread ),
the_thread,
cpusetsize,
cpuset
diff --git a/cpukit/score/src/smp.c b/cpukit/score/src/smp.c
index 08677d83c7..6df72070ec 100644
--- a/cpukit/score/src/smp.c
+++ b/cpukit/score/src/smp.c
@@ -20,14 +20,68 @@
#include <rtems/score/smpimpl.h>
#include <rtems/score/assert.h>
+#include <rtems/score/schedulerimpl.h>
#include <rtems/score/threaddispatch.h>
#include <rtems/score/threadimpl.h>
#include <rtems/config.h>
+static void _SMP_Check_scheduler_configuration( void )
+{
+ size_t n = _Scheduler_Count;
+ size_t i;
+
+ for ( i = 0 ; i < n ; ++i ) {
+ const Scheduler_Control *scheduler = &_Scheduler_Table[ i ];
+
+ if ( scheduler->context->processor_count == 0 ) {
+ _SMP_Fatal( SMP_FATAL_SCHEDULER_WITHOUT_PROCESSORS );
+ }
+ }
+}
+
+static void _SMP_Start_processors( uint32_t cpu_count )
+{
+ uint32_t cpu_self = _SMP_Get_current_processor();
+ uint32_t cpu_index;
+
+
+ for ( cpu_index = 0 ; cpu_index < cpu_count; ++cpu_index ) {
+ const Scheduler_Assignment *assignment =
+ _Scheduler_Get_assignment( cpu_index );
+ Per_CPU_Control *per_cpu = _Per_CPU_Get_by_index( cpu_index );
+ bool started;
+
+ if ( cpu_index != cpu_self ) {
+ if ( _Scheduler_Should_start_processor( assignment ) ) {
+ started = _CPU_SMP_Start_processor( cpu_index );
+
+ if ( !started && _Scheduler_Is_mandatory_processor( assignment ) ) {
+ _SMP_Fatal( SMP_FATAL_START_OF_MANDATORY_PROCESSOR_FAILED );
+ }
+ } else {
+ started = false;
+ }
+ } else {
+ started = true;
+
+ if ( !_Scheduler_Should_start_processor( assignment ) ) {
+ _SMP_Fatal( SMP_FATAL_BOOT_PROCESSOR_NOT_ASSIGNED_TO_SCHEDULER );
+ }
+ }
+
+ per_cpu->started = started;
+
+ if ( started ) {
+ ++assignment->scheduler->context->processor_count;
+ }
+ }
+
+ _SMP_Check_scheduler_configuration();
+}
+
void _SMP_Handler_initialize( void )
{
uint32_t cpu_max = rtems_configuration_get_maximum_processors();
- uint32_t cpu_self;
uint32_t cpu_count;
uint32_t cpu_index;
@@ -45,22 +99,17 @@ void _SMP_Handler_initialize( void )
cpu_count = cpu_count < cpu_max ? cpu_count : cpu_max;
_SMP_Processor_count = cpu_count;
- cpu_self = _SMP_Get_current_processor();
+ for ( cpu_index = cpu_count ; cpu_index < cpu_max; ++cpu_index ) {
+ const Scheduler_Assignment *assignment =
+ _Scheduler_Get_assignment( cpu_index );
- for ( cpu_index = 0 ; cpu_index < cpu_count; ++cpu_index ) {
- if ( cpu_index != cpu_self ) {
- bool ok = _CPU_SMP_Start_processor( cpu_index );
-
- if ( !ok ) {
- _Terminate(
- RTEMS_FATAL_SOURCE_SMP,
- false,
- SMP_FATAL_START_OF_MANDATORY_PROCESSOR_FAILED
- );
- }
+ if ( _Scheduler_Is_mandatory_processor( assignment ) ) {
+ _SMP_Fatal( SMP_FATAL_MANDATORY_PROCESSOR_NOT_PRESENT );
}
}
+ _SMP_Start_processors( cpu_count );
+
_CPU_SMP_Finalize_initialization( cpu_count );
}
@@ -83,6 +132,10 @@ void _SMP_Start_multitasking_on_secondary_processor( void )
{
Per_CPU_Control *self_cpu = _Per_CPU_Get();
+ if ( !_Per_CPU_Is_processor_started( self_cpu ) ) {
+ _SMP_Fatal( SMP_FATAL_MULTITASKING_START_ON_UNASSIGNED_PROCESSOR );
+ }
+
_Per_CPU_State_change( self_cpu, PER_CPU_STATE_READY_TO_START_MULTITASKING );
_Thread_Start_multitasking();
diff --git a/cpukit/score/src/threadcreateidle.c b/cpukit/score/src/threadcreateidle.c
index e044b92905..2a242658a5 100644
--- a/cpukit/score/src/threadcreateidle.c
+++ b/cpukit/score/src/threadcreateidle.c
@@ -19,6 +19,7 @@
#endif
#include <rtems/score/threadimpl.h>
+#include <rtems/score/schedulerimpl.h>
#include <rtems/score/stackimpl.h>
#include <rtems/config.h>
@@ -39,6 +40,7 @@ static void _Thread_Create_idle_for_cpu( Per_CPU_Control *per_cpu )
_Thread_Initialize(
&_Thread_Internal_information,
idle,
+ _Scheduler_Get_by_CPU( per_cpu ),
NULL, /* allocate the stack */
_Stack_Ensure_minimum( rtems_configuration_get_idle_task_stack_size() ),
CPU_IDLE_TASK_IS_FP,
@@ -75,6 +77,8 @@ void _Thread_Create_idle( void )
for ( processor = 0 ; processor < processor_count ; ++processor ) {
Per_CPU_Control *per_cpu = _Per_CPU_Get_by_index( processor );
- _Thread_Create_idle_for_cpu( per_cpu );
+ if ( _Per_CPU_Is_processor_started( per_cpu ) ) {
+ _Thread_Create_idle_for_cpu( per_cpu );
+ }
}
}
diff --git a/cpukit/score/src/threadinitialize.c b/cpukit/score/src/threadinitialize.c
index 153c1d0b13..f8e0e7d440 100644
--- a/cpukit/score/src/threadinitialize.c
+++ b/cpukit/score/src/threadinitialize.c
@@ -31,6 +31,7 @@
bool _Thread_Initialize(
Objects_Information *information,
Thread_Control *the_thread,
+ const Scheduler_Control *scheduler,
void *stack_area,
size_t stack_size,
bool is_fp,
@@ -50,7 +51,6 @@ bool _Thread_Initialize(
bool extension_status;
size_t i;
bool scheduler_allocated = false;
- const Scheduler_Control *scheduler;
/*
* Do not use _TLS_Size here since this will lead GCC to assume that this
@@ -188,6 +188,7 @@ bool _Thread_Initialize(
the_thread->is_scheduled = false;
the_thread->is_in_the_air = false;
the_thread->is_executing = false;
+ the_thread->scheduler = scheduler;
#endif
/* Initialize the CPU for the non-SMP schedulers */
@@ -199,7 +200,6 @@ bool _Thread_Initialize(
the_thread->real_priority = priority;
the_thread->Start.initial_priority = priority;
- scheduler = _Scheduler_Get( _Thread_Get_executing() );
scheduler_allocated = _Scheduler_Allocate( scheduler, the_thread );
if ( !scheduler_allocated ) {
goto failed;
diff --git a/cpukit/score/src/threadstart.c b/cpukit/score/src/threadstart.c
index b65a2c3380..dda9495a35 100644
--- a/cpukit/score/src/threadstart.c
+++ b/cpukit/score/src/threadstart.c
@@ -46,8 +46,12 @@ bool _Thread_Start(
if ( cpu == NULL ) {
_Thread_Ready( the_thread );
} else {
- the_thread->current_state = STATES_READY;
- _Scheduler_Start_idle( _Scheduler_Get( the_thread ), the_thread, cpu );
+ const Scheduler_Control *scheduler = _Scheduler_Get_by_CPU( cpu );
+
+ if ( scheduler != NULL ) {
+ the_thread->current_state = STATES_READY;
+ _Scheduler_Start_idle( scheduler, the_thread, cpu );
+ }
}
_User_extensions_Thread_start( the_thread );