summaryrefslogtreecommitdiffstats
path: root/testsuites
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2015-09-02 11:58:54 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2015-09-04 13:25:03 +0200
commit3995e6d9c213515f0d636dc2f211bf3c0d997631 (patch)
tree7299f4b9c16d4d7987b6f9a0137778bdd93884b5 /testsuites
parentscore: Documentation (diff)
downloadrtems-3995e6d9c213515f0d636dc2f211bf3c0d997631.tar.bz2
score: Implement SMP-specific priority queue
Diffstat (limited to 'testsuites')
-rw-r--r--testsuites/smptests/Makefile.am1
-rw-r--r--testsuites/smptests/configure.ac1
-rw-r--r--testsuites/smptests/smpmutex01/Makefile.am19
-rw-r--r--testsuites/smptests/smpmutex01/init.c326
-rw-r--r--testsuites/smptests/smpmutex01/smpmutex01.doc14
-rw-r--r--testsuites/smptests/smpmutex01/smpmutex01.scn2
6 files changed, 363 insertions, 0 deletions
diff --git a/testsuites/smptests/Makefile.am b/testsuites/smptests/Makefile.am
index 4b81a20b85..92f45286e5 100644
--- a/testsuites/smptests/Makefile.am
+++ b/testsuites/smptests/Makefile.am
@@ -26,6 +26,7 @@ SUBDIRS += smplock01
SUBDIRS += smpmigration01
SUBDIRS += smpmigration02
SUBDIRS += smpmrsp01
+SUBDIRS += smpmutex01
SUBDIRS += smpschedaffinity01
SUBDIRS += smpschedaffinity02
SUBDIRS += smpschedaffinity03
diff --git a/testsuites/smptests/configure.ac b/testsuites/smptests/configure.ac
index 5aee6ec34b..27e8f9c95a 100644
--- a/testsuites/smptests/configure.ac
+++ b/testsuites/smptests/configure.ac
@@ -81,6 +81,7 @@ smplock01/Makefile
smpmigration01/Makefile
smpmigration02/Makefile
smpmrsp01/Makefile
+smpmutex01/Makefile
smppsxaffinity01/Makefile
smppsxaffinity02/Makefile
smppsxsignal01/Makefile
diff --git a/testsuites/smptests/smpmutex01/Makefile.am b/testsuites/smptests/smpmutex01/Makefile.am
new file mode 100644
index 0000000000..1b9e01c447
--- /dev/null
+++ b/testsuites/smptests/smpmutex01/Makefile.am
@@ -0,0 +1,19 @@
+rtems_tests_PROGRAMS = smpmutex01
+smpmutex01_SOURCES = init.c
+
+dist_rtems_tests_DATA = smpmutex01.scn smpmutex01.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 = $(smpmutex01_OBJECTS)
+LINK_LIBS = $(smpmutex01_LDLIBS)
+
+smpmutex01$(EXEEXT): $(smpmutex01_OBJECTS) $(smpmutex01_DEPENDENCIES)
+ @rm -f smpmutex01$(EXEEXT)
+ $(make-exe)
+
+include $(top_srcdir)/../automake/local.am
diff --git a/testsuites/smptests/smpmutex01/init.c b/testsuites/smptests/smpmutex01/init.c
new file mode 100644
index 0000000000..1b2a1895ef
--- /dev/null
+++ b/testsuites/smptests/smpmutex01/init.c
@@ -0,0 +1,326 @@
+/*
+ * Copyright (c) 2015 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 "tmacros.h"
+
+const char rtems_test_name[] = "SMPMUTEX 1";
+
+#define SCHED_A rtems_build_name(' ', ' ', ' ', 'A')
+
+#define SCHED_B rtems_build_name(' ', ' ', ' ', 'B')
+
+#define PART_COUNT 2
+
+#define TASK_COUNT 8
+
+typedef enum {
+ REQ_WAKE_UP_MASTER = RTEMS_EVENT_0,
+ REQ_WAKE_UP_HELPER = RTEMS_EVENT_1,
+ REQ_MTX_OBTAIN = RTEMS_EVENT_2,
+ REQ_MTX_RELEASE = RTEMS_EVENT_3
+} request_id;
+
+typedef enum {
+ A_1,
+ A_2_0,
+ A_2_1,
+ M,
+ B_4,
+ B_5_0,
+ B_5_1,
+ H,
+ NONE
+} task_id;
+
+typedef struct {
+ rtems_id mtx;
+ rtems_id tasks[TASK_COUNT];
+ int generation[TASK_COUNT];
+ int expected_generation[TASK_COUNT];
+} test_context;
+
+static test_context test_instance;
+
+static void start_task(
+ test_context *ctx,
+ task_id id,
+ rtems_task_entry entry,
+ rtems_task_priority prio,
+ rtems_name scheduler
+)
+{
+ rtems_status_code sc;
+ rtems_id scheduler_id;
+
+ sc = rtems_task_create(
+ rtems_build_name('T', 'A', 'S', 'K'),
+ prio,
+ RTEMS_MINIMUM_STACK_SIZE,
+ RTEMS_DEFAULT_MODES,
+ RTEMS_DEFAULT_ATTRIBUTES,
+ &ctx->tasks[id]
+ );
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ sc = rtems_scheduler_ident(scheduler, &scheduler_id);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ sc = rtems_task_set_scheduler(ctx->tasks[id], scheduler_id);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ sc = rtems_task_start(ctx->tasks[id], entry, id);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static void send_event(test_context *ctx, task_id id, rtems_event_set events)
+{
+ rtems_status_code sc;
+
+ sc = rtems_event_send(ctx->tasks[id], events);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static rtems_event_set wait_for_events(void)
+{
+ rtems_event_set events;
+ rtems_status_code sc;
+
+ sc = rtems_event_receive(
+ RTEMS_ALL_EVENTS,
+ RTEMS_EVENT_ANY | RTEMS_WAIT,
+ RTEMS_NO_TIMEOUT,
+ &events
+ );
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ return events;
+}
+
+static void sync_with_helper(test_context *ctx)
+{
+ rtems_event_set events;
+
+ send_event(ctx, H, REQ_WAKE_UP_HELPER);
+ events = wait_for_events();
+ rtems_test_assert(events == REQ_WAKE_UP_MASTER);
+}
+
+static void request(test_context *ctx, task_id id, request_id req)
+{
+ send_event(ctx, id, req);
+ sync_with_helper(ctx);
+}
+
+static void obtain(test_context *ctx)
+{
+ rtems_status_code sc;
+
+ sc = rtems_semaphore_obtain(ctx->mtx, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static void release(test_context *ctx)
+{
+ rtems_status_code sc;
+
+ sc = rtems_semaphore_release(ctx->mtx);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static void check_generations(test_context *ctx, task_id a, task_id b)
+{
+ size_t i;
+
+ if (a != NONE) {
+ ++ctx->expected_generation[a];
+ }
+
+ if (b != NONE) {
+ ++ctx->expected_generation[b];
+ }
+
+ for (i = 0; i < TASK_COUNT; ++i) {
+ rtems_test_assert(ctx->generation[i] == ctx->expected_generation[i]);
+ }
+}
+
+static void helper(rtems_task_argument arg)
+{
+ test_context *ctx = &test_instance;
+
+ while (true) {
+ rtems_event_set events = wait_for_events();
+ rtems_test_assert(events == REQ_WAKE_UP_HELPER);
+ send_event(ctx, M, REQ_WAKE_UP_MASTER);
+ }
+}
+
+static void worker(rtems_task_argument arg)
+{
+ test_context *ctx = &test_instance;
+ task_id id = arg;
+
+ while (true) {
+ rtems_event_set events = wait_for_events();
+
+ if ((events & REQ_MTX_OBTAIN) != 0) {
+ obtain(ctx);
+ ++ctx->generation[id];
+ }
+
+ if ((events & REQ_MTX_RELEASE) != 0) {
+ release(ctx);
+ ++ctx->generation[id];
+ }
+ }
+}
+
+static void test(void)
+{
+ test_context *ctx = &test_instance;
+ rtems_status_code sc;
+
+ ctx->tasks[M] = rtems_task_self();
+ start_task(ctx, A_1, worker, 1, SCHED_A);
+ start_task(ctx, A_2_0, worker, 2, SCHED_A);
+ start_task(ctx, A_2_1, worker, 2, SCHED_A);
+ start_task(ctx, B_4, worker, 4, SCHED_B);
+ start_task(ctx, B_5_0, worker, 5, SCHED_B);
+ start_task(ctx, B_5_1, worker, 5, SCHED_B);
+ start_task(ctx, H, helper, 6, SCHED_B);
+
+ sc = rtems_semaphore_create(
+ rtems_build_name(' ', 'M', 'T', 'X'),
+ 1,
+ RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY,
+ 0,
+ &ctx->mtx
+ );
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ obtain(ctx);
+ request(ctx, A_1, REQ_MTX_OBTAIN);
+ check_generations(ctx, NONE, NONE);
+ release(ctx);
+ check_generations(ctx, A_1, NONE);
+ request(ctx, A_1, REQ_MTX_RELEASE);
+ check_generations(ctx, A_1, NONE);
+
+ obtain(ctx);
+ request(ctx, A_2_0, REQ_MTX_OBTAIN);
+ request(ctx, A_1, REQ_MTX_OBTAIN);
+ request(ctx, A_2_1, REQ_MTX_OBTAIN);
+ check_generations(ctx, NONE, NONE);
+ release(ctx);
+ check_generations(ctx, A_1, NONE);
+ request(ctx, A_1, REQ_MTX_RELEASE);
+ check_generations(ctx, A_1, A_2_0);
+ request(ctx, A_2_0, REQ_MTX_RELEASE);
+ check_generations(ctx, A_2_0, A_2_1);
+ request(ctx, A_2_1, REQ_MTX_RELEASE);
+ check_generations(ctx, A_2_1, NONE);
+
+ obtain(ctx);
+ request(ctx, B_5_0, REQ_MTX_OBTAIN);
+ request(ctx, B_4, REQ_MTX_OBTAIN);
+ request(ctx, B_5_1, REQ_MTX_OBTAIN);
+ check_generations(ctx, NONE, NONE);
+ release(ctx);
+ sync_with_helper(ctx);
+ check_generations(ctx, B_4, NONE);
+ request(ctx, B_4, REQ_MTX_RELEASE);
+ check_generations(ctx, B_4, B_5_0);
+ request(ctx, B_5_0, REQ_MTX_RELEASE);
+ check_generations(ctx, B_5_0, B_5_1);
+ request(ctx, B_5_1, REQ_MTX_RELEASE);
+ check_generations(ctx, B_5_1, NONE);
+
+ obtain(ctx);
+ request(ctx, A_2_0, REQ_MTX_OBTAIN);
+ request(ctx, B_5_0, REQ_MTX_OBTAIN);
+ request(ctx, B_5_1, REQ_MTX_OBTAIN);
+ request(ctx, B_4, REQ_MTX_OBTAIN);
+ request(ctx, A_2_1, REQ_MTX_OBTAIN);
+ request(ctx, A_1, REQ_MTX_OBTAIN);
+ check_generations(ctx, NONE, NONE);
+ release(ctx);
+ check_generations(ctx, A_1, NONE);
+ request(ctx, A_1, REQ_MTX_RELEASE);
+ check_generations(ctx, A_1, B_4);
+ request(ctx, B_4, REQ_MTX_RELEASE);
+ check_generations(ctx, B_4, A_2_0);
+ request(ctx, A_2_0, REQ_MTX_RELEASE);
+ check_generations(ctx, A_2_0, B_5_0);
+ request(ctx, B_5_0, REQ_MTX_RELEASE);
+ check_generations(ctx, B_5_0, A_2_1);
+ request(ctx, A_2_1, REQ_MTX_RELEASE);
+ check_generations(ctx, A_2_1, B_5_1);
+ request(ctx, B_5_1, REQ_MTX_RELEASE);
+ check_generations(ctx, B_5_1, NONE);
+}
+
+static void Init(rtems_task_argument arg)
+{
+ TEST_BEGIN();
+
+ if (rtems_get_processor_count() >= PART_COUNT) {
+ test();
+ }
+
+ TEST_END();
+ rtems_test_exit(0);
+}
+
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+
+#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM
+
+#define CONFIGURE_SMP_APPLICATION
+
+#define CONFIGURE_SMP_MAXIMUM_PROCESSORS PART_COUNT
+
+#define CONFIGURE_SCHEDULER_SIMPLE_SMP
+
+#include <rtems/scheduler.h>
+
+RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(a);
+
+RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(b);
+
+#define CONFIGURE_SCHEDULER_CONTROLS \
+ RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(a, SCHED_A), \
+ RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(b, SCHED_B)
+
+#define CONFIGURE_SMP_SCHEDULER_ASSIGNMENTS \
+ RTEMS_SCHEDULER_ASSIGN(0, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_MANDATORY), \
+ RTEMS_SCHEDULER_ASSIGN(1, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL)
+
+#define CONFIGURE_MAXIMUM_TASKS TASK_COUNT
+
+#define CONFIGURE_MAXIMUM_SEMAPHORES 1
+
+#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
+
+#define CONFIGURE_INIT_TASK_PRIORITY 3
+
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+
+#define CONFIGURE_INIT
+
+#include <rtems/confdefs.h>
diff --git a/testsuites/smptests/smpmutex01/smpmutex01.doc b/testsuites/smptests/smpmutex01/smpmutex01.doc
new file mode 100644
index 0000000000..117d952e57
--- /dev/null
+++ b/testsuites/smptests/smpmutex01/smpmutex01.doc
@@ -0,0 +1,14 @@
+This file describes the directives and concepts tested by this test set.
+
+test set name: smpmutex01
+
+directives:
+
+ - _Thread_queue_Priority_do_enqueue()
+ - _Thread_queue_Priority_do_extract()
+ - _Thread_queue_Priority_first()
+
+concepts:
+
+ - Ensure that the thread queue priority discipline enforces FIFO fairness
+ among the highest priority thread of each scheduler instance.
diff --git a/testsuites/smptests/smpmutex01/smpmutex01.scn b/testsuites/smptests/smpmutex01/smpmutex01.scn
new file mode 100644
index 0000000000..aad67a75c3
--- /dev/null
+++ b/testsuites/smptests/smpmutex01/smpmutex01.scn
@@ -0,0 +1,2 @@
+*** BEGIN OF TEST SMPMUTEX 1 ***
+*** END OF TEST SMPMUTEX 1 ***