From 6a941e3a9986d3cfb3e4ed0139e983b0455cc73b Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Tue, 17 Mar 2015 16:24:44 +0100 Subject: 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. --- testsuites/sptests/Makefile.am | 1 + testsuites/sptests/configure.ac | 1 + testsuites/sptests/spintrcritical23/Makefile.am | 22 +++ testsuites/sptests/spintrcritical23/init.c | 187 +++++++++++++++++++++ .../sptests/spintrcritical23/spintrcritical23.doc | 12 ++ .../sptests/spintrcritical23/spintrcritical23.scn | 2 + 6 files changed, 225 insertions(+) create mode 100644 testsuites/sptests/spintrcritical23/Makefile.am create mode 100644 testsuites/sptests/spintrcritical23/init.c create mode 100644 testsuites/sptests/spintrcritical23/spintrcritical23.doc create mode 100644 testsuites/sptests/spintrcritical23/spintrcritical23.scn (limited to 'testsuites/sptests') 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 + * + * + * 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 + +#include +#include +#include + +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 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 *** -- cgit v1.2.3