From 145becf0759d39d7779760af8f1e11d623997938 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Fri, 2 May 2014 15:33:23 +0200 Subject: score: Add SMP test message handler This handler can be used to test the inter-processor interrupt implementation. --- testsuites/smptests/smpipi01/init.c | 207 ++++++++++++++++++++++++++++++++++++ 1 file changed, 207 insertions(+) create mode 100644 testsuites/smptests/smpipi01/init.c (limited to 'testsuites/smptests/smpipi01/init.c') 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 + * + * + * 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 +#include +#include +#include + +#include + +#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 -- cgit v1.2.3