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.
This commit is contained in:
Sebastian Huber
2016-05-20 07:49:38 +02:00
parent 0475cca9a0
commit 9388390777
4 changed files with 115 additions and 67 deletions
+20 -20
View File
@@ -26,32 +26,32 @@ rtems_status_code rtems_task_restart(
uint32_t argument
)
{
Thread_Control *the_thread;
Objects_Locations location;
Thread_Entry_information entry;
Thread_Control *the_thread;
ISR_lock_Context lock_context;
Thread_Entry_information entry;
bool ok;
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;
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;
}
+9 -27
View File
@@ -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 );
@@ -686,30 +692,6 @@ RTEMS_INLINE_ROUTINE void _Thread_Unblock (
_Thread_Clear_state( the_thread, STATES_BLOCKED );
}
/**
* 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
+4 -6
View File
@@ -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 );
}
+82 -14
View File
@@ -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(