File indexing completed on 2025-05-11 08:24:26
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
0044
0045
0046
0047
0048 #ifdef HAVE_CONFIG_H
0049 #include "config.h"
0050 #endif
0051
0052 #include <rtems/score/mpciimpl.h>
0053 #include <rtems/score/coresemimpl.h>
0054 #include <rtems/score/interr.h>
0055 #include <rtems/score/objectmp.h>
0056 #include <rtems/score/stackimpl.h>
0057 #include <rtems/score/sysstate.h>
0058 #include <rtems/score/schedulerimpl.h>
0059 #include <rtems/score/threadimpl.h>
0060 #include <rtems/score/threadqimpl.h>
0061 #include <rtems/sysinit.h>
0062
0063 #include <string.h>
0064
0065 RTEMS_STATIC_ASSERT(
0066 sizeof(MPCI_Internal_packet) <= MP_PACKET_MINIMUM_PACKET_SIZE,
0067 MPCI_Internal_packet
0068 );
0069
0070 #define MPCI_SEMAPHORE_TQ_OPERATIONS &_Thread_queue_Operations_FIFO
0071
0072 bool _System_state_Is_multiprocessing;
0073
0074
0075
0076
0077 CORE_semaphore_Control _MPCI_Semaphore;
0078
0079 Thread_queue_Control _MPCI_Remote_blocked_threads =
0080 THREAD_QUEUE_INITIALIZER( "MPCI Remote Blocked Threads" );
0081
0082 MPCI_Control *_MPCI_table;
0083
0084 Thread_Control *_MPCI_Receive_server_tcb;
0085
0086 MPCI_Packet_processor _MPCI_Packet_processors[ MP_PACKET_CLASSES_LAST + 1 ];
0087
0088 static void _MPCI_Handler_early_initialization( void )
0089 {
0090
0091
0092
0093
0094
0095 if ( _MPCI_Configuration.maximum_nodes > 1 ) {
0096 _System_state_Is_multiprocessing = true;
0097 }
0098
0099 _Objects_MP_Handler_early_initialization();
0100 }
0101
0102 static void _MPCI_Handler_initialization( void )
0103 {
0104 MPCI_Control *users_mpci_table;
0105
0106 _Objects_MP_Handler_initialization();
0107
0108 users_mpci_table = _MPCI_Configuration.User_mpci_table;
0109
0110 if ( _System_state_Is_multiprocessing && !users_mpci_table )
0111 _Internal_error( INTERNAL_ERROR_NO_MPCI );
0112
0113 _MPCI_table = users_mpci_table;
0114
0115 if ( !_System_state_Is_multiprocessing )
0116 return;
0117
0118
0119
0120
0121
0122 _MPCI_Register_packet_processor(
0123 MP_PACKET_MPCI_INTERNAL,
0124 _MPCI_Internal_packets_Process_packet
0125 );
0126
0127
0128
0129
0130
0131 _CORE_semaphore_Initialize(
0132 &_MPCI_Semaphore,
0133 0
0134 );
0135 }
0136
0137 static void _MPCI_Create_server( void )
0138 {
0139 Thread_Entry_information entry = {
0140 .adaptor = _Thread_Entry_adaptor_numeric,
0141 .Kinds = {
0142 .Numeric = {
0143 .entry = _MPCI_Receive_server
0144 }
0145 }
0146 };
0147 Thread_Configuration config;
0148 Status_Control status;
0149 ISR_lock_Context lock_context;
0150
0151
0152 if ( !_System_state_Is_multiprocessing )
0153 return;
0154
0155
0156
0157
0158
0159 _MPCI_Receive_server_tcb = _Thread_Internal_allocate();
0160 _Assert( _MPCI_Receive_server_tcb != NULL );
0161
0162 memset( &config, 0, sizeof( config ) );
0163 config.scheduler = &_Scheduler_Table[ 0 ];
0164 config.name = _Objects_Build_name( 'M', 'P', 'C', 'I' );
0165 config.priority = PRIORITY_MINIMUM;
0166 config.is_fp = CPU_ALL_TASKS_ARE_FP;
0167 config.stack_size = _Stack_Minimum()
0168 + _MPCI_Configuration.extra_mpci_receive_server_stack
0169 + CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK
0170 + CPU_ALL_TASKS_ARE_FP * CONTEXT_FP_SIZE;
0171 config.stack_area = _MPCI_Receive_server_stack;
0172
0173 status = _Thread_Initialize(
0174 &_Thread_Information,
0175 _MPCI_Receive_server_tcb,
0176 &config
0177 );
0178 _Assert_Unused_variable_equals( status, STATUS_SUCCESSFUL );
0179
0180 _ISR_lock_ISR_disable( &lock_context );
0181 _Thread_Start( _MPCI_Receive_server_tcb, &entry, &lock_context );
0182 }
0183
0184 static void _MPCI_Initialization( void )
0185 {
0186 (*_MPCI_table->initialization)();
0187 }
0188
0189 void _MPCI_Register_packet_processor(
0190 MP_packet_Classes the_class,
0191 MPCI_Packet_processor the_packet_processor
0192
0193 )
0194 {
0195 _MPCI_Packet_processors[ the_class ] = the_packet_processor;
0196 }
0197
0198 MP_packet_Prefix *_MPCI_Get_packet ( void )
0199 {
0200 MP_packet_Prefix *the_packet;
0201
0202 (*_MPCI_table->get_packet)( &the_packet );
0203
0204 if ( the_packet == NULL )
0205 _Internal_error( INTERNAL_ERROR_OUT_OF_PACKETS );
0206
0207
0208
0209
0210
0211
0212 the_packet->timeout = MPCI_DEFAULT_TIMEOUT;
0213
0214 return the_packet;
0215 }
0216
0217 void _MPCI_Return_packet (
0218 MP_packet_Prefix *the_packet
0219 )
0220 {
0221 (*_MPCI_table->return_packet)( the_packet );
0222 }
0223
0224 void _MPCI_Send_process_packet (
0225 uint32_t destination,
0226 MP_packet_Prefix *the_packet
0227 )
0228 {
0229 the_packet->source_tid = _Thread_Executing->Object.id;
0230 the_packet->to_convert =
0231 ( the_packet->to_convert - sizeof(MP_packet_Prefix) ) / sizeof(uint32_t);
0232
0233 (*_MPCI_table->send_packet)( destination, the_packet );
0234 }
0235
0236 static void _MPCI_Enqueue_callout(
0237 Thread_queue_Queue *queue,
0238 Thread_Control *the_thread,
0239 struct Per_CPU_Control *cpu_self,
0240 Thread_queue_Context *queue_context
0241 )
0242 {
0243 _Thread_queue_Add_timeout_ticks( queue, the_thread, cpu_self, queue_context );
0244 _Thread_Dispatch_unnest( cpu_self );
0245 }
0246
0247 Status_Control _MPCI_Send_request_packet(
0248 uint32_t destination,
0249 MP_packet_Prefix *the_packet,
0250 States_Control extra_state
0251 )
0252 {
0253 Per_CPU_Control *cpu_self;
0254 Thread_queue_Context queue_context;
0255 Thread_Control *executing;
0256
0257
0258
0259
0260
0261 if (the_packet->timeout == MPCI_DEFAULT_TIMEOUT)
0262 the_packet->timeout = _MPCI_table->default_timeout;
0263
0264 _Thread_queue_Context_initialize( &queue_context );
0265 _Thread_queue_Context_set_thread_state(
0266 &queue_context,
0267 STATES_WAITING_FOR_RPC_REPLY | extra_state
0268 );
0269 _Thread_queue_Context_set_timeout_ticks( &queue_context, the_packet->timeout );
0270 _Thread_queue_Context_set_enqueue_callout(
0271 &queue_context,
0272 _MPCI_Enqueue_callout
0273 );
0274
0275 cpu_self = _Thread_Dispatch_disable();
0276
0277 executing = _Per_CPU_Get_executing( cpu_self );
0278 executing->Wait.remote_id = the_packet->id;
0279
0280 the_packet->source_tid = executing->Object.id;
0281 the_packet->source_priority = _Thread_Get_priority( executing );
0282 the_packet->to_convert =
0283 ( the_packet->to_convert - sizeof(MP_packet_Prefix) ) / sizeof(uint32_t);
0284
0285 (*_MPCI_table->send_packet)( destination, the_packet );
0286
0287 _Thread_queue_Acquire( &_MPCI_Remote_blocked_threads, &queue_context );
0288 _Thread_queue_Enqueue(
0289 &_MPCI_Remote_blocked_threads.Queue,
0290 &_Thread_queue_Operations_FIFO,
0291 executing,
0292 &queue_context
0293 );
0294 return _Thread_Wait_get_status( executing );
0295 }
0296
0297 void _MPCI_Send_response_packet (
0298 uint32_t destination,
0299 MP_packet_Prefix *the_packet
0300 )
0301 {
0302 the_packet->source_tid = _Thread_Executing->Object.id;
0303
0304 (*_MPCI_table->send_packet)( destination, the_packet );
0305 }
0306
0307 MP_packet_Prefix *_MPCI_Receive_packet ( void )
0308 {
0309 MP_packet_Prefix *the_packet;
0310
0311 (*_MPCI_table->receive_packet)( &the_packet );
0312
0313 return the_packet;
0314 }
0315
0316 Thread_Control *_MPCI_Process_response (
0317 MP_packet_Prefix *the_packet
0318 )
0319 {
0320 ISR_lock_Context lock_context;
0321 Thread_Control *the_thread;
0322
0323 the_thread = _Thread_Get( the_packet->id, &lock_context );
0324 _Assert( the_thread != NULL );
0325
0326
0327
0328
0329
0330
0331
0332
0333
0334 _ISR_lock_ISR_enable( &lock_context );
0335 _Thread_queue_Extract( the_thread );
0336 the_thread->Wait.return_code = the_packet->return_code;
0337 return the_thread;
0338 }
0339
0340
0341
0342
0343
0344
0345 void _MPCI_Receive_server(
0346 Thread_Entry_numeric_type ignored
0347 )
0348 {
0349
0350 MP_packet_Prefix *the_packet;
0351 MPCI_Packet_processor the_function;
0352 Thread_Control *executing;
0353 Thread_queue_Context queue_context;
0354
0355 executing = _Thread_Get_executing();
0356 _Thread_queue_Context_initialize( &queue_context );
0357 _Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
0358
0359 for ( ; ; ) {
0360
0361 executing->receive_packet = NULL;
0362
0363 _ISR_lock_ISR_disable( &queue_context.Lock_context.Lock_context );
0364 _CORE_semaphore_Seize(
0365 &_MPCI_Semaphore,
0366 MPCI_SEMAPHORE_TQ_OPERATIONS,
0367 executing,
0368 true,
0369 &queue_context
0370 );
0371
0372 for ( ; ; ) {
0373 executing->receive_packet = NULL;
0374
0375 the_packet = _MPCI_Receive_packet();
0376
0377 if ( !the_packet )
0378 break;
0379
0380 executing->receive_packet = the_packet;
0381
0382 if ( !_Mp_packet_Is_valid_packet_class ( the_packet->the_class ) )
0383 break;
0384
0385 the_function = _MPCI_Packet_processors[ the_packet->the_class ];
0386
0387 if ( !the_function )
0388 _Internal_error( INTERNAL_ERROR_BAD_PACKET );
0389
0390 (*the_function)( the_packet );
0391 }
0392 }
0393 }
0394
0395 void _MPCI_Announce ( void )
0396 {
0397 Thread_queue_Context queue_context;
0398
0399 _ISR_lock_ISR_disable( &queue_context.Lock_context.Lock_context );
0400 (void) _CORE_semaphore_Surrender(
0401 &_MPCI_Semaphore,
0402 MPCI_SEMAPHORE_TQ_OPERATIONS,
0403 UINT32_MAX,
0404 &queue_context
0405 );
0406 }
0407
0408 void _MPCI_Internal_packets_Send_process_packet (
0409 MPCI_Internal_Remote_operations operation
0410 )
0411 {
0412 MPCI_Internal_packet *the_packet;
0413
0414 switch ( operation ) {
0415
0416 case MPCI_PACKETS_SYSTEM_VERIFY:
0417
0418 the_packet = _MPCI_Internal_packets_Get_packet();
0419 the_packet->Prefix.the_class = MP_PACKET_MPCI_INTERNAL;
0420 the_packet->Prefix.length = sizeof ( MPCI_Internal_packet );
0421 the_packet->Prefix.to_convert = sizeof ( MPCI_Internal_packet );
0422 the_packet->operation = operation;
0423
0424 the_packet->maximum_nodes = _Objects_Maximum_nodes;
0425
0426 the_packet->maximum_global_objects = _Objects_MP_Maximum_global_objects;
0427
0428 _MPCI_Send_process_packet( MPCI_ALL_NODES, &the_packet->Prefix );
0429 break;
0430 }
0431 }
0432
0433
0434
0435
0436
0437
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448
0449 void _MPCI_Internal_packets_Process_packet (
0450 MP_packet_Prefix *the_packet_prefix
0451 )
0452 {
0453 MPCI_Internal_packet *the_packet;
0454 uint32_t maximum_nodes;
0455 uint32_t maximum_global_objects;
0456
0457 the_packet = (MPCI_Internal_packet *) the_packet_prefix;
0458
0459 switch ( the_packet->operation ) {
0460
0461 case MPCI_PACKETS_SYSTEM_VERIFY:
0462
0463 maximum_nodes = the_packet->maximum_nodes;
0464 maximum_global_objects = the_packet->maximum_global_objects;
0465 if ( maximum_nodes != _Objects_Maximum_nodes ||
0466 maximum_global_objects != _Objects_MP_Maximum_global_objects ) {
0467
0468 _MPCI_Return_packet( the_packet_prefix );
0469
0470 _Internal_error( INTERNAL_ERROR_INCONSISTENT_MP_INFORMATION );
0471 }
0472
0473 _MPCI_Return_packet( the_packet_prefix );
0474
0475 break;
0476 }
0477 }
0478
0479
0480
0481
0482
0483
0484
0485
0486
0487
0488
0489
0490
0491
0492
0493
0494
0495 MPCI_Internal_packet *_MPCI_Internal_packets_Get_packet ( void )
0496 {
0497 return ( (MPCI_Internal_packet *) _MPCI_Get_packet() );
0498 }
0499
0500 static void _MPCI_Finalize( void )
0501 {
0502 if ( _System_state_Is_multiprocessing ) {
0503 _MPCI_Initialization();
0504 _MPCI_Internal_packets_Send_process_packet( MPCI_PACKETS_SYSTEM_VERIFY );
0505 }
0506 }
0507
0508 RTEMS_SYSINIT_ITEM(
0509 _MPCI_Handler_early_initialization,
0510 RTEMS_SYSINIT_MP_EARLY,
0511 RTEMS_SYSINIT_ORDER_MIDDLE
0512 );
0513
0514 RTEMS_SYSINIT_ITEM(
0515 _MPCI_Handler_initialization,
0516 RTEMS_SYSINIT_MP,
0517 RTEMS_SYSINIT_ORDER_MIDDLE
0518 );
0519
0520 RTEMS_SYSINIT_ITEM(
0521 _MPCI_Create_server,
0522 RTEMS_SYSINIT_MP_SERVER,
0523 RTEMS_SYSINIT_ORDER_MIDDLE
0524 );
0525
0526 RTEMS_SYSINIT_ITEM(
0527 _MPCI_Finalize,
0528 RTEMS_SYSINIT_MP_FINALIZE,
0529 RTEMS_SYSINIT_ORDER_MIDDLE
0530 );
0531
0532