summaryrefslogtreecommitdiffstats
path: root/testsuites/sptests
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2015-03-17 16:24:44 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2015-03-20 08:49:33 +0100
commit6a941e3a9986d3cfb3e4ed0139e983b0455cc73b (patch)
tree9ad4114b0eea22a82ddc51274a1b6e550ff3f4dd /testsuites/sptests
parentscore: Delete unused _Timestamp_Is_valid() (diff)
downloadrtems-6a941e3a9986d3cfb3e4ed0139e983b0455cc73b.tar.bz2
score: Fix _Thread_Change_priority()
Atomically update the current priority of a thread and the wait queue. Serialize the scheduler update in a separate critical section with a generation number. New test sptests/spintrcritical23. Close #2310.
Diffstat (limited to 'testsuites/sptests')
-rw-r--r--testsuites/sptests/Makefile.am1
-rw-r--r--testsuites/sptests/configure.ac1
-rw-r--r--testsuites/sptests/spintrcritical23/Makefile.am22
-rw-r--r--testsuites/sptests/spintrcritical23/init.c187
-rw-r--r--testsuites/sptests/spintrcritical23/spintrcritical23.doc12
-rw-r--r--testsuites/sptests/spintrcritical23/spintrcritical23.scn2
6 files changed, 225 insertions, 0 deletions
diff --git a/testsuites/sptests/Makefile.am b/testsuites/sptests/Makefile.am
index 0d1e687aaf..9025ff3535 100644
--- a/testsuites/sptests/Makefile.am
+++ b/testsuites/sptests/Makefile.am
@@ -37,6 +37,7 @@ if HAS_SMP
else
_SUBDIRS += sp29
endif
+_SUBDIRS += spintrcritical23
_SUBDIRS += spatomic01
_SUBDIRS += spintrcritical22
_SUBDIRS += spsem03
diff --git a/testsuites/sptests/configure.ac b/testsuites/sptests/configure.ac
index eef901b37b..ae3c763848 100644
--- a/testsuites/sptests/configure.ac
+++ b/testsuites/sptests/configure.ac
@@ -40,6 +40,7 @@ AM_CONDITIONAL(HAS_SMP,test "$rtems_cv_RTEMS_SMP" = "yes")
# Explicitly list all Makefiles here
AC_CONFIG_FILES([Makefile
+spintrcritical23/Makefile
spatomic01/Makefile
spglobalcon01/Makefile
spintrcritical22/Makefile
diff --git a/testsuites/sptests/spintrcritical23/Makefile.am b/testsuites/sptests/spintrcritical23/Makefile.am
new file mode 100644
index 0000000000..6baaf7b77e
--- /dev/null
+++ b/testsuites/sptests/spintrcritical23/Makefile.am
@@ -0,0 +1,22 @@
+rtems_tests_PROGRAMS = spintrcritical23
+spintrcritical23_SOURCES = init.c
+spintrcritical23_SOURCES += ../spintrcritical_support/intrcritical.h
+spintrcritical23_SOURCES += ../spintrcritical_support/intrcritical.c
+
+dist_rtems_tests_DATA = spintrcritical23.scn spintrcritical23.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
+AM_CPPFLAGS += -I$(top_srcdir)/spintrcritical_support
+
+LINK_OBJS = $(spintrcritical23_OBJECTS)
+LINK_LIBS = $(spintrcritical23_LDLIBS)
+
+spintrcritical23$(EXEEXT): $(spintrcritical23_OBJECTS) $(spintrcritical23_DEPENDENCIES)
+ @rm -f spintrcritical23$(EXEEXT)
+ $(make-exe)
+
+include $(top_srcdir)/../automake/local.am
diff --git a/testsuites/sptests/spintrcritical23/init.c b/testsuites/sptests/spintrcritical23/init.c
new file mode 100644
index 0000000000..aca1285c78
--- /dev/null
+++ b/testsuites/sptests/spintrcritical23/init.c
@@ -0,0 +1,187 @@
+/*
+ * 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.com/license/LICENSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include <tmacros.h>
+#include <intrcritical.h>
+
+#include <string.h>
+
+#include <rtems.h>
+#include <rtems/score/schedulerpriority.h>
+#include <rtems/score/threadimpl.h>
+
+const char rtems_test_name[] = "SPINTRCRITICAL 23";
+
+typedef struct {
+ RTEMS_INTERRUPT_LOCK_MEMBER(lock)
+ rtems_id task_id;
+ Thread_Control *tcb;
+ rtems_task_priority priority_task;
+ rtems_task_priority priority_interrupt;
+ uint32_t priority_generation;
+ Scheduler_priority_Node scheduler_node;
+ bool done;
+} test_context;
+
+static test_context ctx_instance;
+
+static Thread_Control *get_tcb(rtems_id id)
+{
+ Objects_Locations location;
+ Thread_Control *tcb;
+
+ tcb = _Thread_Get(id, &location);
+ _Objects_Put(&tcb->Object);
+
+ rtems_test_assert(tcb != NULL && location == OBJECTS_LOCAL);
+
+ return tcb;
+}
+
+static bool scheduler_node_unchanged(const test_context *ctx)
+{
+ return memcmp(
+ &ctx->scheduler_node,
+ ctx->tcb->Scheduler.node,
+ sizeof(ctx->scheduler_node)
+ ) == 0;
+}
+
+static void change_priority(rtems_id timer, void *arg)
+{
+ /* The arg is NULL */
+ test_context *ctx = &ctx_instance;
+ rtems_interrupt_lock_context lock_context;
+ rtems_task_priority priority_interrupt;
+ rtems_task_priority priority_task;
+
+ rtems_interrupt_lock_acquire(&ctx->lock, &lock_context);
+ if (
+ ctx->priority_generation != ctx->tcb->priority_generation
+ && scheduler_node_unchanged(ctx)
+ ) {
+ ctx->done = true;
+ priority_interrupt = ctx->priority_interrupt;
+ priority_task = ctx->priority_task;
+ }
+ rtems_interrupt_lock_release(&ctx->lock, &lock_context);
+
+ if (ctx->done) {
+ rtems_status_code sc;
+ rtems_task_priority previous;
+
+ sc = rtems_task_set_priority(
+ ctx->task_id,
+ priority_interrupt,
+ &previous
+ );
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+ rtems_test_assert(previous == priority_task);
+ }
+}
+
+static bool test_body(void *arg)
+{
+ test_context *ctx = arg;
+ rtems_status_code sc;
+ rtems_interrupt_lock_context lock_context;
+ rtems_task_priority priority_last;
+ rtems_task_priority priority_task;
+ rtems_task_priority priority_interrupt;
+ rtems_task_priority previous;
+
+ rtems_interrupt_lock_acquire(&ctx->lock, &lock_context);
+ priority_last = ctx->priority_task;
+ priority_task = 1 + (priority_last + 1) % 3;
+ priority_interrupt = 1 + (priority_task + 1) % 3;
+ ctx->priority_task = priority_task;
+ ctx->priority_interrupt = priority_interrupt;
+ ctx->priority_generation = ctx->tcb->priority_generation;
+ memcpy(
+ &ctx->scheduler_node,
+ ctx->tcb->Scheduler.node,
+ sizeof(ctx->scheduler_node)
+ );
+ rtems_interrupt_lock_release(&ctx->lock, &lock_context);
+
+ sc = rtems_task_set_priority(
+ ctx->task_id,
+ priority_task,
+ &previous
+ );
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+ rtems_test_assert(previous == priority_last);
+
+ if (ctx->done) {
+ sc = rtems_task_set_priority(
+ ctx->task_id,
+ RTEMS_CURRENT_PRIORITY,
+ &previous
+ );
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+ rtems_test_assert(previous == priority_interrupt);
+ }
+
+ return ctx->done;
+}
+
+static void Init(rtems_task_argument arg)
+{
+ test_context *ctx = &ctx_instance;
+ rtems_status_code sc;
+
+ TEST_BEGIN();
+
+ rtems_interrupt_lock_initialize(&ctx->lock, "Test");
+ ctx->priority_task = 1;
+
+ sc = rtems_task_create(
+ rtems_build_name('T', 'E', 'S', 'T'),
+ ctx->priority_task,
+ RTEMS_MINIMUM_STACK_SIZE,
+ RTEMS_DEFAULT_MODES,
+ RTEMS_DEFAULT_ATTRIBUTES,
+ &ctx->task_id
+ );
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ ctx->tcb = get_tcb(ctx->task_id);
+
+ interrupt_critical_section_test(test_body, ctx, change_priority);
+ rtems_test_assert(ctx->done);
+
+ TEST_END();
+ rtems_test_exit(0);
+}
+
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+
+#define CONFIGURE_MICROSECONDS_PER_TICK 1000
+
+#define CONFIGURE_MAXIMUM_TASKS 2
+#define CONFIGURE_MAXIMUM_TIMERS 1
+#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 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/sptests/spintrcritical23/spintrcritical23.doc b/testsuites/sptests/spintrcritical23/spintrcritical23.doc
new file mode 100644
index 0000000000..89e52815f9
--- /dev/null
+++ b/testsuites/sptests/spintrcritical23/spintrcritical23.doc
@@ -0,0 +1,12 @@
+This file describes the directives and concepts tested by this test set.
+
+test set name: spintrcritical23
+
+directives:
+
+ - _Thread_Change_priority()
+
+concepts:
+
+ - Ensure that priority updates work if carried out in interrupt context while
+ a priority change at task level is in progress.
diff --git a/testsuites/sptests/spintrcritical23/spintrcritical23.scn b/testsuites/sptests/spintrcritical23/spintrcritical23.scn
new file mode 100644
index 0000000000..cea3292ded
--- /dev/null
+++ b/testsuites/sptests/spintrcritical23/spintrcritical23.scn
@@ -0,0 +1,2 @@
+*** BEGIN OF TEST SPINTRCRITICAL 23 ***
+*** END OF TEST SPINTRCRITICAL 23 ***