Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSScoreSMP
0007  *
0008  * @brief This header file provides interfaces of the
0009  *   @ref RTEMSScoreSMP which are only used by the implementation.
0010  */
0011 
0012 /*
0013  *  COPYRIGHT (c) 1989-2011.
0014  *  On-Line Applications Research Corporation (OAR).
0015  *
0016  * Redistribution and use in source and binary forms, with or without
0017  * modification, are permitted provided that the following conditions
0018  * are met:
0019  * 1. Redistributions of source code must retain the above copyright
0020  *    notice, this list of conditions and the following disclaimer.
0021  * 2. Redistributions in binary form must reproduce the above copyright
0022  *    notice, this list of conditions and the following disclaimer in the
0023  *    documentation and/or other materials provided with the distribution.
0024  *
0025  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0026  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0027  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0028  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0029  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0030  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0031  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0032  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0033  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0034  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0035  * POSSIBILITY OF SUCH DAMAGE.
0036  */
0037 
0038 #ifndef _RTEMS_SCORE_SMPIMPL_H
0039 #define _RTEMS_SCORE_SMPIMPL_H
0040 
0041 #include <rtems/score/smp.h>
0042 #include <rtems/score/percpu.h>
0043 #include <rtems/score/processormaskimpl.h>
0044 #include <rtems/fatal.h>
0045 
0046 #ifdef __cplusplus
0047 extern "C" {
0048 #endif
0049 
0050 /**
0051  * @addtogroup RTEMSScoreSMP
0052  *
0053  * This defines the interface of the SuperCore SMP support.
0054  *
0055  * @{
0056  */
0057 
0058 /**
0059  * @brief SMP message to request a processor shutdown.
0060  *
0061  * @see _SMP_Send_message().
0062  */
0063 #define SMP_MESSAGE_SHUTDOWN 0x1UL
0064 
0065 /**
0066  * @brief SMP message to perform per-processor jobs.
0067  *
0068  * @see _SMP_Send_message().
0069  */
0070 #define SMP_MESSAGE_PERFORM_JOBS 0x2UL
0071 
0072 /**
0073  * @brief SMP message to force the message processing in
0074  *   _SMP_Try_to_process_message().
0075  *
0076  * This message bit is never sent to a processor.  It is only used to force the
0077  * message processing in _SMP_Try_to_process_message().  Any non-zero value
0078  * would do it.
0079  */
0080 #define SMP_MESSAGE_FORCE_PROCESSING 0x4UL
0081 
0082 /**
0083  * @brief SMP fatal codes.
0084  */
0085 typedef enum {
0086   SMP_FATAL_BOOT_PROCESSOR_NOT_ASSIGNED_TO_SCHEDULER,
0087   SMP_FATAL_MANDATORY_PROCESSOR_NOT_PRESENT,
0088   SMP_FATAL_MULTITASKING_START_ON_INVALID_PROCESSOR,
0089   SMP_FATAL_MULTITASKING_START_ON_UNASSIGNED_PROCESSOR,
0090   SMP_FATAL_SHUTDOWN,
0091   SMP_FATAL_SHUTDOWN_RESPONSE,
0092   SMP_FATAL_START_OF_MANDATORY_PROCESSOR_FAILED,
0093   SMP_FATAL_SCHEDULER_PIN_OR_UNPIN_NOT_SUPPORTED,
0094   SMP_FATAL_WRONG_CPU_STATE_TO_PERFORM_JOBS,
0095   SMP_FATAL_SCHEDULER_REQUIRES_EXACTLY_ONE_PROCESSOR,
0096   SMP_FATAL_MULTITASKING_START_ON_NOT_ONLINE_PROCESSOR
0097 } SMP_Fatal_code;
0098 
0099 /**
0100  * @brief Terminates with the given code.
0101  *
0102  * @param code The code for the termination.
0103  */
0104 static inline void _SMP_Fatal( SMP_Fatal_code code )
0105 {
0106   _Terminate( RTEMS_FATAL_SOURCE_SMP, code );
0107 }
0108 
0109 /**
0110  * @brief Initializes SMP Handler
0111  *
0112  * This method initialize the SMP Handler.
0113  */
0114 #if defined( RTEMS_SMP )
0115   void _SMP_Handler_initialize( void );
0116 #else
0117   #define _SMP_Handler_initialize() \
0118     do { } while ( 0 )
0119 #endif
0120 
0121 #if defined( RTEMS_SMP )
0122 
0123 /**
0124  * @brief Set of online processors.
0125  *
0126  * A processor is online if was started during system initialization.  In this
0127  * case its corresponding bit in the mask is set.
0128  *
0129  * @see _SMP_Handler_initialize().
0130  */
0131 extern Processor_mask _SMP_Online_processors;
0132 
0133 /**
0134  * @brief Performs high-level initialization of a secondary processor and runs
0135  * the application threads.
0136  *
0137  * The low-level initialization code must call this function to hand over the
0138  * control of this processor to RTEMS.  Interrupts must be disabled.  It must
0139  * be possible to send inter-processor interrupts to this processor.  Since
0140  * interrupts are disabled the inter-processor interrupt delivery is postponed
0141  * until interrupts are enabled the first time.  Interrupts are enabled during
0142  * the execution begin of threads in case they have interrupt level zero (this
0143  * is the default).
0144  *
0145  * The pre-requisites for the call to this function are
0146  * - disabled interrupts,
0147  * - delivery of inter-processor interrupts is possible,
0148  * - a valid stack pointer and enough stack space,
0149  * - a valid code memory, and
0150  * - a valid BSS section.
0151  *
0152  * This function must not be called by the main processor.  The main processor
0153  * uses _Thread_Start_multitasking() instead.
0154  *
0155  * This function does not return to the caller.
0156  *
0157  * @param cpu_self The current processor control.
0158  */
0159 RTEMS_NO_RETURN void _SMP_Start_multitasking_on_secondary_processor(
0160   Per_CPU_Control *cpu_self
0161 );
0162 
0163 /**
0164  * @brief Processes the SMP message.
0165  *
0166  * @param[in, out] cpu_self is the processor control of the processor executing
0167  *   this function.
0168  *
0169  * @param message is the message to process.
0170  */
0171 void _SMP_Process_message( Per_CPU_Control *cpu_self, long unsigned message );
0172 
0173 /**
0174  * @brief Tries to process the current SMP message.
0175  *
0176  * This function may be used in busy wait loops.
0177  *
0178  * @param cpu_self is the processor control of the processor executing this
0179  *   function.
0180  *
0181  * @param message is used to check if the SMP message processing should be
0182  *   carried out.  If it is not equal to zero, then _SMP_Process_message() is
0183  *   called with a newly fetched message.  This parameter is not used to process
0184  *   the message.  It is only used to check if the processing is necessary.
0185  *   Use #SMP_MESSAGE_FORCE_PROCESSING to force the message processing.
0186  */
0187 void _SMP_Try_to_process_message(
0188   Per_CPU_Control *cpu_self,
0189   unsigned long    message
0190 );
0191 
0192 /**
0193  * @brief Processes an inter-processor interrupt.
0194  *
0195  * Use this function for the inter-processor interrupt handler.  Never call
0196  * this function in a tight loop.
0197  *
0198  * @param[in, out] cpu_self is the processor control of the processor executing
0199  *   this function.
0200  */
0201 static inline void _SMP_Inter_processor_interrupt_handler(
0202   Per_CPU_Control *cpu_self
0203 )
0204 {
0205   unsigned long message;
0206 
0207   /*
0208    * In the common case the inter-processor interrupt is issued to carry out a
0209    * thread dispatch.
0210    */
0211   cpu_self->dispatch_necessary = true;
0212 
0213   message = _Atomic_Exchange_ulong(
0214     &cpu_self->message,
0215     0,
0216     ATOMIC_ORDER_ACQUIRE
0217   );
0218 
0219   if ( RTEMS_PREDICT_FALSE( message != 0 ) ) {
0220     _SMP_Process_message( cpu_self, message );
0221   }
0222 }
0223 
0224 /**
0225  * @brief Checks if the processor with the specified index should be started.
0226  *
0227  * @param cpu_index The processor index.
0228  *
0229  * @retval true The processor should be started.
0230  * @retval false The processor should not be started.
0231  */
0232 bool _SMP_Should_start_processor( uint32_t cpu_index );
0233 
0234 /**
0235  * @brief Sends the SMP message to the processor.
0236  *
0237  * The target processor may be the sending processor.
0238  *
0239  * @param[in, out] cpu is the processor control of the target processor.
0240  *
0241  * @param message is the message to send.
0242  */
0243 void _SMP_Send_message( Per_CPU_Control *cpu, unsigned long message );
0244 
0245 typedef void ( *SMP_Action_handler )( void *arg );
0246 
0247 /**
0248  * @brief Initiates an SMP multicast action to the set of target processors.
0249  *
0250  * The current processor may be part of the set.  The caller must ensure that
0251  * no thread dispatch can happen during the call of this function, otherwise
0252  * the behaviour is undefined.  In case a target processor is in a wrong state
0253  * to process per-processor jobs, then this function results in an
0254  * SMP_FATAL_WRONG_CPU_STATE_TO_PERFORM_JOBS fatal SMP error.
0255  *
0256  * @param targets The set of target processors for the action.
0257  * @param handler The multicast action handler.
0258  * @param arg The multicast action argument.
0259  */
0260 void _SMP_Multicast_action(
0261   const Processor_mask *targets,
0262   SMP_Action_handler    handler,
0263   void                 *arg
0264 );
0265 
0266 /**
0267  * @brief Initiates an SMP multicast action to the set of all online
0268  * processors.
0269  *
0270  * Simply calls _SMP_Multicast_action() with _SMP_Get_online_processors() as
0271  * the target processor set.
0272  *
0273  * @param handler The multicast action handler.
0274  * @param arg The multicast action argument.
0275  */
0276 void _SMP_Broadcast_action(
0277   SMP_Action_handler  handler,
0278   void               *arg
0279 );
0280 
0281 /**
0282  * @brief Initiates an SMP multicast action to the set of all online
0283  * processors excluding the current processor.
0284  *
0285  * Simply calls _SMP_Multicast_action() with _SMP_Get_online_processors() as
0286  * the target processor set excluding the current processor.
0287  *
0288  * @param handler The multicast action handler.
0289  * @param arg The multicast action argument.
0290  */
0291 void _SMP_Othercast_action(
0292   SMP_Action_handler  handler,
0293   void               *arg
0294 );
0295 
0296 /**
0297  * @brief Initiates an SMP action on the specified target processor.
0298  *
0299  * This is an optimized variant of _SMP_Multicast_action().
0300  *
0301  * @param cpu_index The index of the target processor.
0302  * @param handler The action handler.
0303  * @param arg The action argument.
0304  */
0305 void _SMP_Unicast_action(
0306   uint32_t            cpu_index,
0307   SMP_Action_handler  handler,
0308   void               *arg
0309 );
0310 
0311 /**
0312  * @brief Ensures that all store operations issued by the current processor
0313  * before the call this function are visible to all other online processors.
0314  *
0315  * Simply calls _SMP_Othercast_action() with an empty multicast action.
0316  */
0317 void _SMP_Synchronize( void );
0318 
0319 /**
0320  * @brief Waits until all other online processors reached the
0321  *   ::PER_CPU_STATE_READY_TO_START_MULTITASKING state.
0322  *
0323  * The waiting is done without a timeout.  If secondary processors cannot reach
0324  * this state, then it is expected that they indicate this failure with an
0325  * ::SMP_MESSAGE_SHUTDOWN message or reset the system.
0326  *
0327  * While waiting for state changes, SMP messages for the current processor are
0328  * processed.
0329  */
0330 void _SMP_Wait_for_ready_to_start_multitasking( void );
0331 
0332 #endif /* defined( RTEMS_SMP ) */
0333 
0334 /**
0335  * @brief Requests a multitasking start on all configured and available
0336  * processors.
0337  */
0338 #if defined( RTEMS_SMP )
0339   void _SMP_Request_start_multitasking( void );
0340 #else
0341   #define _SMP_Request_start_multitasking() \
0342     do { } while ( 0 )
0343 #endif
0344 
0345 /**
0346  * @brief Requests a shutdown of all processors.
0347  *
0348  * This function is a part of the system termination procedure.
0349  *
0350  * @see _Terminate().
0351  */
0352 #if defined( RTEMS_SMP )
0353   void _SMP_Request_shutdown( void );
0354 #else
0355   #define _SMP_Request_shutdown() \
0356     do { } while ( 0 )
0357 #endif
0358 
0359 /**
0360  * @brief Gets all online processors
0361  *
0362  * @return The processor mask with all online processors.
0363  */
0364 static inline const Processor_mask *_SMP_Get_online_processors( void )
0365 {
0366 #if defined(RTEMS_SMP)
0367   return &_SMP_Online_processors;
0368 #else
0369   return &_Processor_mask_The_one_and_only;
0370 #endif
0371 }
0372 
0373 /**
0374  * @brief Indicate if inter-processor interrupts are needed.
0375  *
0376  * @return True if inter-processor interrupts are needed for the correct system
0377  * operation, otherwise false.
0378  */
0379 static inline bool _SMP_Need_inter_processor_interrupts( void )
0380 {
0381   /*
0382    * Use the configured processor maximum instead of the actual to allow
0383    * testing on uni-processor systems.
0384    */
0385   return _SMP_Processor_configured_maximum > 1;
0386 }
0387 
0388 /** @} */
0389 
0390 #ifdef __cplusplus
0391 }
0392 #endif
0393 
0394 #endif
0395 /* end of include file */