<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>