[rtems commit] score: Add SMP test message handler

Sebastian Huber sebh at rtems.org
Mon May 5 07:36:18 UTC 2014


Module:    rtems
Branch:    master
Commit:    145becf0759d39d7779760af8f1e11d623997938
Changeset: http://git.rtems.org/rtems/commit/?id=145becf0759d39d7779760af8f1e11d623997938

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Fri May  2 15:33:23 2014 +0200

score: Add SMP test message handler

This handler can be used to test the inter-processor interrupt
implementation.

---

 cpukit/score/include/rtems/score/smpimpl.h |   28 ++++
 cpukit/score/src/smp.c                     |    8 +
 testsuites/smptests/Makefile.am            |    1 +
 testsuites/smptests/configure.ac           |    1 +
 testsuites/smptests/smpipi01/Makefile.am   |   19 +++
 testsuites/smptests/smpipi01/init.c        |  207 ++++++++++++++++++++++++++++
 testsuites/smptests/smpipi01/smpipi01.doc  |   11 ++
 testsuites/smptests/smpipi01/smpipi01.scn  |    6 +
 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 27cf188..1868546 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 34db46a..3094fe3 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 f16d396..d82503a 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 e3857f1..27f7f54 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 0000000..a00f107
--- /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 at .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 0000000..db0688c
--- /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 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.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 0000000..72fe5d2
--- /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 0000000..255e951
--- /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 ***




More information about the vc mailing list