diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2021-07-27 13:40:51 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2021-07-28 19:32:24 +0200 |
commit | cbb1103a3ca9d2f42501ba373b5d559b981fb1c7 (patch) | |
tree | 8e20c863237d95390b49c82d7ee45791389b5a2a /cpukit/include | |
parent | score: Remove processor event broadcast/receive (diff) | |
download | rtems-cbb1103a3ca9d2f42501ba373b5d559b981fb1c7.tar.bz2 |
score: Simplify SMP processor state handling
The per-CPU states which control the SMP system initialization were added quite
early during the SMP support development. Replace this initial implementation
with a simplified one. There is no longer a global SMP lock required which
serialized the state changes of all processors. The new implementation better
integrates with the per-CPU jobs.
Diffstat (limited to '')
-rw-r--r-- | cpukit/include/rtems/score/percpu.h | 42 | ||||
-rw-r--r-- | cpukit/include/rtems/score/smpimpl.h | 61 |
2 files changed, 66 insertions, 37 deletions
diff --git a/cpukit/include/rtems/score/percpu.h b/cpukit/include/rtems/score/percpu.h index e79596c244..f72339620d 100644 --- a/cpukit/include/rtems/score/percpu.h +++ b/cpukit/include/rtems/score/percpu.h @@ -102,15 +102,18 @@ struct Scheduler_Context; * The processor state controls the life cycle of processors at the lowest * level. No multi-threading or other high-level concepts matter here. * - * State changes must be initiated via _Per_CPU_State_change(). This function - * may not return in case someone requested a shutdown. The - * _SMP_Send_message() function will be used to notify other processors about - * state changes if the other processor is in the up state. + * The state of a processor is indicated by the Per_CPU_Control::state membe. + * The current state of a processor can be get by _Per_CPU_Get_state(). Only + * the processor associated with the control may change its state using + * _Per_CPU_Set_state(). * * Due to the sequential nature of the basic system initialization one * processor has a special role. It is the processor executing the boot_card() * function. This processor is called the boot processor. All other - * processors are called secondary. + * processors are called secondary. The boot processor uses + * _SMP_Request_start_multitasking() to indicate that processors should start + * multiprocessing. Secondary processors will wait for this request in + * _SMP_Start_multitasking_on_secondary_processor(). * * @dot * digraph states { @@ -150,23 +153,13 @@ typedef enum { * the first time. The boot processor will wait for all secondary processors * to change into this state. In case a secondary processor does not reach * this state the system will not start. The secondary processors wait now - * for a change into the PER_CPU_STATE_REQUEST_START_MULTITASKING state set - * by the boot processor once all secondary processors reached the - * PER_CPU_STATE_READY_TO_START_MULTITASKING state. + * for a change into the PER_CPU_STATE_UP state set requested by the boot + * processor through ::_SMP_Ready_to_start_multitasking once all secondary + * processors reached the PER_CPU_STATE_READY_TO_START_MULTITASKING state. */ PER_CPU_STATE_READY_TO_START_MULTITASKING, /** - * @brief Multitasking start of processor is requested. - * - * The boot processor completed system initialization and is about to perform - * a context switch to its heir thread. Secondary processors should now - * issue a context switch to the heir thread. This normally enables - * interrupts on the processor for the first time. - */ - PER_CPU_STATE_REQUEST_START_MULTITASKING, - - /** * @brief Normal multitasking state. */ PER_CPU_STATE_UP, @@ -547,11 +540,12 @@ typedef struct Per_CPU_Control { char *data; /** - * @brief Indicates the current state of the CPU. + * @brief Indicates the current state of the processor. * - * This member is protected by the _Per_CPU_State_lock lock. + * Only the processor associated with this control is allowed to change + * this member. * - * @see _Per_CPU_State_change(). + * @see _Per_CPU_Get_state() and _Per_CPU_Set_state(). */ Atomic_Uint state; @@ -801,6 +795,7 @@ static inline void _Per_CPU_Set_state( Per_CPU_State state ) { + _Assert( cpu_self == _Per_CPU_Get() ); _Atomic_Store_uint( &cpu_self->state, (unsigned int) state, @@ -808,11 +803,6 @@ static inline void _Per_CPU_Set_state( ); } -void _Per_CPU_State_change( - Per_CPU_Control *cpu, - Per_CPU_State new_state -); - /** * @brief Waits for a processor to change into a non-initial state. * diff --git a/cpukit/include/rtems/score/smpimpl.h b/cpukit/include/rtems/score/smpimpl.h index 32704d7288..eea48f5060 100644 --- a/cpukit/include/rtems/score/smpimpl.h +++ b/cpukit/include/rtems/score/smpimpl.h @@ -51,6 +51,16 @@ extern "C" { #define SMP_MESSAGE_PERFORM_JOBS 0x2UL /** + * @brief SMP message to force the message processing in + * _SMP_Try_to_process_message(). + * + * This message bit is never sent to a processor. It is only used to force the + * message processing in _SMP_Try_to_process_message(). Any non-zero value + * would do it. + */ +#define SMP_MESSAGE_FORCE_PROCESSING 0x4UL + +/** * @brief SMP fatal codes. */ typedef enum { @@ -130,11 +140,47 @@ RTEMS_NO_RETURN void _SMP_Start_multitasking_on_secondary_processor( ); /** - * @brief Interrupts handler for inter-processor interrupts. + * @brief Processes the SMP message. + * + * @param[in, out] cpu_self is the processor control of the processor executing + * this function. + * + * @return Returns the processed message. + */ +long unsigned _SMP_Process_message( + Per_CPU_Control *cpu_self, + long unsigned message +); + +/** + * @brief Tries to process the current SMP message. + * + * This function may be used in busy wait loops. + * + * @param cpu_self is the processor control of the processor executing this + * function. + * + * @param message is used to check if the SMP message processing should be + * carried out. If it is not equal to zero, then _SMP_Process_message() is + * called with a newly fetched message. This parameter is not used to process + * the message. It is only used to check if the processing is necessary. + * Use #SMP_MESSAGE_FORCE_PROCESSING to force the message processing. + */ +void _SMP_Try_to_process_message( + Per_CPU_Control *cpu_self, + unsigned long message +); + +/** + * @brief Processes an inter-processor interrupt. + * + * Use this function for the inter-processor interrupt handler. Never call + * this function in a tight loop. * - * @param[in, out] cpu_self The cpu control for the operation. + * @param[in, out] cpu_self is the processor control of the processor executing + * this function. * - * @return The received message. + * @return Returns the processed message. */ static inline long unsigned _SMP_Inter_processor_interrupt_handler( Per_CPU_Control *cpu_self @@ -155,14 +201,7 @@ static inline long unsigned _SMP_Inter_processor_interrupt_handler( ); if ( RTEMS_PREDICT_FALSE( message != 0 ) ) { - if ( ( message & SMP_MESSAGE_SHUTDOWN ) != 0 ) { - _SMP_Fatal( SMP_FATAL_SHUTDOWN_RESPONSE ); - /* does not continue past here */ - } - - if ( ( message & SMP_MESSAGE_PERFORM_JOBS ) != 0 ) { - _Per_CPU_Perform_jobs( cpu_self ); - } + return _SMP_Process_message( cpu_self, message ); } return message; |