summaryrefslogtreecommitdiffstats
path: root/testsuites
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2013-08-28 14:52:43 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2013-08-28 14:58:51 +0200
commit79d03e30bfa8dd28eac90455725169ea7d052092 (patch)
tree74cb88f7f293cf68ab1620ea8995151e9ad34636 /testsuites
parentscore: Atomic flag changes (diff)
downloadrtems-79d03e30bfa8dd28eac90455725169ea7d052092.tar.bz2
smptests/smpatomic08: New test
Diffstat (limited to 'testsuites')
-rw-r--r--testsuites/smptests/Makefile.am1
-rw-r--r--testsuites/smptests/configure.ac1
-rw-r--r--testsuites/smptests/smpatomic08/Makefile.am19
-rw-r--r--testsuites/smptests/smpatomic08/init.c343
-rw-r--r--testsuites/smptests/smpatomic08/smpatomic08.doc12
-rw-r--r--testsuites/smptests/smpatomic08/smpatomic08.scn6
6 files changed, 382 insertions, 0 deletions
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
+ * <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/score/atomic.h>
+#include <rtems.h>
+
+#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 <rtems/confdefs.h>
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 ***