File indexing completed on 2025-05-11 08:24:27
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043 #ifdef HAVE_CONFIG_H
0044 #include "config.h"
0045 #endif
0046
0047 #include <rtems/score/smpimpl.h>
0048 #include <rtems/score/assert.h>
0049 #include <rtems/score/schedulerimpl.h>
0050 #include <rtems/score/threadimpl.h>
0051 #include <rtems/config.h>
0052
0053 #if CPU_USE_DEFERRED_FP_SWITCH == TRUE
0054 #error "deferred FP switch not implemented for SMP"
0055 #endif
0056
0057
0058
0059
0060
0061
0062
0063
0064 static Atomic_Uint _SMP_Ready_to_start_multitasking;
0065
0066 Processor_mask _SMP_Online_processors;
0067
0068 uint32_t _SMP_Processor_maximum;
0069
0070 static const Scheduler_Assignment *_Scheduler_Get_initial_assignment(
0071 uint32_t cpu_index
0072 )
0073 {
0074 return &_Scheduler_Initial_assignments[ cpu_index ];
0075 }
0076
0077 static bool _Scheduler_Is_mandatory_processor(
0078 const Scheduler_Assignment *assignment
0079 )
0080 {
0081 return (assignment->attributes & SCHEDULER_ASSIGN_PROCESSOR_MANDATORY) != 0;
0082 }
0083
0084 static bool _Scheduler_Should_start_processor(
0085 const Scheduler_Assignment *assignment
0086 )
0087 {
0088 return assignment->scheduler != NULL;
0089 }
0090
0091 static void _SMP_Start_processors( uint32_t cpu_max )
0092 {
0093 Per_CPU_Control *cpu_self;
0094 uint32_t cpu_index;
0095
0096 cpu_self = _Per_CPU_Get();
0097 cpu_self->boot = true;
0098 cpu_self->online = true;
0099
0100 for ( cpu_index = 0 ; cpu_index < cpu_max; ++cpu_index ) {
0101 const Scheduler_Assignment *assignment;
0102 Per_CPU_Control *cpu;
0103 bool started;
0104
0105 assignment = _Scheduler_Get_initial_assignment( cpu_index );
0106 cpu = _Per_CPU_Get_by_index( cpu_index );
0107
0108 if ( cpu != cpu_self ) {
0109 if ( _Scheduler_Should_start_processor( assignment ) ) {
0110 started = _CPU_SMP_Start_processor( cpu_index );
0111
0112 if ( !started && _Scheduler_Is_mandatory_processor( assignment ) ) {
0113 _SMP_Fatal( SMP_FATAL_START_OF_MANDATORY_PROCESSOR_FAILED );
0114 }
0115 } else {
0116 started = false;
0117 }
0118
0119 cpu->online = started;
0120 } else {
0121 if ( !_Scheduler_Should_start_processor( assignment ) ) {
0122 _SMP_Fatal( SMP_FATAL_BOOT_PROCESSOR_NOT_ASSIGNED_TO_SCHEDULER );
0123 }
0124
0125 started = true;
0126 }
0127
0128 if ( started ) {
0129 const Scheduler_Control *scheduler;
0130 Scheduler_Context *context;
0131
0132 scheduler = assignment->scheduler;
0133 context = _Scheduler_Get_context( scheduler );
0134
0135 _Processor_mask_Set( &_SMP_Online_processors, cpu_index );
0136 _Processor_mask_Set( &context->Processors, cpu_index );
0137 cpu->Scheduler.control = scheduler;
0138 cpu->Scheduler.context = context;
0139 }
0140 }
0141 }
0142
0143 void _SMP_Handler_initialize( void )
0144 {
0145 uint32_t cpu_config_max;
0146 uint32_t cpu_max;
0147 uint32_t cpu_index;
0148
0149 cpu_config_max = rtems_configuration_get_maximum_processors();
0150
0151 for ( cpu_index = 0 ; cpu_index < cpu_config_max; ++cpu_index ) {
0152 Per_CPU_Control *cpu;
0153
0154 cpu = _Per_CPU_Get_by_index( cpu_index );
0155 _ISR_lock_Set_name( &cpu->Lock, "Per-CPU" );
0156 _ISR_lock_Set_name( &cpu->Jobs.Lock, "Per-CPU Jobs" );
0157 _ISR_lock_Set_name( &cpu->Watchdog.Lock, "Per-CPU Watchdog" );
0158 _Chain_Initialize_empty( &cpu->Threads_in_need_for_help );
0159 }
0160
0161
0162
0163
0164
0165 cpu_max = _CPU_SMP_Initialize();
0166 cpu_max = cpu_max < cpu_config_max ? cpu_max : cpu_config_max;
0167 _SMP_Processor_maximum = cpu_max;
0168
0169 for ( cpu_index = cpu_max ; cpu_index < cpu_config_max; ++cpu_index ) {
0170 const Scheduler_Assignment *assignment;
0171
0172 assignment = _Scheduler_Get_initial_assignment( cpu_index );
0173
0174 if ( _Scheduler_Is_mandatory_processor( assignment ) ) {
0175 _SMP_Fatal( SMP_FATAL_MANDATORY_PROCESSOR_NOT_PRESENT );
0176 }
0177 }
0178
0179 _SMP_Start_processors( cpu_max );
0180
0181 _CPU_SMP_Finalize_initialization( cpu_max );
0182 }
0183
0184 void _SMP_Wait_for_ready_to_start_multitasking( void )
0185 {
0186 Per_CPU_Control *cpu_self;
0187 uint32_t cpu_max;
0188 uint32_t cpu_index;
0189
0190 cpu_max = _SMP_Get_processor_maximum();
0191 cpu_self = _Per_CPU_Get();
0192
0193 for ( cpu_index = 0 ; cpu_index < cpu_max ; ++cpu_index ) {
0194 Per_CPU_Control *cpu;
0195
0196 cpu = _Per_CPU_Get_by_index( cpu_index );
0197
0198 if ( cpu != cpu_self && _Per_CPU_Is_processor_online( cpu ) ) {
0199 while (
0200 _Per_CPU_Get_state( cpu ) != PER_CPU_STATE_READY_TO_START_MULTITASKING
0201 ) {
0202 _SMP_Try_to_process_message(
0203 cpu_self,
0204 _Atomic_Load_ulong( &cpu_self->message, ATOMIC_ORDER_RELAXED )
0205 );
0206 }
0207 }
0208 }
0209 }
0210
0211 void _SMP_Request_start_multitasking( void )
0212 {
0213 _SMP_Wait_for_ready_to_start_multitasking();
0214 _Atomic_Store_uint(
0215 &_SMP_Ready_to_start_multitasking,
0216 1U,
0217 ATOMIC_ORDER_RELEASE
0218 );
0219 }
0220
0221 bool _SMP_Should_start_processor( uint32_t cpu_index )
0222 {
0223 const Scheduler_Assignment *assignment;
0224
0225 assignment = _Scheduler_Get_initial_assignment( cpu_index );
0226 return _Scheduler_Should_start_processor( assignment );
0227 }
0228
0229 static void _SMP_Wait_for_start_multitasking( Per_CPU_Control *cpu_self )
0230 {
0231 unsigned int ready;
0232
0233 do {
0234 _SMP_Try_to_process_message(
0235 cpu_self,
0236 _Atomic_Load_ulong( &cpu_self->message, ATOMIC_ORDER_RELAXED )
0237 );
0238 ready = _Atomic_Load_uint(
0239 &_SMP_Ready_to_start_multitasking,
0240 ATOMIC_ORDER_ACQUIRE
0241 );
0242 } while ( ready == 0U );
0243 }
0244
0245 void _SMP_Start_multitasking_on_secondary_processor(
0246 Per_CPU_Control *cpu_self
0247 )
0248 {
0249 uint32_t cpu_index_self;
0250
0251 cpu_index_self = _Per_CPU_Get_index( cpu_self );
0252
0253
0254
0255
0256
0257 cpu_self->thread_dispatch_disable_level = 1;
0258
0259 if ( cpu_index_self >= rtems_configuration_get_maximum_processors() ) {
0260 _SMP_Fatal( SMP_FATAL_MULTITASKING_START_ON_INVALID_PROCESSOR );
0261 }
0262
0263 if ( !_SMP_Should_start_processor( cpu_index_self ) ) {
0264 _SMP_Fatal( SMP_FATAL_MULTITASKING_START_ON_UNASSIGNED_PROCESSOR );
0265 }
0266
0267 _Per_CPU_Set_state( cpu_self, PER_CPU_STATE_READY_TO_START_MULTITASKING );
0268 _SMP_Wait_for_start_multitasking( cpu_self );
0269
0270 if ( !_Per_CPU_Is_processor_online( cpu_self ) ) {
0271 _SMP_Fatal( SMP_FATAL_MULTITASKING_START_ON_NOT_ONLINE_PROCESSOR );
0272 }
0273
0274 _Thread_Start_multitasking();
0275 }
0276
0277 void _SMP_Request_shutdown( void )
0278 {
0279 ISR_Level level;
0280 const Per_CPU_Control *cpu_self;
0281 uint32_t cpu_max;
0282 uint32_t cpu_index;
0283
0284 _ISR_Local_disable( level );
0285 (void) level;
0286
0287 cpu_max = _SMP_Processor_configured_maximum;
0288 cpu_self = _Per_CPU_Get();
0289
0290 for ( cpu_index = 0 ; cpu_index < cpu_max ; ++cpu_index ) {
0291 Per_CPU_Control *cpu;
0292
0293 cpu = _Per_CPU_Get_by_index( cpu_index );
0294
0295 if ( cpu == cpu_self ) {
0296 _Per_CPU_Set_state( cpu, PER_CPU_STATE_SHUTDOWN );
0297 } else {
0298 _Atomic_Fetch_or_ulong(
0299 &cpu->message,
0300 SMP_MESSAGE_SHUTDOWN,
0301 ATOMIC_ORDER_RELEASE
0302 );
0303
0304 if ( _Per_CPU_Get_state( cpu ) == PER_CPU_STATE_UP ) {
0305 _CPU_SMP_Send_interrupt( cpu_index );
0306 }
0307 }
0308 }
0309 }
0310
0311 void _SMP_Process_message( Per_CPU_Control *cpu_self, long unsigned message )
0312 {
0313 if ( ( message & SMP_MESSAGE_SHUTDOWN ) != 0 ) {
0314 ISR_Level level;
0315
0316 _CPU_ISR_Disable( level );
0317 (void) level;
0318
0319
0320 if ( _Per_CPU_Get_state( cpu_self ) != PER_CPU_STATE_SHUTDOWN ) {
0321 _Per_CPU_Set_state( cpu_self, PER_CPU_STATE_SHUTDOWN );
0322 _SMP_Fatal( SMP_FATAL_SHUTDOWN_RESPONSE );
0323 }
0324 }
0325
0326 if ( ( message & SMP_MESSAGE_PERFORM_JOBS ) != 0 ) {
0327 _Per_CPU_Perform_jobs( cpu_self );
0328 }
0329 }
0330
0331 void _SMP_Try_to_process_message(
0332 Per_CPU_Control *cpu_self,
0333 unsigned long message
0334 )
0335 {
0336 if ( message != 0 ) {
0337
0338
0339
0340
0341
0342 message = _Atomic_Exchange_ulong(
0343 &cpu_self->message,
0344 0,
0345 ATOMIC_ORDER_ACQUIRE
0346 );
0347
0348 _SMP_Process_message( cpu_self, message );
0349 }
0350 }
0351
0352 void _SMP_Send_message( Per_CPU_Control *cpu, unsigned long message )
0353 {
0354 (void) _Atomic_Fetch_or_ulong(
0355 &cpu->message, message,
0356 ATOMIC_ORDER_RELEASE
0357 );
0358
0359 if ( _Per_CPU_Get_state( cpu ) == PER_CPU_STATE_UP ) {
0360 _CPU_SMP_Send_interrupt( _Per_CPU_Get_index( cpu ) );
0361 }
0362 }