[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