Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:26

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSScoreMPCI
0007  *
0008  * @brief This source file contains the definition of
0009  *   ::_System_state_Is_multiprocessing, ::_MPCI_Semaphore,
0010  *   ::_MPCI_Remote_blocked_threads, ::_MPCI_table, ::_MPCI_Receive_server_tcb,
0011  *   ::_MPCI_Packet_processors and the implementation of
0012  *   _MPCI_Register_packet_processor(), _MPCI_Get_packet(),
0013  *   _MPCI_Send_process_packet(), _MPCI_Send_request_packet(),
0014  *   _MPCI_Send_response_packet(), _MPCI_Receive_packet(),
0015  *   _MPCI_Process_response(), _MPCI_Receive_server(), _MPCI_Announce(),
0016  *   _MPCI_Internal_packets_Send_process_packet(),
0017  *   _MPCI_Internal_packets_Process_packet(),
0018  *   _MPCI_Internal_packets_Get_packet(), and the MPCI Handler system
0019  *   initialization.
0020  */
0021 
0022 /*
0023  *  COPYRIGHT (c) 1989-2014.
0024  *  On-Line Applications Research Corporation (OAR).
0025  *
0026  * Redistribution and use in source and binary forms, with or without
0027  * modification, are permitted provided that the following conditions
0028  * are met:
0029  * 1. Redistributions of source code must retain the above copyright
0030  *    notice, this list of conditions and the following disclaimer.
0031  * 2. Redistributions in binary form must reproduce the above copyright
0032  *    notice, this list of conditions and the following disclaimer in the
0033  *    documentation and/or other materials provided with the distribution.
0034  *
0035  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0036  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0037  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0038  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0039  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0040  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0041  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0042  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0043  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0044  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0045  * POSSIBILITY OF SUCH DAMAGE.
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  *  This is the core semaphore which the MPCI Receive Server blocks on.
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    *  Initialize the system state based on whether this is an MP system.
0092    *  In an MP configuration, internally we view single processor
0093    *  systems as a very restricted multiprocessor system.
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    *  Register the MP Process Packet routine.
0120    */
0121 
0122   _MPCI_Register_packet_processor(
0123     MP_PACKET_MPCI_INTERNAL,
0124     _MPCI_Internal_packets_Process_packet
0125   );
0126 
0127   /*
0128    *  Create the counting semaphore used by the MPCI Receive Server.
0129    */
0130 
0131   _CORE_semaphore_Initialize(
0132     &_MPCI_Semaphore,
0133     0                         /* initial_value */
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    *  Initialize the MPCI Receive Server
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    *  Put in a default timeout that will be used for
0209    *  all packets that do not otherwise have a timeout.
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    *  See if we need a default timeout
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    * FIXME: This is broken on SMP, see
0328    *        https://gitlab.rtems.org/rtems/rtos/rtems/-/issues/2703
0329    *
0330    * Should use _Thread_queue_Extract_critical() instead with a handler
0331    * function provided by the caller of _MPCI_Process_response().  Similar to
0332    * the filter function in _Thread_queue_Flush_critical().
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  *  _MPCI_Receive_server
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  *  _MPCI_Internal_packets_Send_request_packet
0435  *
0436  *  This subprogram is not needed since there are no request
0437  *  packets to be sent by this manager.
0438  *
0439  */
0440 
0441 /*
0442  *  _MPCI_Internal_packets_Send_response_packet
0443  *
0444  *  This subprogram is not needed since there are no response
0445  *  packets to be sent by this manager.
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  *  _MPCI_Internal_packets_Send_object_was_deleted
0481  *
0482  *  This subprogram is not needed since there are no objects
0483  *  deleted by this manager.
0484  *
0485  */
0486 
0487 /*
0488  *  _MPCI_Internal_packets_Send_extract_proxy
0489  *
0490  *  This subprogram is not needed since there are no objects
0491  *  deleted by this manager.
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 /* end of file */