mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2026-09-24 10:05:08 +08:00
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:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user