From 79d03e30bfa8dd28eac90455725169ea7d052092 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Wed, 28 Aug 2013 14:52:43 +0200 Subject: smptests/smpatomic08: New test --- testsuites/smptests/Makefile.am | 1 + testsuites/smptests/configure.ac | 1 + testsuites/smptests/smpatomic08/Makefile.am | 19 ++ testsuites/smptests/smpatomic08/init.c | 343 ++++++++++++++++++++++++ testsuites/smptests/smpatomic08/smpatomic08.doc | 12 + testsuites/smptests/smpatomic08/smpatomic08.scn | 6 + 6 files changed, 382 insertions(+) create mode 100644 testsuites/smptests/smpatomic08/Makefile.am create mode 100644 testsuites/smptests/smpatomic08/init.c create mode 100644 testsuites/smptests/smpatomic08/smpatomic08.doc create mode 100644 testsuites/smptests/smpatomic08/smpatomic08.scn diff --git a/testsuites/smptests/Makefile.am b/testsuites/smptests/Makefile.am index add13bc4a4..55d612ff96 100644 --- a/testsuites/smptests/Makefile.am +++ b/testsuites/smptests/Makefile.am @@ -19,6 +19,7 @@ SUBDIRS += smpatomic04 SUBDIRS += smpatomic05 SUBDIRS += smpatomic06 SUBDIRS += smpatomic07 +SUBDIRS += smpatomic08 endif SUBDIRS += smplock01 SUBDIRS += smpmigration01 diff --git a/testsuites/smptests/configure.ac b/testsuites/smptests/configure.ac index c340136ca2..05b90561e0 100644 --- a/testsuites/smptests/configure.ac +++ b/testsuites/smptests/configure.ac @@ -53,6 +53,7 @@ smpatomic04/Makefile smpatomic05/Makefile smpatomic06/Makefile smpatomic07/Makefile +smpatomic08/Makefile smplock01/Makefile smpmigration01/Makefile smppsxsignal01/Makefile diff --git a/testsuites/smptests/smpatomic08/Makefile.am b/testsuites/smptests/smpatomic08/Makefile.am new file mode 100644 index 0000000000..f6abd55c49 --- /dev/null +++ b/testsuites/smptests/smpatomic08/Makefile.am @@ -0,0 +1,19 @@ +rtems_tests_PROGRAMS = smpatomic08 +smpatomic08_SOURCES = init.c + +dist_rtems_tests_DATA = smpatomic08.scn smpatomic08.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 = $(smpatomic08_OBJECTS) +LINK_LIBS = $(smpatomic08_LDLIBS) + +smpatomic08$(EXEEXT): $(smpatomic08_OBJECTS) $(smpatomic08_DEPENDENCIES) + @rm -f smpatomic08$(EXEEXT) + $(make-exe) + +include $(top_srcdir)/../automake/local.am diff --git a/testsuites/smptests/smpatomic08/init.c b/testsuites/smptests/smpatomic08/init.c new file mode 100644 index 0000000000..4b32a1ae70 --- /dev/null +++ b/testsuites/smptests/smpatomic08/init.c @@ -0,0 +1,343 @@ +/* + * Copyright (c) 2013 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.com/license/LICENSE. + */ + +#ifdef HAVE_CONFIG_H + #include "config.h" +#endif + +#include +#include + +#include "tmacros.h" + +/* FIXME: Add barrier to Score */ + +typedef struct { + Atomic_Uint value; + Atomic_Uint sense; +} SMP_barrier_Control; + +typedef struct { + uint_fast32_t sense; +} SMP_barrier_State; + +#define SMP_BARRIER_CONTROL_INITIALIZER \ + { ATOMIC_INITIALIZER_UINT( 0 ), ATOMIC_INITIALIZER_UINT( 0 ) } + +#define SMP_BARRIER_STATE_INITIALIZER { 0 } + +static void _SMP_barrier_Wait( + SMP_barrier_Control *control, + SMP_barrier_State *state, + uint_fast32_t count +) +{ + uint_fast32_t sense = ~state->sense; + uint_fast32_t previous_value; + + state->sense = sense; + + previous_value = _Atomic_Fetch_add_uint( + &control->value, + 1, + ATOMIC_ORDER_RELAXED + ); + + if ( previous_value + 1 == count ) { + _Atomic_Store_uint( &control->value, 0, ATOMIC_ORDER_RELAXED ); + _Atomic_Store_uint( &control->sense, sense, ATOMIC_ORDER_RELEASE ); + } else { + while ( + _Atomic_Load_uint( &control->sense, ATOMIC_ORDER_ACQUIRE ) != sense + ) { + /* Wait */ + } + } +} + +#define MASTER_PRIORITY 1 + +#define WORKER_PRIORITY 2 + +#define CPU_COUNT 32 + +typedef struct { + Atomic_Uint stop; + SMP_barrier_Control barrier; + size_t worker_count; + rtems_id stop_worker_timer_id; + Atomic_Uint global_uint; + uint_fast32_t per_worker_uint[CPU_COUNT]; + uint32_t flag_counter; + Atomic_Flag global_flag; +} test_context; + +typedef void (*test_case_init)(test_context *ctx); + +typedef void (*test_case)(test_context *ctx, size_t worker_index); + +static test_context test_instance = { + .stop = ATOMIC_INITIALIZER_UINT(0), + .barrier = SMP_BARRIER_CONTROL_INITIALIZER +}; + +static bool stop(test_context *ctx) +{ + return _Atomic_Load_uint(&ctx->stop, ATOMIC_ORDER_RELAXED) != 0; +} + +static bool is_master_worker(size_t worker_index) +{ + return worker_index == 0; +} + +static void test_init_atomic_add(test_context *ctx) +{ + _Atomic_Init_uint(&ctx->global_uint, 0); +} + +static void test_atomic_add_report(test_context *ctx) +{ + uint_fast32_t expected_counter = 0; + uint_fast32_t actual_counter; + size_t worker_index; + + printf("=== atomic add test case ==\n"); + + for (worker_index = 0; worker_index < ctx->worker_count; ++worker_index) { + uint_fast32_t worker_counter = ctx->per_worker_uint[worker_index]; + + expected_counter += worker_counter; + + printf( + "atomic add worker %zu counter: %" PRIuFAST32 "\n", + worker_index, + worker_counter + ); + } + + actual_counter = _Atomic_Load_uint(&ctx->global_uint, ATOMIC_ORDER_RELAXED); + + printf( + "global counter: expected = %" PRIuFAST32 ", actual = %" PRIuFAST32 "\n", + expected_counter, + actual_counter + ); + + rtems_test_assert(expected_counter == actual_counter); +} + +static void test_atomic_add(test_context *ctx, size_t worker_index) +{ + uint_fast32_t counter = 0; + + while (!stop(ctx)) { + ++counter; + _Atomic_Fetch_add_uint(&ctx->global_uint, 1, ATOMIC_ORDER_RELAXED); + } + + ctx->per_worker_uint[worker_index] = counter; + + if (is_master_worker(worker_index)) { + test_atomic_add_report(ctx); + } +} + +static void test_atomic_flag_report(test_context *ctx) +{ + uint_fast32_t expected_counter = 0; + uint_fast32_t actual_counter; + size_t worker_index; + + printf("=== atomic flag test case ===\n"); + + for (worker_index = 0; worker_index < ctx->worker_count; ++worker_index) { + uint_fast32_t worker_counter = ctx->per_worker_uint[worker_index]; + + expected_counter += worker_counter; + + printf( + "atomic flag worker %zu counter: %" PRIuFAST32 "\n", + worker_index, + worker_counter + ); + } + + actual_counter = _Atomic_Load_uint(&ctx->global_uint, ATOMIC_ORDER_RELAXED); + + printf( + "global flag counter: expected = %" PRIuFAST32 ", actual = %" PRIuFAST32 "\n", + expected_counter, + actual_counter + ); + + rtems_test_assert(expected_counter == actual_counter); +} + +static void test_init_atomic_flag(test_context *ctx) +{ + _Atomic_Flag_clear(&ctx->global_flag, ATOMIC_ORDER_RELEASE); + ctx->flag_counter = 0; +} + +static void test_atomic_flag(test_context *ctx, size_t worker_index) +{ + uint_fast32_t counter = 0; + + while (!stop(ctx)) { + while (!_Atomic_Flag_test_and_set(&ctx->global_flag, ATOMIC_ORDER_ACQUIRE)) { + /* Wait */ + } + + ++counter; + ++ctx->flag_counter; + + _Atomic_Flag_clear(&ctx->global_flag, ATOMIC_ORDER_RELEASE); + } + + ctx->per_worker_uint[worker_index] = counter; + + if (is_master_worker(worker_index)) { + test_atomic_flag_report(ctx); + } +} + +static const test_case_init test_cases_init[] = { + test_init_atomic_add, + test_init_atomic_flag +}; + +#define TEST_COUNT RTEMS_ARRAY_SIZE(test_cases_init) + +static const test_case test_cases[TEST_COUNT] = { + test_atomic_add, + test_atomic_flag +}; + +static void stop_worker_timer(rtems_id timer_id, void *arg) +{ + test_context *ctx = arg; + + _Atomic_Store_uint(&ctx->stop, 1, ATOMIC_ORDER_RELAXED); +} + +static void start_worker_stop_timer(test_context *ctx) +{ + rtems_status_code sc; + + _Atomic_Store_uint(&ctx->stop, 0, ATOMIC_ORDER_RELEASE); + + sc = rtems_timer_fire_after( + ctx->stop_worker_timer_id, + rtems_clock_get_ticks_per_second(), + stop_worker_timer, + ctx + ); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); +} + +static void run_tests(test_context *ctx, size_t worker_index) +{ + SMP_barrier_State bs = SMP_BARRIER_STATE_INITIALIZER; + size_t test; + + for (test = 0; test < TEST_COUNT; ++test) { + if (is_master_worker(worker_index)) { + start_worker_stop_timer(ctx); + (*test_cases_init[test])(ctx); + } + + _SMP_barrier_Wait(&ctx->barrier, &bs, ctx->worker_count); + + (*test_cases[test])(ctx, worker_index); + + _SMP_barrier_Wait(&ctx->barrier, &bs, ctx->worker_count); + } +} + +static void worker_task(size_t worker_index) +{ + test_context *ctx = &test_instance; + + run_tests(ctx, worker_index); + + (void) rtems_task_suspend(RTEMS_SELF); + rtems_test_assert(0); +} + +static void test(void) +{ + test_context *ctx = &test_instance; + rtems_status_code sc; + size_t worker_index; + + ctx->worker_count = rtems_smp_get_processor_count(); + + sc = rtems_timer_create( + rtems_build_name('S', 'T', 'O', 'P'), + &ctx->stop_worker_timer_id + ); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + for (worker_index = 1; worker_index < ctx->worker_count; ++worker_index) { + rtems_id worker_id; + + sc = rtems_task_create( + rtems_build_name('W', 'O', 'R', 'K'), + WORKER_PRIORITY, + RTEMS_MINIMUM_STACK_SIZE, + RTEMS_DEFAULT_MODES, + RTEMS_DEFAULT_ATTRIBUTES, + &worker_id + ); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_start(worker_id, worker_task, worker_index); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + } + + run_tests(ctx, 0); +} + +static void Init(rtems_task_argument arg) +{ + puts("\n\n*** TEST SMPATOMIC 8 ***"); + + test(); + + puts("*** END OF TEST SMPATOMIC 8 ***"); + + rtems_test_exit(0); +} + +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER + +#define CONFIGURE_SMP_APPLICATION + +#define CONFIGURE_SMP_MAXIMUM_PROCESSORS CPU_COUNT + +#define CONFIGURE_MAXIMUM_TASKS CPU_COUNT + +#define CONFIGURE_MAXIMUM_TIMERS 1 + +#define CONFIGURE_INIT_TASK_PRIORITY MASTER_PRIORITY +#define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES +#define CONFIGURE_INIT_TASK_ATTRIBUTES RTEMS_DEFAULT_ATTRIBUTES + +#define CONFIGURE_RTEMS_INIT_TASKS_TABLE + +#define CONFIGURE_INIT + +#include diff --git a/testsuites/smptests/smpatomic08/smpatomic08.doc b/testsuites/smptests/smpatomic08/smpatomic08.doc new file mode 100644 index 0000000000..629e43189f --- /dev/null +++ b/testsuites/smptests/smpatomic08/smpatomic08.doc @@ -0,0 +1,12 @@ +This file describes the directives and concepts tested by this test set. + +test set name: smpatomic08 + +directives: + + - ATOMIC_* + - _Atomic_* + +concepts: + + - Ensure that the atomic operations work. diff --git a/testsuites/smptests/smpatomic08/smpatomic08.scn b/testsuites/smptests/smpatomic08/smpatomic08.scn new file mode 100644 index 0000000000..5e283daa44 --- /dev/null +++ b/testsuites/smptests/smpatomic08/smpatomic08.scn @@ -0,0 +1,6 @@ +*** TEST SMPATOMIC 8 *** +=== atomic add test case == +atomic add worker 0 counter: 23435 +atomic add worker 1 counter: 374134 +global counter: expected = 397569, actual = 397569 +*** END OF TEST SMPATOMIC 8 *** -- cgit v1.2.3