[rtems commit] score: Split _Thread_Restart()

Sebastian Huber sebh at rtems.org
Fri May 20 05:58:31 UTC 2016


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

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Fri May 13 07:04:43 2016 +0200

score: Split _Thread_Restart()

Split _Thread_Restart() into _Thread_Restart_self() and
_Thread_Restart_other().  Move content of existing
_Thread_Restart_self() into new _Thread_Restart_self().  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 | 36 +++-------
 cpukit/score/src/threadglobalconstruction.c   | 10 ++-
 cpukit/score/src/threadrestart.c              | 96 +++++++++++++++++++++++----
 4 files changed, 116 insertions(+), 68 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..e773523 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 );
@@ -687,30 +693,6 @@ RTEMS_INLINE_ROUTINE void _Thread_Unblock (
 }
 
 /**
- * This routine resets the current context of the calling thread
- * to that of its initial state.
- */
-
-RTEMS_INLINE_ROUTINE void _Thread_Restart_self( Thread_Control *executing )
-{
-#if defined(RTEMS_SMP)
-  ISR_Level level;
-
-  _Giant_Release( _Per_CPU_Get() );
-
-  _ISR_Disable_without_giant( level );
-  ( void ) level;
-#endif
-
-#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
-  if ( executing->fp_context != NULL )
-    _Context_Restore_fp( &executing->fp_context );
-#endif
-
-  _CPU_Context_Restart_self( &executing->Registers );
-}
-
-/**
  * This function returns true if the floating point context of
  * the_thread is currently loaded in the floating point unit, and
  * false otherwise.
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..8adbfa2 100644
--- a/cpukit/score/src/threadrestart.c
+++ b/cpukit/score/src/threadrestart.c
@@ -335,7 +335,25 @@ void _Thread_Life_action_handler(
 
       _User_extensions_Destroy_iterators( executing );
       _Thread_Load_environment( executing );
-      _Thread_Restart_self( executing );
+
+#if defined(RTEMS_SMP)
+      {
+        ISR_Level level;
+
+        _Giant_Release( _Per_CPU_Get() );
+
+        _ISR_Disable_without_giant( level );
+        (void) level;
+      }
+#endif
+
+#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
+      if ( executing->fp_context != NULL ) {
+        _Context_Restore_fp( &executing->fp_context );
+      }
+#endif
+
+      _Context_Restart_self( &executing->Registers );
       RTEMS_UNREACHABLE();
     }
   }
@@ -462,26 +480,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(



More information about the vc mailing list