[PATCH 13/32] score: Split _Thread_Restart()

Sebastian Huber sebastian.huber at embedded-brains.de
Wed May 18 09:20:32 UTC 2016


Rename _Thread_Restart_self() into _Thread_Do_self_restart().  Split
_Thread_Restart() into _Thread_Restart_self() and
_Thread_Restart_other().  Avoid Giant lock for thread restart.
_Thread_Restart_self() is a no-return function and used by
_Thread_Global_construction().

Update #2555.
Update #2626.
---
 cpukit/rtems/src/taskrestart.c                | 42 +++++++--------
 cpukit/score/include/rtems/score/threadimpl.h | 14 +++--
 cpukit/score/src/threadglobalconstruction.c   | 10 ++--
 cpukit/score/src/threadrestart.c              | 78 ++++++++++++++++++++++-----
 4 files changed, 99 insertions(+), 45 deletions(-)

diff --git a/cpukit/rtems/src/taskrestart.c b/cpukit/rtems/src/taskrestart.c
index 8aa7c73..6e4ad96 100644
--- a/cpukit/rtems/src/taskrestart.c
+++ b/cpukit/rtems/src/taskrestart.c
@@ -26,32 +26,32 @@ rtems_status_code rtems_task_restart(
   uint32_t  argument
 )
 {
-  Thread_Control          *the_thread;
-  Objects_Locations        location;
-  Thread_Entry_information entry;
-
-  the_thread = _Thread_Get( id, &location );
-  switch ( location ) {
-
-    case OBJECTS_LOCAL:
-      entry = the_thread->Start.Entry;
-      entry.Kinds.Numeric.argument = argument;
-      if ( _Thread_Restart( the_thread, _Thread_Executing, &entry ) ) {
-        _Objects_Put( &the_thread->Object );
-        return RTEMS_SUCCESSFUL;
-      }
-      _Objects_Put( &the_thread->Object );
-      return RTEMS_INCORRECT_STATE;
+  Thread_Control           *the_thread;
+  ISR_lock_Context          lock_context;
+  Thread_Entry_information  entry;
+  bool                      ok;
 
+  the_thread = _Thread_Get_interrupt_disable( id, &lock_context );
+
+  if ( the_thread == NULL ) {
 #if defined(RTEMS_MULTIPROCESSING)
-    case OBJECTS_REMOTE:
-      _Thread_Dispatch();
+    if ( _Thread_MP_Is_remote( id ) ) {
       return RTEMS_ILLEGAL_ON_REMOTE_OBJECT;
+    }
 #endif
 
-    case OBJECTS_ERROR:
-      break;
+    return RTEMS_INVALID_ID;
   }
 
-  return RTEMS_INVALID_ID;
+  entry = the_thread->Start.Entry;
+  entry.Kinds.Numeric.argument = argument;
+
+  if ( the_thread == _Thread_Executing ) {
+    _Thread_Restart_self( the_thread, &entry, &lock_context );
+    RTEMS_UNREACHABLE();
+  }
+
+  ok = _Thread_Restart_other( the_thread, &entry, &lock_context );
+
+  return ok ? RTEMS_SUCCESSFUL : RTEMS_INCORRECT_STATE;
 }
diff --git a/cpukit/score/include/rtems/score/threadimpl.h b/cpukit/score/include/rtems/score/threadimpl.h
index 68b9e72..0784b50 100644
--- a/cpukit/score/include/rtems/score/threadimpl.h
+++ b/cpukit/score/include/rtems/score/threadimpl.h
@@ -190,10 +190,16 @@ bool _Thread_Start(
   const Thread_Entry_information *entry
 );
 
-bool _Thread_Restart(
-  Thread_Control                 *the_thread,
+void _Thread_Restart_self(
   Thread_Control                 *executing,
-  const Thread_Entry_information *entry
+  const Thread_Entry_information *entry,
+  ISR_lock_Context               *lock_context
+) RTEMS_NO_RETURN;
+
+bool _Thread_Restart_other(
+  Thread_Control                 *the_thread,
+  const Thread_Entry_information *entry,
+  ISR_lock_Context               *lock_context
 );
 
 void _Thread_Yield( Thread_Control *executing );
@@ -691,7 +697,7 @@ RTEMS_INLINE_ROUTINE void _Thread_Unblock (
  * to that of its initial state.
  */
 
-RTEMS_INLINE_ROUTINE void _Thread_Restart_self( Thread_Control *executing )
+RTEMS_INLINE_ROUTINE void _Thread_Do_self_restart( Thread_Control *executing )
 {
 #if defined(RTEMS_SMP)
   ISR_Level level;
diff --git a/cpukit/score/src/threadglobalconstruction.c b/cpukit/score/src/threadglobalconstruction.c
index 997f285..7ce1862 100644
--- a/cpukit/score/src/threadglobalconstruction.c
+++ b/cpukit/score/src/threadglobalconstruction.c
@@ -20,8 +20,6 @@
 #endif
 
 #include <rtems/score/threadimpl.h>
-#include <rtems/score/assert.h>
-#include <rtems/config.h>
 
 /*
  *  Conditional magic to determine what style of C++ constructor
@@ -49,6 +47,8 @@ void _Thread_Global_construction(
   const Thread_Entry_information *entry
 )
 {
+  ISR_lock_Context lock_context;
+
 #if defined(EXECUTE_GLOBAL_CONSTRUCTORS)
   /*
    *  _init could be a weak symbol and we SHOULD test it but it isn't
@@ -58,8 +58,6 @@ void _Thread_Global_construction(
   INIT_NAME();
 #endif
 
-  _Thread_Disable_dispatch();
-  _Thread_Restart( executing, executing, entry );
-  _Thread_Enable_dispatch();
-  RTEMS_UNREACHABLE();
+  _ISR_lock_ISR_disable( &lock_context );
+  _Thread_Restart_self( _Thread_Executing, entry, &lock_context );
 }
diff --git a/cpukit/score/src/threadrestart.c b/cpukit/score/src/threadrestart.c
index 9ab053c..1ebefa7 100644
--- a/cpukit/score/src/threadrestart.c
+++ b/cpukit/score/src/threadrestart.c
@@ -335,7 +335,7 @@ void _Thread_Life_action_handler(
 
       _User_extensions_Destroy_iterators( executing );
       _Thread_Load_environment( executing );
-      _Thread_Restart_self( executing );
+      _Thread_Do_self_restart( executing );
       RTEMS_UNREACHABLE();
     }
   }
@@ -462,26 +462,76 @@ void _Thread_Exit( Thread_Control *executing )
   _Thread_State_release( executing, &lock_context );
 }
 
-bool _Thread_Restart(
+bool _Thread_Restart_other(
   Thread_Control                 *the_thread,
-  Thread_Control                 *executing,
-  const Thread_Entry_information *entry
+  const Thread_Entry_information *entry,
+  ISR_lock_Context               *lock_context
 )
 {
-  if ( !_States_Is_dormant( the_thread->current_state ) ) {
-    the_thread->Start.Entry = *entry;
+  Per_CPU_Control *cpu_self;
 
-    _Thread_Request_life_change(
-      the_thread,
-      executing,
-      the_thread->Start.initial_priority,
-      THREAD_LIFE_RESTARTING
-    );
+  _Thread_State_acquire_critical( the_thread, lock_context );
 
-    return true;
+  if ( _States_Is_dormant( the_thread->current_state ) ) {
+    _Thread_State_release( the_thread, lock_context );
+    return false;
   }
 
-  return false;
+  the_thread->Start.Entry = *entry;
+
+  cpu_self = _Thread_Dispatch_disable_critical( lock_context );
+  _Thread_State_release( the_thread, lock_context );
+
+  _Thread_Request_life_change(
+    the_thread,
+    NULL,
+    the_thread->Start.initial_priority,
+    THREAD_LIFE_RESTARTING
+  );
+
+  _Thread_Dispatch_enable( cpu_self );
+  return true;
+}
+
+void _Thread_Restart_self(
+  Thread_Control                 *executing,
+  const Thread_Entry_information *entry,
+  ISR_lock_Context               *lock_context
+)
+{
+  Per_CPU_Control  *cpu_self;
+  Priority_Control  unused;
+
+  _Assert(
+    _Watchdog_Get_state( &executing->Timer.Watchdog ) == WATCHDOG_INACTIVE
+  );
+  _Assert(
+    executing->current_state == STATES_READY
+      || executing->current_state == STATES_SUSPENDED
+  );
+
+  _Thread_State_acquire_critical( executing, lock_context );
+
+  executing->Start.Entry = *entry;
+  _Thread_Change_life_locked(
+    executing,
+    0,
+    THREAD_LIFE_RESTARTING,
+    THREAD_LIFE_PROTECTED
+  );
+
+  cpu_self = _Thread_Dispatch_disable_critical( lock_context );
+  _Thread_State_release( executing, lock_context );
+
+  _Thread_Set_priority(
+    executing,
+    executing->Start.initial_priority,
+    &unused,
+    true
+  );
+
+  _Thread_Dispatch_enable( cpu_self );
+  RTEMS_UNREACHABLE();
 }
 
 static Thread_Life_state _Thread_Change_life(
-- 
1.8.4.5



More information about the devel mailing list