summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2014-05-02 15:33:23 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2014-05-05 08:26:27 +0200
commit145becf0759d39d7779760af8f1e11d623997938 (patch)
tree104e027282b896e3cf1a35bfcaecd0a6bf25505c
parentscore: SMP_FATAL_SCHEDULER_WITHOUT_PROCESSORS (diff)
downloadrtems-145becf0759d39d7779760af8f1e11d623997938.tar.bz2
score: Add SMP test message handler
This handler can be used to test the inter-processor interrupt implementation.
-rw-r--r--cpukit/score/include/rtems/score/smpimpl.h28
-rw-r--r--cpukit/score/src/smp.c8
-rw-r--r--testsuites/smptests/Makefile.am1
-rw-r--r--testsuites/smptests/configure.ac1
-rw-r--r--testsuites/smptests/smpipi01/Makefile.am19
-rw-r--r--testsuites/smptests/smpipi01/init.c207
-rw-r--r--testsuites/smptests/smpipi01/smpipi01.doc11
-rw-r--r--testsuites/smptests/smpipi01/smpipi01.scn6
8 files changed, 281 insertions, 0 deletions
diff --git a/cpukit/score/include/rtems/score/smpimpl.h b/cpukit/score/include/rtems/score/smpimpl.h
index 27cf188131..1868546996 100644
--- a/cpukit/score/include/rtems/score/smpimpl.h
+++ b/cpukit/score/include/rtems/score/smpimpl.h
@@ -44,6 +44,13 @@ extern "C" {
#define SMP_MESSAGE_SHUTDOWN UINT32_C(0x1)
/**
+ * @brief SMP message to request a test handler invocation.
+ *
+ * @see _SMP_Send_message().
+ */
+#define SMP_MESSAGE_TEST UINT32_C(0x2)
+
+/**
* @brief SMP fatal codes.
*/
typedef enum {
@@ -101,6 +108,23 @@ static inline void _SMP_Fatal( SMP_Fatal_code code )
void _SMP_Start_multitasking_on_secondary_processor( void )
RTEMS_COMPILER_NO_RETURN_ATTRIBUTE;
+typedef void ( *SMP_Test_message_handler )( Per_CPU_Control *cpu_self );
+
+extern SMP_Test_message_handler _SMP_Test_message_handler;
+
+/**
+ * @brief Sets the handler for test messages.
+ *
+ * This handler can be used to test the inter-processor interrupt
+ * implementation.
+ */
+static inline void _SMP_Set_test_message_handler(
+ SMP_Test_message_handler handler
+)
+{
+ _SMP_Test_message_handler = handler;
+}
+
/**
* @brief Interrupt handler for inter-processor interrupts.
*/
@@ -121,6 +145,10 @@ static inline void _SMP_Inter_processor_interrupt_handler( void )
rtems_fatal( RTEMS_FATAL_SOURCE_SMP, SMP_FATAL_SHUTDOWN );
/* does not continue past here */
}
+
+ if ( ( message & SMP_MESSAGE_TEST ) != 0 ) {
+ ( *_SMP_Test_message_handler )( cpu_self );
+ }
}
}
diff --git a/cpukit/score/src/smp.c b/cpukit/score/src/smp.c
index 34db46ad1e..3094fe31f8 100644
--- a/cpukit/score/src/smp.c
+++ b/cpukit/score/src/smp.c
@@ -166,3 +166,11 @@ void _SMP_Broadcast_message( uint32_t message )
}
}
}
+
+static void _SMP_Test_message_default_handler( Per_CPU_Control *cpu_self )
+{
+ (void) cpu_self;
+}
+
+SMP_Test_message_handler _SMP_Test_message_handler =
+ _SMP_Test_message_default_handler;
diff --git a/testsuites/smptests/Makefile.am b/testsuites/smptests/Makefile.am
index f16d39664d..d82503a17c 100644
--- a/testsuites/smptests/Makefile.am
+++ b/testsuites/smptests/Makefile.am
@@ -18,6 +18,7 @@ SUBDIRS += smpfatal04
SUBDIRS += smpfatal05
SUBDIRS += smpfatal07
SUBDIRS += smpfatal08
+SUBDIRS += smpipi01
SUBDIRS += smpload01
SUBDIRS += smplock01
SUBDIRS += smpmigration01
diff --git a/testsuites/smptests/configure.ac b/testsuites/smptests/configure.ac
index e3857f1e0f..27f7f542b3 100644
--- a/testsuites/smptests/configure.ac
+++ b/testsuites/smptests/configure.ac
@@ -73,6 +73,7 @@ smpfatal04/Makefile
smpfatal05/Makefile
smpfatal07/Makefile
smpfatal08/Makefile
+smpipi01/Makefile
smpload01/Makefile
smplock01/Makefile
smpmigration01/Makefile
diff --git a/testsuites/smptests/smpipi01/Makefile.am b/testsuites/smptests/smpipi01/Makefile.am
new file mode 100644
index 0000000000..a00f1076ca
--- /dev/null
+++ b/testsuites/smptests/smpipi01/Makefile.am
@@ -0,0 +1,19 @@
+rtems_tests_PROGRAMS = smpipi01
+smpipi01_SOURCES = init.c
+
+dist_rtems_tests_DATA = smpipi01.scn smpipi01.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 = $(smpipi01_OBJECTS)
+LINK_LIBS = $(smpipi01_LDLIBS)
+
+smpipi01$(EXEEXT): $(smpipi01_OBJECTS) $(smpipi01_DEPENDENCIES)
+ @rm -f smpipi01$(EXEEXT)
+ $(make-exe)
+
+include $(top_srcdir)/../automake/local.am
diff --git a/testsuites/smptests/smpipi01/init.c b/testsuites/smptests/smpipi01/init.c
new file mode 100644
index 0000000000..db0688c5ee
--- /dev/null
+++ b/testsuites/smptests/smpipi01/init.c
@@ -0,0 +1,207 @@
+/*
+ * 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.org/license/LICENSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include <rtems/score/smpimpl.h>
+#include <rtems/score/smpbarrier.h>
+#include <rtems/counter.h>
+#include <rtems.h>
+
+#include <stdio.h>
+
+#include "tmacros.h"
+
+const char rtems_test_name[] = "SMPIPI 1";
+
+#define CPU_COUNT 32
+
+typedef struct {
+ uint32_t value;
+ uint32_t cache_line_separation[31];
+} test_counter;
+
+typedef struct {
+ test_counter counters[CPU_COUNT];
+ uint32_t copy_counters[CPU_COUNT];
+ SMP_barrier_Control barrier;
+ SMP_barrier_State main_barrier_state;
+ SMP_barrier_State worker_barrier_state;
+} test_context;
+
+static test_context test_instance = {
+ .barrier = SMP_BARRIER_CONTROL_INITIALIZER,
+ .main_barrier_state = SMP_BARRIER_STATE_INITIALIZER,
+ .worker_barrier_state = SMP_BARRIER_STATE_INITIALIZER
+};
+
+static void barrier(
+ test_context *ctx,
+ SMP_barrier_State *state
+)
+{
+ _SMP_barrier_Wait(&ctx->barrier, state, 2);
+}
+
+static void barrier_handler(Per_CPU_Control *cpu_self)
+{
+ test_context *ctx = &test_instance;
+ uint32_t cpu_index_self = _Per_CPU_Get_index(cpu_self);
+ SMP_barrier_State *bs = &ctx->worker_barrier_state;
+
+ ++ctx->counters[cpu_index_self].value;
+
+ /* (A) */
+ barrier(ctx, bs);
+
+ /* (B) */
+ barrier(ctx, bs);
+
+ /* (C) */
+ barrier(ctx, bs);
+}
+
+static void test_send_message_while_processing_a_message(
+ test_context *ctx
+)
+{
+ uint32_t cpu_count = rtems_get_processor_count();
+ uint32_t cpu_index_self = rtems_get_current_processor();
+ uint32_t cpu_index;
+ SMP_barrier_State *bs = &ctx->main_barrier_state;
+
+ _SMP_Set_test_message_handler(barrier_handler);
+
+ for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) {
+ if (cpu_index != cpu_index_self) {
+ _SMP_Send_message(cpu_index, SMP_MESSAGE_TEST);
+
+ /* (A) */
+ barrier(ctx, bs);
+
+ rtems_test_assert(ctx->counters[cpu_index].value == 1);
+ _SMP_Send_message(cpu_index, SMP_MESSAGE_TEST);
+
+ /* (B) */
+ barrier(ctx, bs);
+
+ rtems_test_assert(ctx->counters[cpu_index].value == 1);
+
+ /* (C) */
+ barrier(ctx, bs);
+
+ /* (A) */
+ barrier(ctx, bs);
+
+ rtems_test_assert(ctx->counters[cpu_index].value == 2);
+
+ /* (B) */
+ barrier(ctx, bs);
+
+ /* (C) */
+ barrier(ctx, bs);
+
+ ctx->counters[cpu_index].value = 0;
+ }
+ }
+}
+
+static void counter_handler(Per_CPU_Control *cpu_self)
+{
+ test_context *ctx = &test_instance;
+ uint32_t cpu_index_self = _Per_CPU_Get_index(cpu_self);
+
+ ++ctx->counters[cpu_index_self].value;
+}
+
+static void test_send_message_flood(
+ test_context *ctx
+)
+{
+ uint32_t cpu_count = rtems_get_processor_count();
+ uint32_t cpu_index_self = rtems_get_current_processor();
+ uint32_t cpu_index;
+
+ _SMP_Set_test_message_handler(counter_handler);
+
+ for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) {
+ uint32_t i;
+
+ /* Wait 1us so that all outstanding messages have been processed */
+ rtems_counter_delay_nanoseconds(1000000);
+
+ for (i = 0; i < cpu_count; ++i) {
+ if (i != cpu_index) {
+ ctx->copy_counters[i] = ctx->counters[i].value;
+ }
+ }
+
+ for (i = 0; i < 100000; ++i) {
+ _SMP_Send_message(cpu_index, SMP_MESSAGE_TEST);
+ }
+
+ for (i = 0; i < cpu_count; ++i) {
+ if (i != cpu_index) {
+ rtems_test_assert(ctx->copy_counters[i] == ctx->counters[i].value);
+ }
+ }
+ }
+
+ for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) {
+ printf(
+ "inter-processor interrupts for processor %"
+ PRIu32 "%s: %" PRIu32 "\n",
+ cpu_index,
+ cpu_index == cpu_index_self ? " (main)" : "",
+ ctx->counters[cpu_index].value
+ );
+ }
+}
+
+static void test(void)
+{
+ test_context *ctx = &test_instance;
+
+ test_send_message_while_processing_a_message(ctx);
+ test_send_message_flood(ctx);
+}
+
+static void Init(rtems_task_argument arg)
+{
+ TEST_BEGIN();
+
+ test();
+
+ TEST_END();
+ rtems_test_exit(0);
+}
+
+#define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+
+#define CONFIGURE_SMP_APPLICATION
+
+#define CONFIGURE_SMP_MAXIMUM_PROCESSORS CPU_COUNT
+
+#define CONFIGURE_MAXIMUM_TASKS 1
+
+#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
+
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+
+#define CONFIGURE_INIT
+
+#include <rtems/confdefs.h>
diff --git a/testsuites/smptests/smpipi01/smpipi01.doc b/testsuites/smptests/smpipi01/smpipi01.doc
new file mode 100644
index 0000000000..72fe5d23e2
--- /dev/null
+++ b/testsuites/smptests/smpipi01/smpipi01.doc
@@ -0,0 +1,11 @@
+This file describes the directives and concepts tested by this test set.
+
+test set name: smpipi01
+
+directives:
+
+ - _SMP_Send_message()
+
+concepts:
+
+ - Ensure that inter-processor interrupts work as expected.
diff --git a/testsuites/smptests/smpipi01/smpipi01.scn b/testsuites/smptests/smpipi01/smpipi01.scn
new file mode 100644
index 0000000000..255e9519d9
--- /dev/null
+++ b/testsuites/smptests/smpipi01/smpipi01.scn
@@ -0,0 +1,6 @@
+*** BEGIN OF TEST SMPIPI 1 ***
+inter-processor interrupts for processor 0: 12502
+inter-processor interrupts for processor 1: 12502
+inter-processor interrupts for processor 2: 12502
+inter-processor interrupts for processor 3 (main): 99987
+*** END OF TEST SMPIPI 1 ***