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