On Wed, Jul 28, 2021 at 5:18 AM Sebastian Huber <sebastian.hu...@embedded-brains.de> wrote: > > 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. > --- > cpukit/include/rtems/score/percpu.h | 42 ++--- > cpukit/include/rtems/score/smpimpl.h | 60 +++++-- > cpukit/score/src/percpu.c | 151 +----------------- > cpukit/score/src/smp.c | 133 +++++++++++++-- > cpukit/score/src/smpmulticastaction.c | 36 ++--- > cpukit/score/src/threadstartmultitasking.c | 4 +- > testsuites/smptests/smpfatal01/init.c | 57 +++++-- > testsuites/smptests/smpfatal01/smpfatal01.doc | 3 +- > testsuites/smptests/smpfatal02/init.c | 21 ++- > testsuites/smptests/smpfatal02/smpfatal02.doc | 3 +- > 10 files changed, 260 insertions(+), 250 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. member
> + * The current state of a processor can be get by _Per_CPU_Get_state(). Only s/get/gotten or some other word here. > + * 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,22 +153,12 @@ 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. > */ > @@ -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..2770402562 100644 > --- a/cpukit/include/rtems/score/smpimpl.h > +++ b/cpukit/include/rtems/score/smpimpl.h > @@ -50,6 +50,12 @@ extern "C" { > */ > #define SMP_MESSAGE_PERFORM_JOBS 0x2UL > > +/** > + * @brief SMP message to force the message processing in > + * _SMP_Try_to_process_message(). > + */ > +#define SMP_MESSAGE_FORCE_PROCESSING 0x1UL > + This is overlapping with SMP_MESSAGE_SHUTDOWN is that purposeful and safe to do? > /** > * @brief SMP fatal codes. > */ > @@ -99,6 +105,15 @@ static inline void _SMP_Fatal( SMP_Fatal_code code ) > */ > extern Processor_mask _SMP_Online_processors; > > +/** > + * @brief Indicates if the system is ready to start multitasking. > + * > + * Only the boot processor is allowed to change this object. If the object > has > + * a non-zero value and no fatal error occurred, then secondary processors > + * should call _Thread_Start_multitasking() to start multiprocessing. > + */ > +extern Atomic_Uint _SMP_Ready_to_start_multitasking; > + > /** > * @brief Performs high-level initialization of a secondary processor and > runs > * the application threads. > @@ -129,12 +144,44 @@ RTEMS_NO_RETURN void > _SMP_Start_multitasking_on_secondary_processor( > Per_CPU_Control *cpu_self > ); > > +/** > + * @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 if a newly fetched message. This parameter is not used to > process s/if/for ? > + * the message. > + */ > +void _SMP_Try_to_process_message( > + Per_CPU_Control *cpu_self, > + unsigned long message > +); > + > /** > * @brief Interrupts handler for inter-processor interrupts. s/Interrupts/Interrupt > * > - * @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 +202,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; > diff --git a/cpukit/score/src/percpu.c b/cpukit/score/src/percpu.c > index 7fbc1c8637..611f55c0c1 100644 > --- a/cpukit/score/src/percpu.c > +++ b/cpukit/score/src/percpu.c > @@ -3,8 +3,8 @@ > * > * @ingroup RTEMSScorePerCPU > * > - * @brief This source file contains a definition of ::_Per_CPU_Information > and > - * the implementation of _Per_CPU_State_change(). > + * @brief This source file contains the uniprocessor definition of > + * ::_Per_CPU_Information and the some static assertions. delete 'the' > */ > > /* > @@ -21,10 +21,6 @@ > #endif > > #include <rtems/score/percpu.h> > -#include <rtems/score/assert.h> > -#include <rtems/score/isrlock.h> > -#include <rtems/score/smpimpl.h> > -#include <rtems/config.h> > > RTEMS_STATIC_ASSERT( > sizeof( CPU_Uint32ptr ) >= sizeof( uintptr_t ), > @@ -36,148 +32,7 @@ RTEMS_STATIC_ASSERT( > CPU_Uint32ptr_greater_equal_uint32_t > ); > > -#if defined(RTEMS_SMP) > - > -ISR_LOCK_DEFINE( static, _Per_CPU_State_lock, "Per-CPU State" ) > - > -static void _Per_CPU_State_acquire( ISR_lock_Context *lock_context ) > -{ > - _ISR_lock_ISR_disable_and_acquire( &_Per_CPU_State_lock, lock_context ); > -} > - > -static void _Per_CPU_State_release( ISR_lock_Context *lock_context ) > -{ > - _ISR_lock_Release_and_ISR_enable( &_Per_CPU_State_lock, lock_context ); > -} > - > -static void _Per_CPU_State_busy_wait( > - Per_CPU_Control *cpu, > - Per_CPU_State new_state > -) > -{ > - Per_CPU_State state; > - > - state = _Per_CPU_Get_state( cpu ); > - > - switch ( new_state ) { > - case PER_CPU_STATE_REQUEST_START_MULTITASKING: > - while ( > - state != PER_CPU_STATE_READY_TO_START_MULTITASKING > - && state != PER_CPU_STATE_SHUTDOWN > - ) { > - _Per_CPU_Perform_jobs( cpu ); > - state = _Per_CPU_Get_state( cpu ); > - } > - break; > - case PER_CPU_STATE_UP: > - while ( > - state != PER_CPU_STATE_REQUEST_START_MULTITASKING > - && state != PER_CPU_STATE_SHUTDOWN > - ) { > - _Per_CPU_Perform_jobs( cpu ); > - state = _Per_CPU_Get_state( cpu ); > - } > - break; > - default: > - /* No need to wait */ > - break; > - } > -} > - > -static Per_CPU_State _Per_CPU_State_get_next( > - Per_CPU_State current_state, > - Per_CPU_State new_state > -) > -{ > - switch ( current_state ) { > - case PER_CPU_STATE_INITIAL: > - switch ( new_state ) { > - case PER_CPU_STATE_READY_TO_START_MULTITASKING: > - case PER_CPU_STATE_SHUTDOWN: > - /* Change is acceptable */ > - break; > - default: > - new_state = PER_CPU_STATE_SHUTDOWN; > - break; > - } > - break; > - case PER_CPU_STATE_READY_TO_START_MULTITASKING: > - switch ( new_state ) { > - case PER_CPU_STATE_REQUEST_START_MULTITASKING: > - case PER_CPU_STATE_SHUTDOWN: > - /* Change is acceptable */ > - break; > - default: > - new_state = PER_CPU_STATE_SHUTDOWN; > - break; > - } > - break; > - case PER_CPU_STATE_REQUEST_START_MULTITASKING: > - switch ( new_state ) { > - case PER_CPU_STATE_UP: > - case PER_CPU_STATE_SHUTDOWN: > - /* Change is acceptable */ > - break; > - default: > - new_state = PER_CPU_STATE_SHUTDOWN; > - break; > - } > - break; > - default: > - new_state = PER_CPU_STATE_SHUTDOWN; > - break; > - } > - > - return new_state; > -} > - > -void _Per_CPU_State_change( > - Per_CPU_Control *cpu, > - Per_CPU_State new_state > -) > -{ > - ISR_lock_Context lock_context; > - Per_CPU_State next_state; > - > - _Per_CPU_State_busy_wait( cpu, new_state ); > - > - _Per_CPU_State_acquire( &lock_context ); > - > - next_state = _Per_CPU_State_get_next( _Per_CPU_Get_state( cpu ), new_state > ); > - _Per_CPU_Set_state( cpu, next_state ); > - > - if ( next_state == PER_CPU_STATE_SHUTDOWN ) { > - uint32_t cpu_max = rtems_configuration_get_maximum_processors(); > - uint32_t cpu_index; > - > - for ( cpu_index = 0 ; cpu_index < cpu_max ; ++cpu_index ) { > - Per_CPU_Control *cpu_other = _Per_CPU_Get_by_index( cpu_index ); > - > - if ( cpu_other != cpu ) { > - switch ( _Per_CPU_Get_state( cpu_other ) ) { > - case PER_CPU_STATE_UP: > - _SMP_Send_message( cpu_index, SMP_MESSAGE_SHUTDOWN ); > - break; > - default: > - /* Nothing to do */ > - break; > - } > - > - _Per_CPU_Set_state( cpu_other, PER_CPU_STATE_SHUTDOWN ); > - } > - } > - } > - > - _Per_CPU_State_release( &lock_context ); > - > - if ( > - next_state == PER_CPU_STATE_SHUTDOWN > - && new_state != PER_CPU_STATE_SHUTDOWN > - ) { > - _SMP_Fatal( SMP_FATAL_SHUTDOWN ); > - } > -} > -#else > +#if !defined(RTEMS_SMP) > /* > * On single core systems, we can efficiently directly access a single > * statically allocated per cpu structure. And the fields are initialized > diff --git a/cpukit/score/src/smp.c b/cpukit/score/src/smp.c > index 0488464da0..bf53876dab 100644 > --- a/cpukit/score/src/smp.c > +++ b/cpukit/score/src/smp.c > @@ -4,12 +4,13 @@ > * @ingroup RTEMSScoreSMP > * > * @brief This source file contains the definition of > ::_SMP_Online_processors > - * and ::_SMP_Processor_maximum and the implementation of > - * _SMP_Handler_initialize(), _SMP_Request_shutdown(), > - * _SMP_Request_start_multitasking(), _SMP_Send_message(), > - * _SMP_Send_message_broadcast(), _SMP_Send_message_multicast(), > - * _SMP_Should_start_processor(), and > - * _SMP_Start_multitasking_on_secondary_processor(). > + * ::_SMP_Ready_to_start_multitasking, and ::_SMP_Processor_maximum and the > + * implementation of _SMP_Handler_initialize(), _SMP_Process_message(), > + * _SMP_Request_shutdown(), _SMP_Request_start_multitasking(), > + * _SMP_Send_message(), _SMP_Send_message_broadcast(), > + * _SMP_Send_message_multicast(), _SMP_Should_start_processor(), > + * _SMP_Start_multitasking_on_secondary_processor(), and > + * _SMP_Try_to_process_message(). > */ > > /* > @@ -37,6 +38,8 @@ > > Processor_mask _SMP_Online_processors; > > +Atomic_Uint _SMP_Ready_to_start_multitasking; > + > uint32_t _SMP_Processor_maximum; > > static const Scheduler_Assignment *_Scheduler_Get_initial_assignment( > @@ -159,20 +162,38 @@ void _SMP_Request_start_multitasking( void ) > uint32_t cpu_max; > uint32_t cpu_index; > > - cpu_self = _Per_CPU_Get(); > - _Per_CPU_State_change( cpu_self, PER_CPU_STATE_READY_TO_START_MULTITASKING > ); > - > cpu_max = _SMP_Get_processor_maximum(); > + cpu_self = _Per_CPU_Get(); > > + /* > + * Wait until all other online processors reached the > + * PER_CPU_STATE_READY_TO_START_MULTITASKING state. The waiting is done > + * without a timeout. If secondary processors cannot reach this state, > then > + * it is expected that they indicate this failure with an > + * ::SMP_MESSAGE_SHUTDOWN message or reset the system. > + */ > for ( cpu_index = 0 ; cpu_index < cpu_max ; ++cpu_index ) { > Per_CPU_Control *cpu; > > cpu = _Per_CPU_Get_by_index( cpu_index ); > > - if ( _Per_CPU_Is_processor_online( cpu ) ) { > - _Per_CPU_State_change( cpu, PER_CPU_STATE_REQUEST_START_MULTITASKING ); > + if ( cpu != cpu_self && _Per_CPU_Is_processor_online( cpu ) ) { > + while ( > + _Per_CPU_Get_state( cpu ) != > PER_CPU_STATE_READY_TO_START_MULTITASKING > + ) { > + _SMP_Try_to_process_message( > + cpu_self, > + _Atomic_Load_ulong( &cpu_self->message, ATOMIC_ORDER_RELAXED ) > + ); > + } > } > } > + > + _Atomic_Store_uint( > + &_SMP_Ready_to_start_multitasking, > + 0xffffffffU, Should this constant be defined for some kind of meaningful term? > + ATOMIC_ORDER_RELEASE > + ); > } > > bool _SMP_Should_start_processor( uint32_t cpu_index ) > @@ -183,6 +204,22 @@ bool _SMP_Should_start_processor( uint32_t cpu_index ) > return _Scheduler_Should_start_processor( assignment ); > } > > +static void _SMP_Wait_for_start_multitasking( Per_CPU_Control *cpu_self ) > +{ > + unsigned int ready; > + > + do { > + _SMP_Try_to_process_message( > + cpu_self, > + _Atomic_Load_ulong( &cpu_self->message, ATOMIC_ORDER_RELAXED ) > + ); > + ready = (Per_CPU_State) _Atomic_Load_uint( > + &_SMP_Ready_to_start_multitasking, > + ATOMIC_ORDER_ACQUIRE > + ); > + } while ( ready == 0 ); > +} > + > void _SMP_Start_multitasking_on_secondary_processor( > Per_CPU_Control *cpu_self > ) > @@ -199,28 +236,92 @@ void _SMP_Start_multitasking_on_secondary_processor( > _SMP_Fatal( SMP_FATAL_MULTITASKING_START_ON_UNASSIGNED_PROCESSOR ); > } > > - _Per_CPU_State_change( cpu_self, PER_CPU_STATE_READY_TO_START_MULTITASKING > ); > - > + _Per_CPU_Set_state( cpu_self, PER_CPU_STATE_READY_TO_START_MULTITASKING ); > + _SMP_Wait_for_start_multitasking( cpu_self ); > _Thread_Start_multitasking(); > } > > void _SMP_Request_shutdown( void ) > { > ISR_Level level; > + uint32_t cpu_max; > + uint32_t cpu_index_self; > + uint32_t cpu_index; > > _ISR_Local_disable( level ); > (void) level; > > - _Per_CPU_State_change( _Per_CPU_Get(), PER_CPU_STATE_SHUTDOWN ); > + cpu_max = _SMP_Processor_configured_maximum; > + cpu_index_self = _SMP_Get_current_processor(); > + > + for ( cpu_index = 0 ; cpu_index < cpu_max ; ++cpu_index ) { > + Per_CPU_Control *cpu; > + > + cpu = _Per_CPU_Get_by_index( cpu_index ); > + > + if ( cpu_index == cpu_index_self ) { > + _Per_CPU_Set_state( cpu, PER_CPU_STATE_SHUTDOWN ); > + } else { > + _Atomic_Fetch_or_ulong( > + &cpu->message, > + SMP_MESSAGE_SHUTDOWN, > + ATOMIC_ORDER_RELEASE > + ); > + > + if ( _Per_CPU_Get_state( cpu ) == PER_CPU_STATE_UP ) { > + _CPU_SMP_Send_interrupt( cpu_index ); > + } > + } > + } > +} > + > +long unsigned _SMP_Process_message( > + Per_CPU_Control *cpu_self, > + long unsigned message > +) > +{ > + if ( ( message & SMP_MESSAGE_SHUTDOWN ) != 0 ) { > + /* Check the state to prevent recursive shutdowns */ > + if ( _Per_CPU_Get_state( cpu_self ) != PER_CPU_STATE_SHUTDOWN ) { > + _Per_CPU_Set_state( cpu_self, PER_CPU_STATE_SHUTDOWN ); > + _SMP_Fatal( SMP_FATAL_SHUTDOWN_RESPONSE ); > + } > + } > + > + if ( ( message & SMP_MESSAGE_PERFORM_JOBS ) != 0 ) { > + _Per_CPU_Perform_jobs( cpu_self ); > + } > +} > + > +void _SMP_Try_to_process_message( > + Per_CPU_Control *cpu_self, > + unsigned long message > +) > +{ > + if ( message != 0 ) { > + /* Fetch the actual message */ > + message = _Atomic_Exchange_ulong( > + &cpu_self->message, > + 0, > + ATOMIC_ORDER_ACQUIRE > + ); > + > + _SMP_Process_message( cpu_self, message ); > + } > } > > void _SMP_Send_message( uint32_t cpu_index, unsigned long message ) > { > Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index ); > > - _Atomic_Fetch_or_ulong( &cpu->message, message, ATOMIC_ORDER_RELEASE ); > + (void) _Atomic_Fetch_or_ulong( > + &cpu->message, message, > + ATOMIC_ORDER_RELEASE > + ); > > - _CPU_SMP_Send_interrupt( cpu_index ); > + if ( _Per_CPU_Get_state( cpu ) == PER_CPU_STATE_UP ) { > + _CPU_SMP_Send_interrupt( cpu_index ); > + } > } > > void _SMP_Send_message_broadcast( unsigned long message ) > diff --git a/cpukit/score/src/smpmulticastaction.c > b/cpukit/score/src/smpmulticastaction.c > index 5d65ef14ca..8dbdef80c7 100644 > --- a/cpukit/score/src/smpmulticastaction.c > +++ b/cpukit/score/src/smpmulticastaction.c > @@ -92,27 +92,6 @@ void _Per_CPU_Add_job( Per_CPU_Control *cpu, Per_CPU_Job > *job ) > _Per_CPU_Jobs_release_and_ISR_enable( cpu, &lock_context ); > } > > -static void _Per_CPU_Try_perform_jobs( Per_CPU_Control *cpu_self ) > -{ > - unsigned long message; > - > - message = _Atomic_Load_ulong( &cpu_self->message, ATOMIC_ORDER_RELAXED ); > - > - if ( ( message & SMP_MESSAGE_PERFORM_JOBS ) != 0 ) { > - bool success; > - > - success = _Atomic_Compare_exchange_ulong( > - &cpu_self->message, &message, > - message & ~SMP_MESSAGE_PERFORM_JOBS, ATOMIC_ORDER_RELAXED, > - ATOMIC_ORDER_RELAXED > - ); > - > - if ( success ) { > - _Per_CPU_Perform_jobs( cpu_self ); > - } > - } > -} > - > void _Per_CPU_Wait_for_job( > const Per_CPU_Control *cpu, > const Per_CPU_Job *job > @@ -122,17 +101,22 @@ void _Per_CPU_Wait_for_job( > _Atomic_Load_ulong( &job->done, ATOMIC_ORDER_ACQUIRE ) > != PER_CPU_JOB_DONE > ) { > + Per_CPU_Control *cpu_self; > + > switch ( _Per_CPU_Get_state( cpu ) ) { > case PER_CPU_STATE_INITIAL: > case PER_CPU_STATE_READY_TO_START_MULTITASKING: > - case PER_CPU_STATE_REQUEST_START_MULTITASKING: > case PER_CPU_STATE_UP: > /* > - * Calling this function with the current processor is intentional. > - * We have to perform our own jobs here in case inter-processor > - * interrupts are not working. > + * Calling this function with the current processor is intentional. > We > + * have to perform our own jobs here in case inter-processor > interrupts > + * are not working. > */ > - _Per_CPU_Try_perform_jobs( _Per_CPU_Get() ); > + cpu_self = _Per_CPU_Get(); > + _SMP_Try_to_process_message( > + cpu_self, > + _Atomic_Load_ulong( &cpu_self->message, ATOMIC_ORDER_RELAXED ) > + ); > break; > default: > _SMP_Fatal( SMP_FATAL_WRONG_CPU_STATE_TO_PERFORM_JOBS ); > diff --git a/cpukit/score/src/threadstartmultitasking.c > b/cpukit/score/src/threadstartmultitasking.c > index 094a535394..9fa52a58ac 100644 > --- a/cpukit/score/src/threadstartmultitasking.c > +++ b/cpukit/score/src/threadstartmultitasking.c > @@ -22,6 +22,7 @@ > > #include <rtems/score/threadimpl.h> > #include <rtems/score/assert.h> > +#include <rtems/score/smpimpl.h> > > void _Thread_Start_multitasking( void ) > { > @@ -29,7 +30,8 @@ void _Thread_Start_multitasking( void ) > Thread_Control *heir; > > #if defined(RTEMS_SMP) > - _Per_CPU_State_change( cpu_self, PER_CPU_STATE_UP ); > + _Per_CPU_Set_state( cpu_self, PER_CPU_STATE_UP ); > + _SMP_Try_to_process_message( cpu_self, SMP_MESSAGE_FORCE_PROCESSING ); > > /* > * Threads begin execution in the _Thread_Handler() function. This > diff --git a/testsuites/smptests/smpfatal01/init.c > b/testsuites/smptests/smpfatal01/init.c > index 0fd5f3fc46..6ee08cf653 100644 > --- a/testsuites/smptests/smpfatal01/init.c > +++ b/testsuites/smptests/smpfatal01/init.c > @@ -32,6 +32,8 @@ const char rtems_test_name[] = "SMPFATAL 1"; > > static uint32_t main_cpu; > > +static uint32_t other_cpu; > + > static SMP_barrier_Control barrier = SMP_BARRIER_CONTROL_INITIALIZER; > > static void Init(rtems_task_argument arg) > @@ -45,35 +47,59 @@ static void fatal_extension( > rtems_fatal_code code > ) > { > - SMP_barrier_State barrier_state = SMP_BARRIER_STATE_INITIALIZER; > + assert(!always_set_to_false); > > if (source == RTEMS_FATAL_SOURCE_SMP) { > + SMP_barrier_State barrier_state = SMP_BARRIER_STATE_INITIALIZER; > + uint32_t cpu_count = rtems_scheduler_get_processor_maximum(); > uint32_t self = rtems_scheduler_get_processor(); > > - assert(!always_set_to_false); > - assert(code == SMP_FATAL_SHUTDOWN); > + if (self == other_cpu) { > + assert(code == SMP_FATAL_SHUTDOWN); > + } else { > + assert(code == SMP_FATAL_SHUTDOWN_RESPONSE); > + } > + > + _SMP_barrier_Wait(&barrier, &barrier_state, cpu_count); > > if (self == main_cpu) { > uint32_t cpu; > > - for (cpu = 0; cpu < MAX_CPUS; ++cpu) { > + for (cpu = 0; cpu < cpu_count; ++cpu) { > const Per_CPU_Control *per_cpu = _Per_CPU_Get_by_index( cpu ); > Per_CPU_State state = _Per_CPU_Get_state(per_cpu); > > assert(state == PER_CPU_STATE_SHUTDOWN); > } > > + for (cpu = cpu_count; cpu < MAX_CPUS; ++cpu) { > + const Per_CPU_Control *per_cpu = _Per_CPU_Get_by_index( cpu ); > + Per_CPU_State state = _Per_CPU_Get_state(per_cpu); > + > + assert(state == PER_CPU_STATE_INITIAL); > + } > + > TEST_END(); > + } else { > + _SMP_barrier_Wait(&barrier, &barrier_state, cpu_count); > } > } > +} > > - _SMP_barrier_Wait( > - &barrier, > - &barrier_state, > - rtems_scheduler_get_processor_maximum() > - ); > +static void shutdown_handler(void *arg) > +{ > + _SMP_Request_shutdown(); > + _SMP_Fatal(SMP_FATAL_SHUTDOWN); > } > > +static const Per_CPU_Job_context shutdown_context = { > + .handler = shutdown_handler > +}; > + > +static Per_CPU_Job shutdown_job = { > + .context = &shutdown_context > +}; > + > static rtems_status_code test_driver_init( > rtems_device_major_number major, > rtems_device_minor_number minor, > @@ -89,6 +115,7 @@ static rtems_status_code test_driver_init( > assert(rtems_configuration_get_maximum_processors() == MAX_CPUS); > > main_cpu = self; > + other_cpu = (self + 1) % cpu_count; > > for (cpu = 0; cpu < MAX_CPUS; ++cpu) { > const Per_CPU_Control *per_cpu = _Per_CPU_Get_by_index( cpu ); > @@ -107,10 +134,14 @@ static rtems_status_code test_driver_init( > } > > if (cpu_count > 1) { > - uint32_t other = (self + 1) % cpu_count; > - Per_CPU_Control *per_cpu = _Per_CPU_Get_by_index( other ); > - > - _Per_CPU_Set_state(per_cpu, PER_CPU_STATE_SHUTDOWN); > + Per_CPU_Control *per_cpu = _Per_CPU_Get_by_index( other_cpu ); > + > + _Per_CPU_Add_job(per_cpu, &shutdown_job); > + _Atomic_Fetch_or_ulong( > + &per_cpu->message, > + SMP_MESSAGE_PERFORM_JOBS, > + ATOMIC_ORDER_RELEASE > + ); > } else { > TEST_END(); > exit(0); > diff --git a/testsuites/smptests/smpfatal01/smpfatal01.doc > b/testsuites/smptests/smpfatal01/smpfatal01.doc > index c037cfe78b..c6b54b7dd1 100644 > --- a/testsuites/smptests/smpfatal01/smpfatal01.doc > +++ b/testsuites/smptests/smpfatal01/smpfatal01.doc > @@ -4,7 +4,8 @@ test set name: smpfatal01 > > directives: > > - - _Per_CPU_State_change() > + - _SMP_Request_shutdown() > + - _SMP_Request_start_multitasking() > > concepts: > > diff --git a/testsuites/smptests/smpfatal02/init.c > b/testsuites/smptests/smpfatal02/init.c > index 25321ca27b..5528a4315d 100644 > --- a/testsuites/smptests/smpfatal02/init.c > +++ b/testsuites/smptests/smpfatal02/init.c > @@ -47,6 +47,7 @@ static void fatal_extension( > { > SMP_barrier_State barrier_state = SMP_BARRIER_STATE_INITIALIZER; > uint32_t self = rtems_scheduler_get_processor(); > + uint32_t cpu_count = rtems_scheduler_get_processor_maximum(); > > assert(!always_set_to_false); > > @@ -57,25 +58,29 @@ static void fatal_extension( > assert(code == 0xdeadbeef); > > _SMP_Request_shutdown(); > + _SMP_barrier_Wait(&barrier, &barrier_state, cpu_count); > > - for (cpu = 0; cpu < MAX_CPUS; ++cpu) { > + for (cpu = 0; cpu < cpu_count; ++cpu) { > const Per_CPU_Control *per_cpu = _Per_CPU_Get_by_index( cpu ); > Per_CPU_State state = _Per_CPU_Get_state(per_cpu); > > assert(state == PER_CPU_STATE_SHUTDOWN); > } > > + for (cpu = cpu_count; cpu < MAX_CPUS; ++cpu) { > + const Per_CPU_Control *per_cpu = _Per_CPU_Get_by_index( cpu ); > + Per_CPU_State state = _Per_CPU_Get_state(per_cpu); > + > + assert(state == PER_CPU_STATE_INITIAL); > + } > + > TEST_END(); > } else if ( source == RTEMS_FATAL_SOURCE_SMP ) { > assert(self != main_cpu); > - assert(code == SMP_FATAL_SHUTDOWN); > + assert(code == SMP_FATAL_SHUTDOWN_RESPONSE); > + _SMP_barrier_Wait(&barrier, &barrier_state, cpu_count); > + _SMP_barrier_Wait(&barrier, &barrier_state, cpu_count); > } > - > - _SMP_barrier_Wait( > - &barrier, > - &barrier_state, > - rtems_scheduler_get_processor_maximum() > - ); > } > > static rtems_status_code test_driver_init( > diff --git a/testsuites/smptests/smpfatal02/smpfatal02.doc > b/testsuites/smptests/smpfatal02/smpfatal02.doc > index 9e2e002b37..b962f528ad 100644 > --- a/testsuites/smptests/smpfatal02/smpfatal02.doc > +++ b/testsuites/smptests/smpfatal02/smpfatal02.doc > @@ -4,7 +4,8 @@ test set name: smpfatal02 > > directives: > > - - _Per_CPU_State_change() > + - _Terminate() > + - _SMP_Start_multitasking_on_secondary_processor() > > concepts: > > -- > 2.26.2 > > _______________________________________________ > devel mailing list > devel@rtems.org > http://lists.rtems.org/mailman/listinfo/devel _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel