[rtems commit] score: Do not reset resource count during restart

Sebastian Huber sebh at rtems.org
Mon Mar 31 08:09:16 UTC 2014


Module:    rtems
Branch:    master
Commit:    f0b4fd9c2e680b7eaf4b4710f02d1d2127cab2e0
Changeset: http://git.rtems.org/rtems/commit/?id=f0b4fd9c2e680b7eaf4b4710f02d1d2127cab2e0

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Fri Mar 28 09:29:51 2014 +0100

score: Do not reset resource count during restart

This fixes an integer underflow problem in case resources are released
after a thread restart.

Add new test sptests/spthreadlife01.

---

 cpukit/score/src/threadrestart.c                   |    1 -
 testsuites/sptests/Makefile.am                     |    1 +
 testsuites/sptests/configure.ac                    |    1 +
 testsuites/sptests/spthreadlife01/Makefile.am      |   19 +
 testsuites/sptests/spthreadlife01/init.c           |  352 ++++++++++++++++++++
 .../sptests/spthreadlife01/spthreadlife01.doc      |   14 +
 .../sptests/spthreadlife01/spthreadlife01.scn      |    2 +
 7 files changed, 389 insertions(+), 1 deletions(-)

diff --git a/cpukit/score/src/threadrestart.c b/cpukit/score/src/threadrestart.c
index 985329f..4b83ede 100644
--- a/cpukit/score/src/threadrestart.c
+++ b/cpukit/score/src/threadrestart.c
@@ -212,7 +212,6 @@ static void _Thread_Start_life_change(
   Priority_Control  priority
 )
 {
-  the_thread->resource_count   = 0;
   the_thread->is_preemptible   = the_thread->Start.is_preemptible;
   the_thread->budget_algorithm = the_thread->Start.budget_algorithm;
   the_thread->budget_callout   = the_thread->Start.budget_callout;
diff --git a/testsuites/sptests/Makefile.am b/testsuites/sptests/Makefile.am
index 4722d42..d47f6f7 100644
--- a/testsuites/sptests/Makefile.am
+++ b/testsuites/sptests/Makefile.am
@@ -33,6 +33,7 @@ SUBDIRS = \
     spsignal_err01 spport_err01 spmsgq_err01 spmsgq_err02 spsem_err01 \
     spsem_err02 sptask_err01 spevent_err03 sptask_err03 sptask_err02 \
     sptask_err04 spclock_err01 
+SUBDIRS += spthreadlife01
 SUBDIRS += spprofiling01
 SUBDIRS += spcache01
 SUBDIRS += sptls03
diff --git a/testsuites/sptests/configure.ac b/testsuites/sptests/configure.ac
index 6a48dd9..4809bdc 100644
--- a/testsuites/sptests/configure.ac
+++ b/testsuites/sptests/configure.ac
@@ -36,6 +36,7 @@ AM_CONDITIONAL(HAS_CPUSET,test x"${ac_cv_header_sys_cpuset_h}" = x"yes")
 
 # Explicitly list all Makefiles here
 AC_CONFIG_FILES([Makefile
+spthreadlife01/Makefile
 spprofiling01/Makefile
 spcache01/Makefile
 sptls03/Makefile
diff --git a/testsuites/sptests/spthreadlife01/Makefile.am b/testsuites/sptests/spthreadlife01/Makefile.am
new file mode 100644
index 0000000..14f9a68
--- /dev/null
+++ b/testsuites/sptests/spthreadlife01/Makefile.am
@@ -0,0 +1,19 @@
+rtems_tests_PROGRAMS = spthreadlife01
+spthreadlife01_SOURCES = init.c
+
+dist_rtems_tests_DATA = spthreadlife01.scn spthreadlife01.doc
+
+include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP at .cfg
+include $(top_srcdir)/../automake/compile.am
+include $(top_srcdir)/../automake/leaf.am
+
+AM_CPPFLAGS += -I$(top_srcdir)/../support/include
+
+LINK_OBJS = $(spthreadlife01_OBJECTS)
+LINK_LIBS = $(spthreadlife01_LDLIBS)
+
+spthreadlife01$(EXEEXT): $(spthreadlife01_OBJECTS) $(spthreadlife01_DEPENDENCIES)
+	@rm -f spthreadlife01$(EXEEXT)
+	$(make-exe)
+
+include $(top_srcdir)/../automake/local.am
diff --git a/testsuites/sptests/spthreadlife01/init.c b/testsuites/sptests/spthreadlife01/init.c
new file mode 100644
index 0000000..b85b98c
--- /dev/null
+++ b/testsuites/sptests/spthreadlife01/init.c
@@ -0,0 +1,352 @@
+/*
+ * Copyright (c) 2014 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Dornierstr. 4
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at 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 <rtems.h>
+#include <rtems/libcsupport.h>
+
+#include "tmacros.h"
+
+#define PRIO_INIT 1
+#define PRIO_HIGH 2
+#define PRIO_MID 3
+#define PRIO_LOW 4
+
+const char rtems_test_name[] = "SPTHREADLIFE 1";
+
+typedef enum {
+  INIT,
+  SET_PRIO,
+  SET_PRIO_DONE,
+  DO_OBTAIN_0,
+  OBTAIN_DONE_0,
+  DO_RELEASE_0,
+  RELEASE_DONE_0,
+  DO_OBTAIN_1,
+  OBTAIN_DONE_1,
+  RESTART_0,
+  RESTART_1,
+  RESTART_2,
+  RESTART_3,
+  DO_RELEASE_1,
+  RELEASE_DONE_1,
+  DELETE_0,
+  DELETE_1,
+  DELETE_2,
+  DELETE_3,
+  INVALID
+} test_state;
+
+typedef struct {
+  rtems_id main_task_id;
+  rtems_id worker_task_id;
+  rtems_id sema_id;
+  test_state current;
+  test_state next;
+} test_context;
+
+static test_context test_instance;
+
+static void wake_up_main(const test_context *ctx)
+{
+  rtems_status_code sc;
+
+  sc = rtems_event_transient_send(ctx->main_task_id);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static void wait(void)
+{
+  rtems_status_code sc;
+
+  sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static void change_state(
+  test_context *ctx,
+  test_state expected,
+  test_state current,
+  test_state next
+)
+{
+  rtems_test_assert(ctx->current == expected);
+  ctx->current = current;
+  ctx->next = next;
+}
+
+static void change_state_and_wait(
+  test_context *ctx,
+  test_state expected,
+  test_state current,
+  test_state next
+)
+{
+  change_state(ctx, expected, current, next);
+  wait();
+}
+
+static void set_priority(rtems_task_priority prio)
+{
+  rtems_status_code sc;
+
+  sc = rtems_task_set_priority(RTEMS_SELF, prio, &prio);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static void assert_priority(rtems_task_priority expected)
+{
+  rtems_status_code sc;
+  rtems_task_priority prio;
+
+  sc = rtems_task_set_priority(RTEMS_SELF, RTEMS_CURRENT_PRIORITY, &prio);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  rtems_test_assert(prio == expected);
+}
+
+static void restart_extension(
+  Thread_Control *executing,
+  Thread_Control *restarted
+)
+{
+  test_context *ctx = &test_instance;
+  rtems_status_code sc;
+
+  rtems_test_assert(executing == restarted);
+  rtems_test_assert(ctx->worker_task_id == rtems_task_self());
+
+  switch (ctx->current) {
+    case RESTART_0:
+      ctx->current = RESTART_1;
+      sc = rtems_task_restart(RTEMS_SELF, 0);
+      rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+      break;
+    case RESTART_1:
+      ctx->current = RESTART_2;
+      break;
+    default:
+      rtems_test_assert(0);
+      break;
+  }
+}
+
+static void delete_extension(
+  Thread_Control *executing,
+  Thread_Control *deleted
+)
+{
+  test_context *ctx = &test_instance;
+
+  rtems_test_assert(executing != deleted);
+  rtems_test_assert(ctx->main_task_id == rtems_task_self());
+
+  assert_priority(PRIO_INIT);
+
+  rtems_test_assert(ctx->current == DELETE_2);
+  ctx->current = DELETE_3;
+}
+
+static void terminate_extension(Thread_Control *executing)
+{
+  test_context *ctx = &test_instance;
+  rtems_status_code sc;
+
+  rtems_test_assert(ctx->worker_task_id == rtems_task_self());
+
+  assert_priority(PRIO_INIT);
+
+  switch (ctx->current) {
+    case DELETE_0:
+      ctx->current = DELETE_1;
+      sc = rtems_task_delete(RTEMS_SELF);
+      rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+      break;
+    case DELETE_1:
+      ctx->current = DELETE_2;
+      break;
+    default:
+      rtems_test_assert(0);
+      break;
+  }
+}
+
+static void worker_task(rtems_task_argument arg)
+{
+  test_context *ctx = &test_instance;
+
+  while (true) {
+    test_state state = ctx->current;
+    rtems_status_code sc;
+
+    switch (state) {
+      case SET_PRIO:
+        assert_priority(PRIO_LOW);
+        set_priority(PRIO_MID);
+        break;
+      case DO_OBTAIN_0:
+      case DO_OBTAIN_1:
+        assert_priority(PRIO_MID);
+        sc = rtems_semaphore_obtain(
+          ctx->sema_id,
+          RTEMS_WAIT,
+          RTEMS_NO_TIMEOUT
+        );
+        rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+        assert_priority(PRIO_HIGH);
+        break;
+      case DO_RELEASE_0:
+      case DO_RELEASE_1:
+        assert_priority(PRIO_HIGH);
+        sc = rtems_semaphore_release(ctx->sema_id);
+        rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+        switch (state) {
+          case DO_RELEASE_0:
+            assert_priority(PRIO_MID);
+            break;
+          case DO_RELEASE_1:
+            assert_priority(PRIO_LOW);
+            break;
+          default:
+            rtems_test_assert(0);
+            break;
+        }
+
+        break;
+      case RESTART_2:
+        assert_priority(PRIO_HIGH);
+        break;
+      default:
+        rtems_test_assert(0);
+        break;
+    }
+
+    ctx->current = ctx->next;
+    wake_up_main(ctx);
+  }
+}
+
+static void create_sema(test_context *ctx)
+{
+  rtems_status_code sc;
+
+  sc = rtems_semaphore_create(
+    rtems_build_name('S', 'E', 'M', 'A'),
+    1,
+    RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_PRIORITY_CEILING,
+    PRIO_HIGH,
+    &ctx->sema_id
+  );
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static void test(void)
+{
+  test_context *ctx = &test_instance;
+  rtems_status_code sc;
+  rtems_resource_snapshot snapshot;
+
+  ctx->main_task_id = rtems_task_self();
+
+  rtems_resource_snapshot_take(&snapshot);
+
+  create_sema(ctx);
+
+  sc = rtems_task_create(
+    rtems_build_name('W', 'O', 'R', 'K'),
+    PRIO_LOW,
+    RTEMS_MINIMUM_STACK_SIZE,
+    RTEMS_DEFAULT_MODES,
+    RTEMS_DEFAULT_ATTRIBUTES,
+    &ctx->worker_task_id
+  );
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  sc = rtems_task_start(ctx->worker_task_id, worker_task, 0);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  change_state_and_wait(ctx, INIT, SET_PRIO, SET_PRIO_DONE);
+  change_state_and_wait(ctx, SET_PRIO_DONE, DO_OBTAIN_0, OBTAIN_DONE_0);
+
+  sc = rtems_semaphore_delete(ctx->sema_id);
+  rtems_test_assert(sc == RTEMS_RESOURCE_IN_USE);
+
+  change_state_and_wait(ctx, OBTAIN_DONE_0, DO_RELEASE_0, RELEASE_DONE_0);
+
+  sc = rtems_semaphore_delete(ctx->sema_id);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  create_sema(ctx);
+
+  change_state_and_wait(ctx, RELEASE_DONE_0, DO_OBTAIN_1, OBTAIN_DONE_1);
+
+  sc = rtems_semaphore_delete(ctx->sema_id);
+  rtems_test_assert(sc == RTEMS_RESOURCE_IN_USE);
+
+  sc = rtems_task_restart(ctx->worker_task_id, 0);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  change_state_and_wait(ctx, OBTAIN_DONE_1, RESTART_0, RESTART_3);
+  change_state_and_wait(ctx, RESTART_3, DO_RELEASE_1, RELEASE_DONE_1);
+
+  sc = rtems_semaphore_delete(ctx->sema_id);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  change_state(ctx, RELEASE_DONE_1, DELETE_0, INVALID);
+
+  sc = rtems_task_delete(ctx->worker_task_id);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  rtems_test_assert(ctx->current == DELETE_2);
+
+  rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
+
+  rtems_test_assert(ctx->current == DELETE_3);
+}
+
+static void Init(rtems_task_argument arg)
+{
+  TEST_BEGIN();
+
+  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_MAXIMUM_TASKS 2
+#define CONFIGURE_MAXIMUM_SEMAPHORES 1
+
+#define CONFIGURE_INITIAL_EXTENSIONS \
+  { \
+    .thread_restart = restart_extension, \
+    .thread_delete = delete_extension, \
+    .thread_terminate = terminate_extension \
+  }, \
+  RTEMS_TEST_INITIAL_EXTENSION
+
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+
+#define CONFIGURE_INIT
+
+#include <rtems/confdefs.h>
diff --git a/testsuites/sptests/spthreadlife01/spthreadlife01.doc b/testsuites/sptests/spthreadlife01/spthreadlife01.doc
new file mode 100644
index 0000000..91c8167
--- /dev/null
+++ b/testsuites/sptests/spthreadlife01/spthreadlife01.doc
@@ -0,0 +1,14 @@
+This file describes the directives and concepts tested by this test set.
+
+test set name: spthreadlife01
+
+directives:
+
+  - rtems_task_restart()
+  - rtems_task_delete()
+
+concepts:
+
+  - Ensure that semaphores owned by a restarted thread can be deleted.
+  - Ensure that the task priority is adjusted properly across task restarts.
+  - Ensure that the task priority is adjusted properly across task deletes.
diff --git a/testsuites/sptests/spthreadlife01/spthreadlife01.scn b/testsuites/sptests/spthreadlife01/spthreadlife01.scn
new file mode 100644
index 0000000..12ed3c3
--- /dev/null
+++ b/testsuites/sptests/spthreadlife01/spthreadlife01.scn
@@ -0,0 +1,2 @@
+*** BEGIN OF TEST SPTHREADLIFE 1 ***
+*** END OF TEST SPTHREADLIFE 1 ***




More information about the vc mailing list