[PATCH 2/4] score: SMP initialization and shutdown changes

Sebastian Huber sebastian.huber at embedded-brains.de
Wed Feb 19 13:42:26 UTC 2014


Rename _SMP_Request_other_cores_to_perform_first_context_switch() into
_SMP_Request_start_multitasking_on_secondary_processors() to match the
corresponding _SMP_Start_multitasking_on_secondary_processor() action of
secondary processors.  Highlights also similarity to
_Thread_Start_multitasking().  Move in source file to right place.

Rename PER_CPU_STATE_READY_TO_BEGIN_MULTITASKING into
PER_CPU_STATE_READY_TO_START_MULTITASKING.

Rename PER_CPU_STATE_BEGIN_MULTITASKING into
PER_CPU_STATE_START_MULTITASKING.

Rename _SMP_Request_other_cores_to_shutdown() into
_SMP_Request_processors_to_shutdown().

Add new state PER_CPU_STATE_DO_SHUTDOWN to initiate a shutdown of other
processors during system initialization.  Add documentation for
Per_CPU_State.

Delete debug output.

New test smptests/smpfatal01.
---
 cpukit/sapi/src/exinit.c                      |    2 +-
 cpukit/score/include/rtems/score/percpu.h     |   66 ++++++++++--
 cpukit/score/include/rtems/score/smpimpl.h    |   11 +-
 cpukit/score/src/interr.c                     |    2 +-
 cpukit/score/src/percpu.c                     |   13 ++-
 cpukit/score/src/smp.c                        |  117 +++++++++++---------
 testsuites/smptests/Makefile.am               |    1 +
 testsuites/smptests/configure.ac              |    1 +
 testsuites/smptests/smpfatal01/Makefile.am    |   19 ++++
 testsuites/smptests/smpfatal01/init.c         |  140 +++++++++++++++++++++++++
 testsuites/smptests/smpfatal01/smpfatal01.doc |   12 ++
 testsuites/smptests/smpfatal01/smpfatal01.scn |    2 +
 12 files changed, 312 insertions(+), 74 deletions(-)
 create mode 100644 testsuites/smptests/smpfatal01/Makefile.am
 create mode 100644 testsuites/smptests/smpfatal01/init.c
 create mode 100644 testsuites/smptests/smpfatal01/smpfatal01.doc
 create mode 100644 testsuites/smptests/smpfatal01/smpfatal01.scn

diff --git a/cpukit/sapi/src/exinit.c b/cpukit/sapi/src/exinit.c
index d265455..3784401 100644
--- a/cpukit/sapi/src/exinit.c
+++ b/cpukit/sapi/src/exinit.c
@@ -210,7 +210,7 @@ void rtems_initialize_start_multitasking(void)
 {
   _System_state_Set( SYSTEM_STATE_UP );
 
-  _SMP_Request_other_cores_to_perform_first_context_switch();
+  _SMP_Request_start_multitasking_on_secondary_processors();
 
   _Thread_Start_multitasking();
 
diff --git a/cpukit/score/include/rtems/score/percpu.h b/cpukit/score/include/rtems/score/percpu.h
index 4c46b50..27b97f6 100644
--- a/cpukit/score/include/rtems/score/percpu.h
+++ b/cpukit/score/include/rtems/score/percpu.h
@@ -70,6 +70,32 @@ typedef struct Thread_Control_struct Thread_Control;
   #error "deferred FP switch not implemented for SMP"
 #endif
 
+/**
+ * @brief State of a processor.
+ *
+ * @dot
+ * digraph states {
+ *   bi [label="PER_CPU_STATE_BEFORE_INITIALIZATION"];
+ *   rsm [label="PER_CPU_STATE_READY_TO_START_MULTITASKING"];
+ *   sm [label="PER_CPU_STATE_START_MULTITASKING"];
+ *   ds [label="PER_CPU_STATE_DO_SHUTDOWN"];
+ *   u [label="PER_CPU_STATE_UP"];
+ *   s [label="PER_CPU_STATE_SHUTDOWN"];
+ *   bi -> rsm [label="secondary processor\ncompleted initialization"];
+ *   bi -> u [label="main processor\nstarts multitasking"];
+ *   rsm -> sm [label="main processor\ncompleted initialization"];
+ *   rsm -> ds [label="a fatal error occurred"];
+ *   ds -> s [label="do shutdown\nstate observed"];
+ *   sm -> u [label="secondary processor\nstarts multitasking"];
+ *   u -> s [label="shutdown initiated"];
+ * }
+ * @enddot
+ *
+ * The values are chosen to stop the wait for change in case an alternative
+ * state change occurs during _Per_CPU_Wait_for_state().
+ *
+ * @see _Per_CPU_Change_state(), _Per_CPU_Wait_for_state() and _Per_CPU_Get_state().
+ */
 typedef enum {
   /**
    * @brief The per CPU controls are initialized to zero.
@@ -77,15 +103,15 @@ typedef enum {
    * In this state the only valid field of the per CPU controls for secondary
    * processors is the per CPU state.  The secondary processors should perform
    * their basic initialization now and change into the
-   * PER_CPU_STATE_READY_TO_BEGIN_MULTITASKING state once this is complete.
+   * PER_CPU_STATE_READY_TO_START_MULTITASKING state once this is complete.
    *
    * The owner of the per CPU state field is the secondary processor in this
    * state.
    */
-  PER_CPU_STATE_BEFORE_INITIALIZATION,
+  PER_CPU_STATE_BEFORE_INITIALIZATION = 0x0,
 
   /**
-   * @brief Secondary processor is ready to begin multitasking.
+   * @brief Secondary processor is ready to start multitasking.
    *
    * The secondary processor performed its basic initialization and is ready to
    * receive inter-processor interrupts.  Interrupt delivery must be disabled
@@ -94,16 +120,16 @@ typedef enum {
    * the first time.  The main 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_BEGIN_MULTITASKING state set by the
+   * for a change into the PER_CPU_STATE_START_MULTITASKING state set by the
    * main processor once all secondary processors reached the
-   * PER_CPU_STATE_READY_TO_BEGIN_MULTITASKING state.
+   * PER_CPU_STATE_READY_TO_START_MULTITASKING state.
    *
    * The owner of the per CPU state field is the main processor in this state.
    */
-  PER_CPU_STATE_READY_TO_BEGIN_MULTITASKING,
+  PER_CPU_STATE_READY_TO_START_MULTITASKING = 0x1,
 
   /**
-   * @brief Multitasking begin of secondary processor is requested.
+   * @brief Multitasking start of secondary processor is requested.
    *
    * The main processor completed system initialization and is about to perform
    * a context switch to its heir thread.  Secondary processors should now
@@ -113,7 +139,18 @@ typedef enum {
    * The owner of the per CPU state field is the secondary processor in this
    * state.
    */
-  PER_CPU_STATE_BEGIN_MULTITASKING,
+  PER_CPU_STATE_START_MULTITASKING = 0x2 | 0x4,
+
+  /**
+   * @brief Shutdown of secondary processor is requested.
+   *
+   * A fatal error occurred during system initialization.  A secondary
+   * processor will shutdown once observes this state.
+   *
+   * The owner of the per CPU state field is the secondary processor in this
+   * state.
+   */
+  PER_CPU_STATE_DO_SHUTDOWN = 0x2 | 0x8,
 
   /**
    * @brief Normal multitasking state.
@@ -121,7 +158,7 @@ typedef enum {
    * The owner of the per CPU state field is the secondary processor in this
    * state.
    */
-  PER_CPU_STATE_UP,
+  PER_CPU_STATE_UP = 0x10,
 
   /**
    * @brief This is the terminal state.
@@ -129,7 +166,7 @@ typedef enum {
    * The owner of the per CPU state field is the secondary processor in this
    * state.
    */
-  PER_CPU_STATE_SHUTDOWN
+  PER_CPU_STATE_SHUTDOWN = 0x20
 } Per_CPU_State;
 
 #endif /* defined( RTEMS_SMP ) */
@@ -318,11 +355,18 @@ void _Per_CPU_Change_state(
   Per_CPU_State new_state
 );
 
-void _Per_CPU_Wait_for_state(
+Per_CPU_State _Per_CPU_Wait_for_state(
   const Per_CPU_Control *per_cpu,
   Per_CPU_State desired_state
 );
 
+static inline Per_CPU_State _Per_CPU_Get_state(
+  const Per_CPU_Control *per_cpu
+)
+{
+  return per_cpu->state;
+}
+
 #endif /* defined( RTEMS_SMP ) */
 
 /*
diff --git a/cpukit/score/include/rtems/score/smpimpl.h b/cpukit/score/include/rtems/score/smpimpl.h
index d68af43..1c44c29 100644
--- a/cpukit/score/include/rtems/score/smpimpl.h
+++ b/cpukit/score/include/rtems/score/smpimpl.h
@@ -47,6 +47,7 @@ extern "C" {
  * @brief SMP fatal codes.
  */
 typedef enum {
+  SMP_FATAL_EARLY_SHUTDOWN,
   SMP_FATAL_SHUTDOWN
 } SMP_Fatal_code;
 
@@ -108,8 +109,6 @@ static inline void _SMP_Inter_processor_interrupt_handler( void )
     _Per_CPU_Release_and_ISR_enable( self_cpu, level );
 
     if ( ( message & SMP_MESSAGE_SHUTDOWN ) != 0 ) {
-      _Per_CPU_Change_state( self_cpu, PER_CPU_STATE_SHUTDOWN );
-
       rtems_fatal( RTEMS_FATAL_SOURCE_SMP, SMP_FATAL_SHUTDOWN );
       /* does not continue past here */
     }
@@ -149,9 +148,9 @@ void _SMP_Broadcast_message(
  *  their first context switch operation.
  */
 #if defined( RTEMS_SMP )
-  void _SMP_Request_other_cores_to_perform_first_context_switch( void );
+  void _SMP_Request_start_multitasking_on_secondary_processors( void );
 #else
-  #define _SMP_Request_other_cores_to_perform_first_context_switch() \
+  #define _SMP_Request_start_multitasking_on_secondary_processors() \
     do { } while ( 0 )
 #endif
 
@@ -161,9 +160,9 @@ void _SMP_Broadcast_message(
  *  Send message to other cores requesting them to shutdown.
  */
 #if defined( RTEMS_SMP )
-  void _SMP_Request_other_cores_to_shutdown( void );
+  void _SMP_Request_processors_to_shutdown( void );
 #else
-  #define _SMP_Request_other_cores_to_shutdown() \
+  #define _SMP_Request_processors_to_shutdown() \
     do { } while ( 0 )
 #endif
 
diff --git a/cpukit/score/src/interr.c b/cpukit/score/src/interr.c
index c2a9fbe..d57f116 100644
--- a/cpukit/score/src/interr.c
+++ b/cpukit/score/src/interr.c
@@ -39,7 +39,7 @@ void _Terminate(
   _ISR_Disable_without_giant( level );
   (void) level;
 
-  _SMP_Request_other_cores_to_shutdown();
+  _SMP_Request_processors_to_shutdown();
 
   _User_extensions_Fatal( the_source, is_internal, the_error );
 
diff --git a/cpukit/score/src/percpu.c b/cpukit/score/src/percpu.c
index c68f378..9ce8b17 100644
--- a/cpukit/score/src/percpu.c
+++ b/cpukit/score/src/percpu.c
@@ -19,6 +19,7 @@
 #endif
 
 #include <rtems/score/percpu.h>
+#include <rtems/score/assert.h>
 
 #if defined(RTEMS_SMP)
   void _Per_CPU_Change_state(
@@ -30,14 +31,22 @@
     _CPU_SMP_Processor_event_broadcast();
   }
 
-  void _Per_CPU_Wait_for_state(
+  Per_CPU_State _Per_CPU_Wait_for_state(
     const Per_CPU_Control *per_cpu,
     Per_CPU_State desired_state
   )
   {
-    while ( per_cpu->state != desired_state ) {
+    Per_CPU_State state = per_cpu->state;
+
+    _Assert( desired_state != 0 );
+
+    while ( (state & desired_state) == 0 ) {
       _CPU_SMP_Processor_event_receive();
+
+       state = per_cpu->state;
     }
+
+    return state;
   }
 #else
   /*
diff --git a/cpukit/score/src/smp.c b/cpukit/score/src/smp.c
index 59036eb..445a56a 100644
--- a/cpukit/score/src/smp.c
+++ b/cpukit/score/src/smp.c
@@ -24,10 +24,6 @@
 #include <rtems/score/threadimpl.h>
 #include <rtems/config.h>
 
-#if defined(RTEMS_DEBUG)
-  #include <rtems/bspIo.h>
-#endif
-
 void _SMP_Handler_initialize( void )
 {
   uint32_t max_cpus = rtems_configuration_get_maximum_processors();
@@ -47,69 +43,44 @@ void _SMP_Handler_initialize( void )
   _SMP_Processor_count = max_cpus;
 }
 
-void _SMP_Start_multitasking_on_secondary_processor( void )
-{
-  Per_CPU_Control *self_cpu = _Per_CPU_Get();
-
-  #if defined(RTEMS_DEBUG)
-    printk( "Made it to %d -- ", _Per_CPU_Get_index( self_cpu ) );
-  #endif
-
-  _Per_CPU_Change_state( self_cpu, PER_CPU_STATE_READY_TO_BEGIN_MULTITASKING );
-
-  _Per_CPU_Wait_for_state( self_cpu, PER_CPU_STATE_BEGIN_MULTITASKING );
-
-  _Thread_Start_multitasking();
-}
-
-void _SMP_Send_message( uint32_t cpu, uint32_t message )
-{
-  Per_CPU_Control *per_cpu = _Per_CPU_Get_by_index( cpu );
-  ISR_Level level;
-
-  _Per_CPU_ISR_disable_and_acquire( per_cpu, level );
-  per_cpu->message |= message;
-  _Per_CPU_Release_and_ISR_enable( per_cpu, level );
-
-  _CPU_SMP_Send_interrupt( cpu );
-}
-
-void _SMP_Broadcast_message( uint32_t message )
+void _SMP_Request_start_multitasking_on_secondary_processors( void )
 {
   uint32_t self = _SMP_Get_current_processor();
   uint32_t ncpus = _SMP_Get_processor_count();
   uint32_t cpu;
 
-  _Assert_Thread_dispatching_repressed();
-
   for ( cpu = 0 ; cpu < ncpus ; ++cpu ) {
+    Per_CPU_Control *per_cpu = _Per_CPU_Get_by_index( cpu );
+
     if ( cpu != self ) {
-      _SMP_Send_message( cpu, message );
+      _Per_CPU_Wait_for_state(
+        per_cpu,
+        PER_CPU_STATE_READY_TO_START_MULTITASKING
+      );
+
+      _Per_CPU_Change_state( per_cpu, PER_CPU_STATE_START_MULTITASKING );
     }
   }
 }
 
-void _SMP_Request_other_cores_to_perform_first_context_switch( void )
+void _SMP_Start_multitasking_on_secondary_processor( void )
 {
-  uint32_t self = _SMP_Get_current_processor();
-  uint32_t ncpus = _SMP_Get_processor_count();
-  uint32_t cpu;
+  Per_CPU_Control *self_cpu = _Per_CPU_Get();
+  Per_CPU_State state;
 
-  for ( cpu = 0 ; cpu < ncpus ; ++cpu ) {
-    Per_CPU_Control *per_cpu = _Per_CPU_Get_by_index( cpu );
+  _Per_CPU_Change_state( self_cpu, PER_CPU_STATE_READY_TO_START_MULTITASKING );
 
-    if ( cpu != self ) {
-      _Per_CPU_Wait_for_state(
-        per_cpu,
-        PER_CPU_STATE_READY_TO_BEGIN_MULTITASKING
-      );
+  state =
+    _Per_CPU_Wait_for_state( self_cpu, PER_CPU_STATE_START_MULTITASKING );
 
-      _Per_CPU_Change_state( per_cpu, PER_CPU_STATE_BEGIN_MULTITASKING );
-    }
+  if ( state == PER_CPU_STATE_START_MULTITASKING ) {
+    _Thread_Start_multitasking();
+  } else {
+    rtems_fatal( RTEMS_FATAL_SOURCE_SMP, SMP_FATAL_EARLY_SHUTDOWN );
   }
 }
 
-void _SMP_Request_other_cores_to_shutdown( void )
+void _SMP_Request_processors_to_shutdown( void )
 {
   uint32_t self = _SMP_Get_current_processor();
 
@@ -123,12 +94,52 @@ void _SMP_Request_other_cores_to_shutdown( void )
   uint32_t cpu;
 
   for ( cpu = 0 ; cpu < ncpus ; ++cpu ) {
-    if ( cpu != self ) {
-      const Per_CPU_Control *per_cpu = _Per_CPU_Get_by_index( cpu );
+    Per_CPU_Control *per_cpu = _Per_CPU_Get_by_index( cpu );
 
-      if ( per_cpu->state != PER_CPU_STATE_BEFORE_INITIALIZATION ) {
-        _SMP_Send_message( cpu, SMP_MESSAGE_SHUTDOWN );
+    if ( cpu != self ) {
+      switch ( _Per_CPU_Get_state( per_cpu ) ) {
+        case PER_CPU_STATE_READY_TO_START_MULTITASKING:
+          _Per_CPU_Change_state( per_cpu, PER_CPU_STATE_DO_SHUTDOWN );
+          break;
+        case PER_CPU_STATE_START_MULTITASKING:
+        case PER_CPU_STATE_UP:
+          _SMP_Send_message( cpu, SMP_MESSAGE_SHUTDOWN );
+          break;
+        case PER_CPU_STATE_DO_SHUTDOWN:
+        case PER_CPU_STATE_SHUTDOWN:
+        case PER_CPU_STATE_BEFORE_INITIALIZATION:
+          /* Nothing to do */
+          break;
       }
+    } else {
+      _Per_CPU_Change_state( per_cpu, PER_CPU_STATE_SHUTDOWN );
+    }
+  }
+}
+
+void _SMP_Send_message( uint32_t cpu, uint32_t message )
+{
+  Per_CPU_Control *per_cpu = _Per_CPU_Get_by_index( cpu );
+  ISR_Level level;
+
+  _Per_CPU_ISR_disable_and_acquire( per_cpu, level );
+  per_cpu->message |= message;
+  _Per_CPU_Release_and_ISR_enable( per_cpu, level );
+
+  _CPU_SMP_Send_interrupt( cpu );
+}
+
+void _SMP_Broadcast_message( uint32_t message )
+{
+  uint32_t self = _SMP_Get_current_processor();
+  uint32_t ncpus = _SMP_Get_processor_count();
+  uint32_t cpu;
+
+  _Assert_Thread_dispatching_repressed();
+
+  for ( cpu = 0 ; cpu < ncpus ; ++cpu ) {
+    if ( cpu != self ) {
+      _SMP_Send_message( cpu, message );
     }
   }
 }
diff --git a/testsuites/smptests/Makefile.am b/testsuites/smptests/Makefile.am
index 023b7e9..7b610b5 100644
--- a/testsuites/smptests/Makefile.am
+++ b/testsuites/smptests/Makefile.am
@@ -11,6 +11,7 @@ SUBDIRS += smp07
 SUBDIRS += smp08
 SUBDIRS += smp09
 SUBDIRS += smpatomic01
+SUBDIRS += smpfatal01
 SUBDIRS += smplock01
 SUBDIRS += smpmigration01
 SUBDIRS += smpschedule01
diff --git a/testsuites/smptests/configure.ac b/testsuites/smptests/configure.ac
index 5c68772..475ee9c 100644
--- a/testsuites/smptests/configure.ac
+++ b/testsuites/smptests/configure.ac
@@ -65,6 +65,7 @@ smp07/Makefile
 smp08/Makefile
 smp09/Makefile
 smpatomic01/Makefile
+smpfatal01/Makefile
 smplock01/Makefile
 smpmigration01/Makefile
 smppsxsignal01/Makefile
diff --git a/testsuites/smptests/smpfatal01/Makefile.am b/testsuites/smptests/smpfatal01/Makefile.am
new file mode 100644
index 0000000..2aaee2b
--- /dev/null
+++ b/testsuites/smptests/smpfatal01/Makefile.am
@@ -0,0 +1,19 @@
+rtems_tests_PROGRAMS = smpfatal01
+smpfatal01_SOURCES = init.c
+
+dist_rtems_tests_DATA = smpfatal01.scn smpfatal01.doc
+
+include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP at .cfg
+include $(top_srcdir)/../automake/compile.am
+include $(top_srcdir)/../automake/leaf.am
+
+AM_CPPFLAGS += -I$(top_srcdir)/../support/include
+
+LINK_OBJS = $(smpfatal01_OBJECTS)
+LINK_LIBS = $(smpfatal01_LDLIBS)
+
+smpfatal01$(EXEEXT): $(smpfatal01_OBJECTS) $(smpfatal01_DEPENDENCIES)
+	@rm -f smpfatal01$(EXEEXT)
+	$(make-exe)
+
+include $(top_srcdir)/../automake/local.am
diff --git a/testsuites/smptests/smpfatal01/init.c b/testsuites/smptests/smpfatal01/init.c
new file mode 100644
index 0000000..e6b2eee
--- /dev/null
+++ b/testsuites/smptests/smpfatal01/init.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2014 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Dornierstr. 4
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+  #include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/score/percpu.h>
+#include <rtems/score/smpimpl.h>
+
+#include "tmacros.h"
+
+#define MAX_CPUS 32
+
+static uint32_t main_cpu;
+
+static void Init(rtems_task_argument arg)
+{
+  rtems_test_assert(0);
+}
+
+static void fatal_extension(
+  rtems_fatal_source source,
+  bool is_internal,
+  rtems_fatal_code code
+)
+{
+  if (source != RTEMS_FATAL_SOURCE_ASSERT) {
+    uint32_t self_cpu = rtems_smp_get_current_processor();
+
+    rtems_test_assert(!is_internal);
+
+    if (self_cpu == main_cpu) {
+      uint32_t cpu_count = rtems_smp_get_processor_count();
+      uint32_t cpu;
+
+      rtems_test_assert(source == RTEMS_FATAL_SOURCE_APPLICATION);
+      rtems_test_assert(code == 0xdeadbeef);
+
+      for (cpu = 0; 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 );
+
+        if (cpu == self_cpu) {
+          rtems_test_assert(state == PER_CPU_STATE_SHUTDOWN);
+        } else if (cpu < cpu_count) {
+          rtems_test_assert(
+             state == PER_CPU_STATE_READY_TO_START_MULTITASKING
+              || state == PER_CPU_STATE_DO_SHUTDOWN
+              || state == PER_CPU_STATE_SHUTDOWN
+          );
+          state = _Per_CPU_Wait_for_state(
+            per_cpu,
+            PER_CPU_STATE_SHUTDOWN
+          );
+          rtems_test_assert(state == PER_CPU_STATE_SHUTDOWN);
+        } else {
+          rtems_test_assert(state == PER_CPU_STATE_BEFORE_INITIALIZATION);
+        }
+      }
+
+      printk( "*** END OF TEST SMPFATAL 1 ***\n" );
+    } else {
+      rtems_test_assert(source == RTEMS_FATAL_SOURCE_SMP);
+      rtems_test_assert(code == SMP_FATAL_EARLY_SHUTDOWN);
+    }
+  }
+}
+
+static rtems_status_code test_driver_init(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+)
+{
+  uint32_t self_cpu = rtems_smp_get_current_processor();
+  uint32_t cpu_count = rtems_smp_get_processor_count();
+  uint32_t cpu;
+
+  printk("\n\n*** TEST SMPFATAL 1 ***\n");
+
+  rtems_test_assert(rtems_configuration_get_maximum_processors() == MAX_CPUS);
+
+  main_cpu = self_cpu;
+
+  for (cpu = 0; 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 );
+
+    if (cpu == self_cpu) {
+      rtems_test_assert(state == PER_CPU_STATE_BEFORE_INITIALIZATION);
+    } else if (cpu < cpu_count) {
+      rtems_test_assert(
+        state == PER_CPU_STATE_BEFORE_INITIALIZATION
+          || state == PER_CPU_STATE_READY_TO_START_MULTITASKING
+      );
+      state = _Per_CPU_Wait_for_state(
+        per_cpu,
+        PER_CPU_STATE_READY_TO_START_MULTITASKING
+      );
+      rtems_test_assert(state == PER_CPU_STATE_READY_TO_START_MULTITASKING);
+    } else {
+      rtems_test_assert(state == PER_CPU_STATE_BEFORE_INITIALIZATION);
+    }
+  }
+
+  rtems_fatal(RTEMS_FATAL_SOURCE_APPLICATION, 0xdeadbeef);
+}
+
+#define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+
+#define CONFIGURE_APPLICATION_EXTRA_DRIVERS \
+  { .initialization_entry = test_driver_init }
+
+#define CONFIGURE_INITIAL_EXTENSIONS { .fatal = fatal_extension }
+
+#define CONFIGURE_SMP_APPLICATION
+
+#define CONFIGURE_SMP_MAXIMUM_PROCESSORS MAX_CPUS
+
+#define CONFIGURE_MAXIMUM_TASKS 1
+
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+
+#define CONFIGURE_INIT
+
+#include <rtems/confdefs.h>
diff --git a/testsuites/smptests/smpfatal01/smpfatal01.doc b/testsuites/smptests/smpfatal01/smpfatal01.doc
new file mode 100644
index 0000000..831fabc
--- /dev/null
+++ b/testsuites/smptests/smpfatal01/smpfatal01.doc
@@ -0,0 +1,12 @@
+This file describes the directives and concepts tested by this test set.
+
+test set name: smpfatal01
+
+directives:
+
+  - _SMP_Request_processors_to_shutdown()
+
+concepts:
+
+  - Ensure that the system termination in case of fatal errors during driver
+    initialization works.
diff --git a/testsuites/smptests/smpfatal01/smpfatal01.scn b/testsuites/smptests/smpfatal01/smpfatal01.scn
new file mode 100644
index 0000000..0b67121
--- /dev/null
+++ b/testsuites/smptests/smpfatal01/smpfatal01.scn
@@ -0,0 +1,2 @@
+*** TEST SMPFATAL 1 ***
+*** END OF TEST SMPFATAL 1 ***
-- 
1.7.7




More information about the devel mailing list