[PATCH 6/8] score: Add _SMP_Before_multitasking_action()
Joel Sherrill
joel at rtems.org
Thu Mar 3 15:08:50 UTC 2016
The git log message needs more but it looks good otherwise.
--joel
On Thu, Mar 3, 2016 at 8:47 AM, Sebastian Huber <
sebastian.huber at embedded-brains.de> wrote:
> Update #2554.
> ---
> cpukit/score/include/rtems/score/percpu.h | 8 +++
> cpukit/score/include/rtems/score/smpimpl.h | 48 +++++++++++++++-
> cpukit/score/src/percpu.c | 92
> +++++++++++++++++++++++++++---
> cpukit/score/src/smp.c | 23 ++++++++
> cpukit/score/src/smpmulticastaction.c | 4 +-
> 5 files changed, 164 insertions(+), 11 deletions(-)
>
> diff --git a/cpukit/score/include/rtems/score/percpu.h
> b/cpukit/score/include/rtems/score/percpu.h
> index 19f46d2..39be1e3 100644
> --- a/cpukit/score/include/rtems/score/percpu.h
> +++ b/cpukit/score/include/rtems/score/percpu.h
> @@ -361,6 +361,14 @@ typedef struct Per_CPU_Control {
> Per_CPU_State state;
>
> /**
> + * @brief Action to be executed by this processor in the
> + * SYSTEM_STATE_BEFORE_MULTITASKING state on behalf of the boot
> processor.
> + *
> + * @see _SMP_Before_multitasking_action().
> + */
> + Atomic_Uintptr before_multitasking_action;
> +
> + /**
> * @brief Indicates if the processor has been successfully started via
> * _CPU_SMP_Start_processor().
> */
> diff --git a/cpukit/score/include/rtems/score/smpimpl.h
> b/cpukit/score/include/rtems/score/smpimpl.h
> index 386216f..59a99ec 100644
> --- a/cpukit/score/include/rtems/score/smpimpl.h
> +++ b/cpukit/score/include/rtems/score/smpimpl.h
> @@ -235,7 +235,7 @@ void _SMP_Send_message_multicast(
> unsigned long message
> );
>
> -typedef void ( *SMP_Multicast_action_handler )( void *arg );
> +typedef void ( *SMP_Action_handler )( void *arg );
>
> /**
> * @brief Initiates a SMP multicast action to a set of processors.
> @@ -250,10 +250,54 @@ typedef void ( *SMP_Multicast_action_handler )( void
> *arg );
> void _SMP_Multicast_action(
> const size_t setsize,
> const cpu_set_t *cpus,
> - SMP_Multicast_action_handler handler,
> + SMP_Action_handler handler,
> void *arg
> );
>
> +/**
> + * @brief Executes a handler with argument on the specified processor on
> behalf
> + * of the boot processor.
> + *
> + * The calling processor must be the boot processor. In case the
> specified
> + * processor is not online or not in the
> + * PER_CPU_STATE_READY_TO_START_MULTITASKING state, then no action is
> + * performed.
> + *
> + * @param cpu The processor to execute the action.
> + * @param handler The handler of the action.
> + * @param arg The argument of the action.
> + *
> + * @retval true The handler executed on the specified processor.
> + * @retval false Otherwise.
> + *
> + * @see _SMP_Before_multitasking_action_broadcast().
> + */
> +bool _SMP_Before_multitasking_action(
> + Per_CPU_Control *cpu,
> + SMP_Action_handler handler,
> + void *arg
> +);
> +
> +/**
> + * @brief Executes a handler with argument on all online processors
> except the
> + * boot processor on behalf of the boot processor.
> + *
> + * The calling processor must be the boot processor.
> + *
> + * @param handler The handler of the action.
> + * @param arg The argument of the action.
> + *
> + * @retval true The handler executed on all online processors except the
> boot
> + * processor.
> + * @retval false Otherwise.
> + *
> + * @see _SMP_Before_multitasking_action().
> + */
> +bool _SMP_Before_multitasking_action_broadcast(
> + SMP_Action_handler handler,
> + void *arg
> +);
> +
> #endif /* defined( RTEMS_SMP ) */
>
> /**
> diff --git a/cpukit/score/src/percpu.c b/cpukit/score/src/percpu.c
> index 730528a..0e4c067 100644
> --- a/cpukit/score/src/percpu.c
> +++ b/cpukit/score/src/percpu.c
> @@ -20,6 +20,7 @@
>
> #include <rtems/score/percpu.h>
> #include <rtems/score/assert.h>
> +#include <rtems/score/isrlock.h>
> #include <rtems/score/smpimpl.h>
> #include <rtems/config.h>
>
> @@ -35,11 +36,48 @@ RTEMS_STATIC_ASSERT(
>
> #if defined(RTEMS_SMP)
>
> -static SMP_lock_Control _Per_CPU_State_lock =
> - SMP_LOCK_INITIALIZER("per-CPU state");
> +typedef struct {
> + SMP_Action_handler handler;
> + void *arg;
> +} SMP_Before_multicast_action;
> +
> +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_before_multitasking_action( Per_CPU_Control
> *cpu )
> +{
> + uintptr_t action_value;
> +
> + action_value = _Atomic_Load_uintptr(
> + &cpu->before_multitasking_action,
> + ATOMIC_ORDER_ACQUIRE
> + );
> +
> + if ( action_value != 0 ) {
> + SMP_Before_multicast_action *action =
> + (SMP_Before_multicast_action *) action_value;
> +
> + ( *action->handler )( action->arg );
> +
> + _Atomic_Store_uintptr(
> + &cpu->before_multitasking_action,
> + 0,
> + ATOMIC_ORDER_RELEASE
> + );
> + }
> +}
>
> static void _Per_CPU_State_busy_wait(
> - const Per_CPU_Control *cpu,
> + Per_CPU_Control *cpu,
> Per_CPU_State new_state
> )
> {
> @@ -60,6 +98,7 @@ static void _Per_CPU_State_busy_wait(
> state != PER_CPU_STATE_REQUEST_START_MULTITASKING
> && state != PER_CPU_STATE_SHUTDOWN
> ) {
> + _Per_CPU_State_before_multitasking_action( cpu );
> _CPU_SMP_Processor_event_receive();
> state = cpu->state;
> }
> @@ -122,13 +161,12 @@ void _Per_CPU_State_change(
> Per_CPU_State new_state
> )
> {
> - SMP_lock_Control *lock = &_Per_CPU_State_lock;
> - SMP_lock_Context lock_context;
> + ISR_lock_Context lock_context;
> Per_CPU_State next_state;
>
> _Per_CPU_State_busy_wait( cpu, new_state );
>
> - _SMP_lock_ISR_disable_and_acquire( lock, &lock_context );
> + _Per_CPU_State_acquire( &lock_context );
>
> next_state = _Per_CPU_State_get_next( cpu->state, new_state );
> cpu->state = next_state;
> @@ -157,7 +195,7 @@ void _Per_CPU_State_change(
>
> _CPU_SMP_Processor_event_broadcast();
>
> - _SMP_lock_Release_and_ISR_enable( lock, &lock_context );
> + _Per_CPU_State_release( &lock_context );
>
> if (
> next_state == PER_CPU_STATE_SHUTDOWN
> @@ -167,6 +205,46 @@ void _Per_CPU_State_change(
> }
> }
>
> +bool _SMP_Before_multitasking_action(
> + Per_CPU_Control *cpu,
> + SMP_Action_handler handler,
> + void *arg
> +)
> +{
> + bool done;
> +
> + _Assert( _Per_CPU_Is_boot_processor( _Per_CPU_Get() ) );
> +
> + if ( _Per_CPU_Is_processor_online( cpu ) ) {
> + SMP_Before_multicast_action action = {
> + .handler = handler,
> + .arg = arg
> + };
> + Per_CPU_State expected_state =
> PER_CPU_STATE_READY_TO_START_MULTITASKING;
> +
> + _Atomic_Store_uintptr(
> + &cpu->before_multitasking_action,
> + (uintptr_t) &action,
> + ATOMIC_ORDER_RELEASE
> + );
> +
> + _CPU_SMP_Processor_event_broadcast();
> +
> + _Per_CPU_State_busy_wait( cpu, expected_state );
> +
> + do {
> + done = _Atomic_Load_uintptr(
> + &cpu->before_multitasking_action,
> + ATOMIC_ORDER_ACQUIRE
> + ) == 0;
> + } while ( !done && cpu->state == expected_state );
> + } else {
> + done = false;
> + }
> +
> + return done;
> +}
> +
> #else
> /*
> * On single core systems, we can efficiently directly access a single
> diff --git a/cpukit/score/src/smp.c b/cpukit/score/src/smp.c
> index 8049643..4dacd4e 100644
> --- a/cpukit/score/src/smp.c
> +++ b/cpukit/score/src/smp.c
> @@ -211,4 +211,27 @@ void _SMP_Send_message_multicast(
> }
> }
>
> +bool _SMP_Before_multitasking_action_broadcast(
> + SMP_Action_handler handler,
> + void *arg
> +)
> +{
> + bool done = true;
> + uint32_t cpu_count = _SMP_Get_processor_count();
> + uint32_t cpu_index;
> +
> + for ( cpu_index = 0 ; done && cpu_index < cpu_count ; ++cpu_index ) {
> + Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index );
> +
> + if (
> + !_Per_CPU_Is_boot_processor( cpu )
> + && _Per_CPU_Is_processor_online( cpu )
> + ) {
> + done = _SMP_Before_multitasking_action( cpu, handler, arg );
> + }
> + }
> +
> + return done;
> +}
> +
> SMP_Test_message_handler _SMP_Test_message_handler;
> diff --git a/cpukit/score/src/smpmulticastaction.c
> b/cpukit/score/src/smpmulticastaction.c
> index 2e59262..d5d0064 100644
> --- a/cpukit/score/src/smpmulticastaction.c
> +++ b/cpukit/score/src/smpmulticastaction.c
> @@ -17,7 +17,7 @@
>
> typedef struct {
> Chain_Node Node;
> - SMP_Multicast_action_handler handler;
> + SMP_Action_handler handler;
> void *arg;
> cpu_set_t *recipients;
> size_t setsize;
> @@ -94,7 +94,7 @@ _SMP_Multicast_actions_try_process( void )
> void _SMP_Multicast_action(
> const size_t setsize,
> const cpu_set_t *cpus,
> - SMP_Multicast_action_handler handler,
> + SMP_Action_handler handler,
> void *arg
> )
> {
> --
> 1.8.4.5
>
> _______________________________________________
> devel mailing list
> devel at rtems.org
> http://lists.rtems.org/mailman/listinfo/devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.rtems.org/pipermail/devel/attachments/20160303/9b601569/attachment-0002.html>
More information about the devel
mailing list