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 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel