forked from Imagelibrary/rtems
score: SMP initialization and shutdown changes
Rename _SMP_Request_other_cores_to_perform_first_context_switch() into _SMP_Request_start_multitasking() since this requests now a multitasking start on all configured and available processors. The name corresponds _Thread_Start_multitasking() and _SMP_Start_multitasking_on_secondary_processor() actions issued in response to this request. 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_REQUEST_START_MULTITASKING. Rename _SMP_Request_other_cores_to_shutdown() into _SMP_Request_shutdown(). Add a per-CPU state lock to protect all changes. This was necessary to offer a controlled shutdown of the system (atomic read/writes alone are not sufficient for this kind of synchronization). Add documentation for Per_CPU_State. Delete debug output. New tests smptests/smpfatal01 and smptests/smpfatal02.
This commit is contained in:
@@ -11,6 +11,8 @@ SUBDIRS += smp07
|
||||
SUBDIRS += smp08
|
||||
SUBDIRS += smp09
|
||||
SUBDIRS += smpatomic01
|
||||
SUBDIRS += smpfatal01
|
||||
SUBDIRS += smpfatal02
|
||||
SUBDIRS += smplock01
|
||||
SUBDIRS += smpmigration01
|
||||
SUBDIRS += smpschedule01
|
||||
|
||||
@@ -65,6 +65,8 @@ smp07/Makefile
|
||||
smp08/Makefile
|
||||
smp09/Makefile
|
||||
smpatomic01/Makefile
|
||||
smpfatal01/Makefile
|
||||
smpfatal02/Makefile
|
||||
smplock01/Makefile
|
||||
smpmigration01/Makefile
|
||||
smppsxsignal01/Makefile
|
||||
|
||||
19
testsuites/smptests/smpfatal01/Makefile.am
Normal file
19
testsuites/smptests/smpfatal01/Makefile.am
Normal file
@@ -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@.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
|
||||
130
testsuites/smptests/smpfatal01/init.c
Normal file
130
testsuites/smptests/smpfatal01/init.c
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (c) 2014 embedded brains GmbH. All rights reserved.
|
||||
*
|
||||
* embedded brains GmbH
|
||||
* Dornierstr. 4
|
||||
* 82178 Puchheim
|
||||
* Germany
|
||||
* <rtems@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 <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define MAX_CPUS 32
|
||||
|
||||
static uint32_t main_cpu;
|
||||
|
||||
static void Init(rtems_task_argument arg)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
static void end_of_test(void)
|
||||
{
|
||||
printk( "*** END OF TEST SMPFATAL 1 ***\n" );
|
||||
}
|
||||
|
||||
static void fatal_extension(
|
||||
rtems_fatal_source source,
|
||||
bool is_internal,
|
||||
rtems_fatal_code code
|
||||
)
|
||||
{
|
||||
if (source == RTEMS_FATAL_SOURCE_SMP) {
|
||||
uint32_t self = rtems_smp_get_current_processor();
|
||||
|
||||
assert(!is_internal);
|
||||
assert(code == SMP_FATAL_SHUTDOWN);
|
||||
|
||||
if (self == main_cpu) {
|
||||
uint32_t 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->state;
|
||||
|
||||
assert(state == PER_CPU_STATE_SHUTDOWN);
|
||||
}
|
||||
|
||||
end_of_test();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static rtems_status_code test_driver_init(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void *arg
|
||||
)
|
||||
{
|
||||
uint32_t self = rtems_smp_get_current_processor();
|
||||
uint32_t cpu_count = rtems_smp_get_processor_count();
|
||||
uint32_t cpu;
|
||||
|
||||
printk("\n\n*** TEST SMPFATAL 1 ***\n");
|
||||
|
||||
assert(rtems_configuration_get_maximum_processors() == MAX_CPUS);
|
||||
|
||||
main_cpu = self;
|
||||
|
||||
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->state;
|
||||
|
||||
if (cpu == self) {
|
||||
assert(state == PER_CPU_STATE_INITIAL);
|
||||
} else if (cpu < cpu_count) {
|
||||
assert(
|
||||
state == PER_CPU_STATE_INITIAL
|
||||
|| state == PER_CPU_STATE_READY_TO_START_MULTITASKING
|
||||
);
|
||||
} else {
|
||||
assert(state == PER_CPU_STATE_INITIAL);
|
||||
}
|
||||
}
|
||||
|
||||
if (cpu_count > 1) {
|
||||
uint32_t other = (self + 1) % cpu_count;
|
||||
Per_CPU_Control *per_cpu = _Per_CPU_Get_by_index( other );
|
||||
|
||||
per_cpu->state = PER_CPU_STATE_SHUTDOWN;
|
||||
} else {
|
||||
end_of_test();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
#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>
|
||||
12
testsuites/smptests/smpfatal01/smpfatal01.doc
Normal file
12
testsuites/smptests/smpfatal01/smpfatal01.doc
Normal file
@@ -0,0 +1,12 @@
|
||||
This file describes the directives and concepts tested by this test set.
|
||||
|
||||
test set name: smpfatal01
|
||||
|
||||
directives:
|
||||
|
||||
- _Per_CPU_State_change()
|
||||
|
||||
concepts:
|
||||
|
||||
- Ensure that the system termination in case of shutdown detection at a
|
||||
secondary processors works during driver initialization.
|
||||
2
testsuites/smptests/smpfatal01/smpfatal01.scn
Normal file
2
testsuites/smptests/smpfatal01/smpfatal01.scn
Normal file
@@ -0,0 +1,2 @@
|
||||
*** TEST SMPFATAL 1 ***
|
||||
*** END OF TEST SMPFATAL 1 ***
|
||||
19
testsuites/smptests/smpfatal02/Makefile.am
Normal file
19
testsuites/smptests/smpfatal02/Makefile.am
Normal file
@@ -0,0 +1,19 @@
|
||||
rtems_tests_PROGRAMS = smpfatal02
|
||||
smpfatal02_SOURCES = init.c
|
||||
|
||||
dist_rtems_tests_DATA = smpfatal02.scn smpfatal02.doc
|
||||
|
||||
include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
|
||||
include $(top_srcdir)/../automake/compile.am
|
||||
include $(top_srcdir)/../automake/leaf.am
|
||||
|
||||
AM_CPPFLAGS += -I$(top_srcdir)/../support/include
|
||||
|
||||
LINK_OBJS = $(smpfatal02_OBJECTS)
|
||||
LINK_LIBS = $(smpfatal02_LDLIBS)
|
||||
|
||||
smpfatal02$(EXEEXT): $(smpfatal02_OBJECTS) $(smpfatal02_DEPENDENCIES)
|
||||
@rm -f smpfatal02$(EXEEXT)
|
||||
$(make-exe)
|
||||
|
||||
include $(top_srcdir)/../automake/local.am
|
||||
135
testsuites/smptests/smpfatal02/init.c
Normal file
135
testsuites/smptests/smpfatal02/init.c
Normal file
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright (c) 2014 embedded brains GmbH. All rights reserved.
|
||||
*
|
||||
* embedded brains GmbH
|
||||
* Dornierstr. 4
|
||||
* 82178 Puchheim
|
||||
* Germany
|
||||
* <rtems@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 <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define MAX_CPUS 32
|
||||
|
||||
static uint32_t main_cpu;
|
||||
|
||||
static void Init(rtems_task_argument arg)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
static void end_of_test(void)
|
||||
{
|
||||
printk( "*** END OF TEST SMPFATAL 2 ***\n" );
|
||||
}
|
||||
|
||||
static void fatal_extension(
|
||||
rtems_fatal_source source,
|
||||
bool is_internal,
|
||||
rtems_fatal_code code
|
||||
)
|
||||
{
|
||||
if (
|
||||
source == RTEMS_FATAL_SOURCE_APPLICATION
|
||||
|| source == RTEMS_FATAL_SOURCE_SMP
|
||||
) {
|
||||
uint32_t self = rtems_smp_get_current_processor();
|
||||
|
||||
assert(!is_internal);
|
||||
|
||||
if (self == main_cpu) {
|
||||
uint32_t cpu;
|
||||
|
||||
assert(source == RTEMS_FATAL_SOURCE_APPLICATION);
|
||||
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->state;
|
||||
|
||||
assert(state == PER_CPU_STATE_SHUTDOWN);
|
||||
}
|
||||
|
||||
end_of_test();
|
||||
} else {
|
||||
assert(source == RTEMS_FATAL_SOURCE_SMP);
|
||||
assert(code == SMP_FATAL_SHUTDOWN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static rtems_status_code test_driver_init(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void *arg
|
||||
)
|
||||
{
|
||||
uint32_t self = rtems_smp_get_current_processor();
|
||||
uint32_t cpu_count = rtems_smp_get_processor_count();
|
||||
uint32_t cpu;
|
||||
|
||||
printk("\n\n*** TEST SMPFATAL 2 ***\n");
|
||||
|
||||
assert(rtems_configuration_get_maximum_processors() == MAX_CPUS);
|
||||
|
||||
main_cpu = self;
|
||||
|
||||
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->state;
|
||||
|
||||
if (cpu == self) {
|
||||
assert(state == PER_CPU_STATE_INITIAL);
|
||||
} else if (cpu < cpu_count) {
|
||||
assert(
|
||||
state == PER_CPU_STATE_INITIAL
|
||||
|| state == PER_CPU_STATE_READY_TO_START_MULTITASKING
|
||||
);
|
||||
} else {
|
||||
assert(state == PER_CPU_STATE_INITIAL);
|
||||
}
|
||||
}
|
||||
|
||||
if (cpu_count > 1) {
|
||||
rtems_fatal(RTEMS_FATAL_SOURCE_APPLICATION, 0xdeadbeef);
|
||||
} else {
|
||||
end_of_test();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
#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>
|
||||
12
testsuites/smptests/smpfatal02/smpfatal02.doc
Normal file
12
testsuites/smptests/smpfatal02/smpfatal02.doc
Normal file
@@ -0,0 +1,12 @@
|
||||
This file describes the directives and concepts tested by this test set.
|
||||
|
||||
test set name: smpfatal02
|
||||
|
||||
directives:
|
||||
|
||||
- _Per_CPU_State_change()
|
||||
|
||||
concepts:
|
||||
|
||||
- Ensure that the system termination in case of fatal errors during driver
|
||||
initialization works.
|
||||
2
testsuites/smptests/smpfatal02/smpfatal02.scn
Normal file
2
testsuites/smptests/smpfatal02/smpfatal02.scn
Normal file
@@ -0,0 +1,2 @@
|
||||
*** TEST SMPFATAL 2 ***
|
||||
*** END OF TEST SMPFATAL 2 ***
|
||||
Reference in New Issue
Block a user