[rtems commit] score: Use thread action for thread restart

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


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

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Mon Mar 17 10:12:14 2014 +0100

score: Use thread action for thread restart

The thread restart is now supported on SMP.  New test
smptests/smpthreadlife01.

---

 cpukit/rtems/src/taskrestart.c                     |   10 +--
 cpukit/score/include/rtems/score/objectimpl.h      |   17 ---
 cpukit/score/include/rtems/score/thread.h          |    5 +
 cpukit/score/include/rtems/score/threadimpl.h      |   37 ++++++-
 cpukit/score/src/threadinitialize.c                |    5 +
 cpukit/score/src/threadrestart.c                   |   50 ++++++---
 testsuites/smptests/Makefile.am                    |    1 +
 testsuites/smptests/configure.ac                   |    1 +
 testsuites/smptests/smpthreadlife01/Makefile.am    |   19 +++
 testsuites/smptests/smpthreadlife01/init.c         |  122 ++++++++++++++++++++
 .../smptests/smpthreadlife01/smpthreadlife01.doc   |   11 ++
 .../smptests/smpthreadlife01/smpthreadlife01.scn   |    2 +
 testsuites/smptests/smpunsupported01/init.c        |   25 +----
 13 files changed, 236 insertions(+), 69 deletions(-)

diff --git a/cpukit/rtems/src/taskrestart.c b/cpukit/rtems/src/taskrestart.c
index daac0da..ad44642 100644
--- a/cpukit/rtems/src/taskrestart.c
+++ b/cpukit/rtems/src/taskrestart.c
@@ -34,15 +34,7 @@ rtems_status_code rtems_task_restart(
 
     case OBJECTS_LOCAL:
       if ( _Thread_Restart( the_thread, NULL, argument ) ) {
-        if ( _Thread_Is_executing( the_thread ) ) {
-          _Objects_Put_and_keep_thread_dispatch_disabled(
-            &the_thread->Object
-          );
-          _Thread_Restart_self();
-        } else {
-          _Objects_Put( &the_thread->Object );
-        }
-
+        _Objects_Put( &the_thread->Object );
         return RTEMS_SUCCESSFUL;
       }
       _Objects_Put( &the_thread->Object );
diff --git a/cpukit/score/include/rtems/score/objectimpl.h b/cpukit/score/include/rtems/score/objectimpl.h
index 3764c66..119f11d 100644
--- a/cpukit/score/include/rtems/score/objectimpl.h
+++ b/cpukit/score/include/rtems/score/objectimpl.h
@@ -880,23 +880,6 @@ RTEMS_INLINE_ROUTINE void _Objects_Put_without_thread_dispatch(
 }
 
 /**
- * @brief Puts back an object obtained with _Objects_Get().
- *
- * The thread dispatch disable level will remain unchanged.
- *
- * On SMP configurations the Giant lock will be released.
- */
-RTEMS_INLINE_ROUTINE void _Objects_Put_and_keep_thread_dispatch_disabled(
-  Objects_Control *the_object
-)
-{
-  (void) the_object;
-#if defined(RTEMS_SMP)
-  _Giant_Release();
-#endif
-}
-
-/**
  * @brief Puts back an object obtained with _Objects_Get_isr_disable().
  */
 RTEMS_INLINE_ROUTINE void _Objects_Put_for_get_isr_disable(
diff --git a/cpukit/score/include/rtems/score/thread.h b/cpukit/score/include/rtems/score/thread.h
index e5a1a55..d853aa0 100644
--- a/cpukit/score/include/rtems/score/thread.h
+++ b/cpukit/score/include/rtems/score/thread.h
@@ -396,6 +396,10 @@ typedef struct {
   Chain_Control Chain;
 } Thread_Action_control;
 
+typedef struct {
+  Thread_Action      Action;
+} Thread_Life_control;
+
 /**
  *  This structure defines the Thread Control Block (TCB).
  */
@@ -543,6 +547,7 @@ struct Thread_Control_struct {
    */
   Chain_Control           Key_Chain;
 
+  Thread_Life_control                   Life;
 };
 
 #if (CPU_PROVIDES_IDLE_THREAD_BODY == FALSE)
diff --git a/cpukit/score/include/rtems/score/threadimpl.h b/cpukit/score/include/rtems/score/threadimpl.h
index bbaa10a..b864727 100644
--- a/cpukit/score/include/rtems/score/threadimpl.h
+++ b/cpukit/score/include/rtems/score/threadimpl.h
@@ -219,6 +219,13 @@ void _Thread_Reset(
   Thread_Entry_numeric_type  numeric_argument
 );
 
+void _Thread_Life_action_handler(
+  Thread_Control  *executing,
+  Thread_Action   *action,
+  Per_CPU_Control *cpu,
+  ISR_Level        level
+);
+
 /**
  *  @brief Frees all memory associated with the specified thread.
  *
@@ -501,21 +508,23 @@ RTEMS_INLINE_ROUTINE void _Thread_Unblock (
  * to that of its initial state.
  */
 
-RTEMS_INLINE_ROUTINE void _Thread_Restart_self( void )
+RTEMS_INLINE_ROUTINE void _Thread_Restart_self( Thread_Control *executing )
 {
 #if defined(RTEMS_SMP)
   ISR_Level level;
 
+  _Giant_Release();
+
   _Per_CPU_ISR_disable_and_acquire( _Per_CPU_Get(), level );
   ( void ) level;
 #endif
 
 #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
-  if ( _Thread_Executing->fp_context != NULL )
-    _Context_Restore_fp( &_Thread_Executing->fp_context );
+  if ( executing->fp_context != NULL )
+    _Context_Restore_fp( &executing->fp_context );
 #endif
 
-  _CPU_Context_Restart_self( &_Thread_Executing->Registers );
+  _CPU_Context_Restart_self( &executing->Registers );
 }
 
 /**
@@ -603,6 +612,26 @@ RTEMS_INLINE_ROUTINE Thread_Control *_Thread_Internal_allocate( void )
   return (Thread_Control *) _Objects_Allocate( &_Thread_Internal_information );
 }
 
+RTEMS_INLINE_ROUTINE void _Thread_Request_dispatch_if_executing(
+  Thread_Control *thread
+)
+{
+#if defined(RTEMS_SMP)
+  if ( thread->is_executing ) {
+    const Per_CPU_Control *cpu_of_executing = _Per_CPU_Get();
+    Per_CPU_Control *cpu_of_thread = _Thread_Get_CPU( thread );
+
+    cpu_of_thread->dispatch_necessary = true;
+
+    if ( cpu_of_executing != cpu_of_thread ) {
+      _Per_CPU_Send_interrupt( cpu_of_thread );
+    }
+  }
+#else
+  (void) thread;
+#endif
+}
+
 RTEMS_INLINE_ROUTINE void _Thread_Signal_notification( Thread_Control *thread )
 {
   if ( _ISR_Is_in_progress() && _Thread_Is_executing( thread ) ) {
diff --git a/cpukit/score/src/threadinitialize.c b/cpukit/score/src/threadinitialize.c
index 315156e..c851320 100644
--- a/cpukit/score/src/threadinitialize.c
+++ b/cpukit/score/src/threadinitialize.c
@@ -240,6 +240,11 @@ bool _Thread_Initialize(
 
   _Thread_Action_control_initialize( &the_thread->Post_switch_actions );
 
+  _Thread_Action_initialize(
+    &the_thread->Life.Action,
+    _Thread_Life_action_handler
+  );
+
   /*
    *  Open the object
    */
diff --git a/cpukit/score/src/threadrestart.c b/cpukit/score/src/threadrestart.c
index b9a7dd5..d982f72 100644
--- a/cpukit/score/src/threadrestart.c
+++ b/cpukit/score/src/threadrestart.c
@@ -20,32 +20,52 @@
 
 #include <rtems/score/threadimpl.h>
 #include <rtems/score/userextimpl.h>
-#include <rtems/config.h>
 
-bool _Thread_Restart(
+void _Thread_Life_action_handler(
+  Thread_Control  *executing,
+  Thread_Action   *action,
+  Per_CPU_Control *cpu,
+  ISR_Level        level
+)
+{
+  (void) action;
+  _Thread_Action_release_and_ISR_enable( cpu, level );
+
+  _Thread_Disable_dispatch();
+
+  _Thread_Load_environment( executing );
+  _Thread_Restart_self( executing );
+}
+
+static void _Thread_Request_life_change(
   Thread_Control            *the_thread,
   void                      *pointer_argument,
   Thread_Entry_numeric_type  numeric_argument
 )
 {
-#if defined( RTEMS_SMP )
-  if (
-    rtems_configuration_is_smp_enabled()
-      && !_Thread_Is_executing( the_thread )
-  ) {
-    return false;
-  }
-#endif
+  _Thread_Set_transient( the_thread );
 
-  if ( !_States_Is_dormant( the_thread->current_state ) ) {
+  _Thread_Reset( the_thread, pointer_argument, numeric_argument );
 
-    _Thread_Set_transient( the_thread );
+  _Thread_Add_post_switch_action( the_thread, &the_thread->Life.Action );
 
-    _Thread_Reset( the_thread, pointer_argument, numeric_argument );
+  _Thread_Ready( the_thread );
 
-    _Thread_Load_environment( the_thread );
+  _Thread_Request_dispatch_if_executing( the_thread );
+}
 
-    _Thread_Ready( the_thread );
+bool _Thread_Restart(
+  Thread_Control            *the_thread,
+  void                      *pointer_argument,
+  Thread_Entry_numeric_type  numeric_argument
+)
+{
+  if ( !_States_Is_dormant( the_thread->current_state ) ) {
+    _Thread_Request_life_change(
+      the_thread,
+      pointer_argument,
+      numeric_argument
+    );
 
     _User_extensions_Thread_restart( the_thread );
 
diff --git a/testsuites/smptests/Makefile.am b/testsuites/smptests/Makefile.am
index c7fa028..dddd7ab 100644
--- a/testsuites/smptests/Makefile.am
+++ b/testsuites/smptests/Makefile.am
@@ -21,6 +21,7 @@ SUBDIRS += smpmigration01
 SUBDIRS += smpschedule01
 SUBDIRS += smpsignal01
 SUBDIRS += smpswitchextension01
+SUBDIRS += smpthreadlife01
 SUBDIRS += smpunsupported01
 if HAS_POSIX
 SUBDIRS += smppsxaffinity01
diff --git a/testsuites/smptests/configure.ac b/testsuites/smptests/configure.ac
index 0d08f0d..b7bd8d2 100644
--- a/testsuites/smptests/configure.ac
+++ b/testsuites/smptests/configure.ac
@@ -78,6 +78,7 @@ smppsxsignal01/Makefile
 smpschedule01/Makefile
 smpsignal01/Makefile
 smpswitchextension01/Makefile
+smpthreadlife01/Makefile
 smpunsupported01/Makefile
 ])
 AC_OUTPUT
diff --git a/testsuites/smptests/smpthreadlife01/Makefile.am b/testsuites/smptests/smpthreadlife01/Makefile.am
new file mode 100644
index 0000000..02b5bd5
--- /dev/null
+++ b/testsuites/smptests/smpthreadlife01/Makefile.am
@@ -0,0 +1,19 @@
+rtems_tests_PROGRAMS = smpthreadlife01
+smpthreadlife01_SOURCES = init.c
+
+dist_rtems_tests_DATA = smpthreadlife01.scn smpthreadlife01.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 = $(smpthreadlife01_OBJECTS)
+LINK_LIBS = $(smpthreadlife01_LDLIBS)
+
+smpthreadlife01$(EXEEXT): $(smpthreadlife01_OBJECTS) $(smpthreadlife01_DEPENDENCIES)
+	@rm -f smpthreadlife01$(EXEEXT)
+	$(make-exe)
+
+include $(top_srcdir)/../automake/local.am
diff --git a/testsuites/smptests/smpthreadlife01/init.c b/testsuites/smptests/smpthreadlife01/init.c
new file mode 100644
index 0000000..ee36068
--- /dev/null
+++ b/testsuites/smptests/smpthreadlife01/init.c
@@ -0,0 +1,122 @@
+/*
+ * 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 "tmacros.h"
+
+#include <rtems.h>
+#include <rtems/score/smpbarrier.h>
+
+const char rtems_test_name[] = "SMPTHREADLIFE 1";
+
+#define CPU_COUNT 2
+
+typedef struct {
+  volatile rtems_task_argument main_arg;
+  volatile rtems_task_argument worker_arg;
+  SMP_barrier_Control barrier;
+  SMP_barrier_State worker_barrier_state;
+} test_context;
+
+static test_context test_instance = {
+  .barrier = SMP_BARRIER_CONTROL_INITIALIZER,
+  .worker_barrier_state = SMP_BARRIER_STATE_INITIALIZER
+};
+
+static void worker_task(rtems_task_argument arg)
+{
+  test_context *ctx = &test_instance;
+
+  rtems_test_assert(arg == ctx->main_arg);
+
+  ctx->worker_arg = arg;
+
+  _SMP_barrier_Wait(&ctx->barrier, &ctx->worker_barrier_state, CPU_COUNT);
+
+  while (true) {
+    /* Do nothing */
+  }
+}
+
+static void test(void)
+{
+  test_context *ctx = &test_instance;
+  SMP_barrier_State barrier_state = SMP_BARRIER_STATE_INITIALIZER;
+  rtems_status_code sc;
+  rtems_id id;
+  rtems_task_argument arg;
+
+  sc = rtems_task_create(
+    rtems_build_name('W', 'O', 'R', 'K'),
+    1,
+    RTEMS_MINIMUM_STACK_SIZE,
+    RTEMS_DEFAULT_MODES,
+    RTEMS_DEFAULT_ATTRIBUTES,
+    &id
+  );
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  sc = rtems_task_start(id, worker_task, 0);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  _SMP_barrier_Wait(
+    &ctx->barrier,
+    &barrier_state,
+    CPU_COUNT
+  );
+
+  for (arg = 1; arg < 23; ++arg) {
+    ctx->main_arg = arg;
+    ctx->worker_arg = 0;
+
+    sc = rtems_task_restart(id, arg);
+    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+    _SMP_barrier_Wait(&ctx->barrier, &barrier_state, CPU_COUNT);
+
+    rtems_test_assert(ctx->worker_arg == arg);
+  }
+}
+
+static void Init(rtems_task_argument arg)
+{
+  TEST_BEGIN();
+
+  if (rtems_smp_get_processor_count() >= CPU_COUNT) {
+    test();
+  }
+
+  TEST_END();
+  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_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
+
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+
+#define CONFIGURE_INIT
+
+#include <rtems/confdefs.h>
diff --git a/testsuites/smptests/smpthreadlife01/smpthreadlife01.doc b/testsuites/smptests/smpthreadlife01/smpthreadlife01.doc
new file mode 100644
index 0000000..f620567
--- /dev/null
+++ b/testsuites/smptests/smpthreadlife01/smpthreadlife01.doc
@@ -0,0 +1,11 @@
+This file describes the directives and concepts tested by this test set.
+
+test set name: smprestart01
+
+directives:
+
+  - rtems_task_restart()
+
+concepts:
+
+  - Ensure that a restart of a task executing on another processor works.
diff --git a/testsuites/smptests/smpthreadlife01/smpthreadlife01.scn b/testsuites/smptests/smpthreadlife01/smpthreadlife01.scn
new file mode 100644
index 0000000..7b4de1b
--- /dev/null
+++ b/testsuites/smptests/smpthreadlife01/smpthreadlife01.scn
@@ -0,0 +1,2 @@
+*** BEGIN OF TEST SMPTHREADLIFE 1 ***
+*** END OF TEST SMPTHREADLIFE 1 ***
diff --git a/testsuites/smptests/smpunsupported01/init.c b/testsuites/smptests/smpunsupported01/init.c
index a2ffbed..ffa4013 100644
--- a/testsuites/smptests/smpunsupported01/init.c
+++ b/testsuites/smptests/smpunsupported01/init.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013 embedded brains GmbH.  All rights reserved.
+ * Copyright (c) 2013-2014 embedded brains GmbH.  All rights reserved.
  *
  *  embedded brains GmbH
  *  Dornierstr. 4
@@ -20,13 +20,6 @@
 
 const char rtems_test_name[] = "SMPUNSUPPORTED 1";
 
-static void some_task(rtems_task_argument arg)
-{
-  (void) arg;
-
-  while (1);
-}
-
 static void test(void)
 {
   rtems_status_code sc;
@@ -59,22 +52,6 @@ static void test(void)
     &id
   );
   rtems_test_assert(sc == RTEMS_UNSATISFIED);
-
-  sc = rtems_task_create(
-    rtems_build_name('T', 'A', 'S', 'K'),
-    RTEMS_MAXIMUM_PRIORITY,
-    RTEMS_MINIMUM_STACK_SIZE,
-    RTEMS_DEFAULT_MODES,
-    RTEMS_DEFAULT_ATTRIBUTES,
-    &id
-  );
-  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
-
-  sc = rtems_task_start(id, some_task, 0);
-  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
-
-  sc = rtems_task_restart(id, 0);
-  rtems_test_assert(sc == RTEMS_INCORRECT_STATE);
 }
 
 static void Init(rtems_task_argument arg)




More information about the vc mailing list