Update #2556. --- cpukit/posix/src/psignalunblockthread.c | 20 +++--- cpukit/rtems/include/rtems/rtems/signalimpl.h | 8 +-- cpukit/rtems/src/signalcatch.c | 10 +-- cpukit/rtems/src/signalsend.c | 7 +- cpukit/rtems/src/taskmode.c | 4 +- cpukit/score/include/rtems/score/thread.h | 54 +++++++++------ cpukit/score/include/rtems/score/threadimpl.h | 98 ++++++++++++++------------- cpukit/score/src/thread.c | 1 + cpukit/score/src/threaddispatch.c | 15 ++-- cpukit/score/src/threadinitialize.c | 2 + cpukit/score/src/threadrestart.c | 44 +++++++----- 11 files changed, 149 insertions(+), 114 deletions(-)
diff --git a/cpukit/posix/src/psignalunblockthread.c b/cpukit/posix/src/psignalunblockthread.c index df4a491..5635afa 100644 --- a/cpukit/posix/src/psignalunblockthread.c +++ b/cpukit/posix/src/psignalunblockthread.c @@ -91,19 +91,17 @@ static void _POSIX_signals_Check_signal( } static void _POSIX_signals_Action_handler( - Thread_Control *executing, - Thread_Action *action, - Per_CPU_Control *cpu, - ISR_Level level + Thread_Control *executing, + Thread_Action *action, + ISR_lock_Context *lock_context ) { POSIX_API_Control *api; int signo; - ISR_lock_Context lock_context; int hold_errno; (void) action; - _Thread_Action_release_and_ISR_enable( cpu, level ); + _Thread_State_release( executing, lock_context ); api = executing->API_Extensions[ THREAD_API_POSIX ]; @@ -137,13 +135,13 @@ static void _POSIX_signals_Action_handler( * processed at all. No point in doing this loop otherwise. */ while (1) { - _POSIX_signals_Acquire( &lock_context ); + _POSIX_signals_Acquire( lock_context ); if ( !(api->signals_unblocked & (api->signals_pending | _POSIX_signals_Pending)) ) { - _POSIX_signals_Release( &lock_context ); + _POSIX_signals_Release( lock_context ); break; } - _POSIX_signals_Release( &lock_context ); + _POSIX_signals_Release( lock_context ); for ( signo = SIGRTMIN ; signo <= SIGRTMAX ; signo++ ) { _POSIX_signals_Check_signal( api, signo, false ); @@ -166,11 +164,15 @@ static bool _POSIX_signals_Unblock_thread_done( bool status ) { + ISR_lock_Context lock_context; + + _Thread_State_acquire( the_thread, &lock_context ); _Thread_Add_post_switch_action( the_thread, &api->Signal_action, _POSIX_signals_Action_handler ); + _Thread_State_release( the_thread, &lock_context ); return status; } diff --git a/cpukit/rtems/include/rtems/rtems/signalimpl.h b/cpukit/rtems/include/rtems/rtems/signalimpl.h index b19b2ac..61848ae 100644 --- a/cpukit/rtems/include/rtems/rtems/signalimpl.h +++ b/cpukit/rtems/include/rtems/rtems/signalimpl.h @@ -18,7 +18,6 @@ #define _RTEMS_RTEMS_SIGNALIMPL_H #include <rtems/rtems/signal.h> -#include <rtems/score/percpu.h> #include <rtems/score/thread.h> #ifdef __cplusplus @@ -33,10 +32,9 @@ extern "C" { /**@{*/ void _Signal_Action_handler( - Thread_Control *thread, - Thread_Action *action, - Per_CPU_Control *cpu, - ISR_Level level + Thread_Control *executing, + Thread_Action *action, + ISR_lock_Context *lock_context ); /**@}*/ diff --git a/cpukit/rtems/src/signalcatch.c b/cpukit/rtems/src/signalcatch.c index 73138a1..e300890 100644 --- a/cpukit/rtems/src/signalcatch.c +++ b/cpukit/rtems/src/signalcatch.c @@ -22,13 +22,13 @@ #include <rtems/rtems/signalimpl.h> #include <rtems/rtems/asrimpl.h> #include <rtems/rtems/tasks.h> +#include <rtems/score/assert.h> #include <rtems/score/threadimpl.h> void _Signal_Action_handler( - Thread_Control *executing, - Thread_Action *action, - Per_CPU_Control *cpu, - ISR_Level level + Thread_Control *executing, + Thread_Action *action, + ISR_lock_Context *lock_context ) { RTEMS_API_Control *api; @@ -37,7 +37,7 @@ void _Signal_Action_handler( Modes_Control prev_mode; (void) action; - _Thread_Action_release_and_ISR_enable( cpu, level ); + _Thread_State_release( executing, lock_context ); api = executing->API_Extensions[ THREAD_API_RTEMS ]; if ( !api ) diff --git a/cpukit/rtems/src/signalsend.c b/cpukit/rtems/src/signalsend.c index 162de5c..abf3d5d 100644 --- a/cpukit/rtems/src/signalsend.c +++ b/cpukit/rtems/src/signalsend.c @@ -59,14 +59,19 @@ rtems_status_code rtems_signal_send( } if ( asr->is_enabled ) { + Per_CPU_Control *cpu_self; + _ASR_Post_signals( signal_set, &asr->signals_posted ); _ASR_Release( asr, &lock_context ); + _Thread_State_acquire( the_thread, &lock_context ); _Thread_Add_post_switch_action( the_thread, &api->Signal_action, _Signal_Action_handler ); - _Thread_Dispatch(); + cpu_self = _Thread_Dispatch_disable_critical( &lock_context ); + _Thread_State_release( the_thread, &lock_context ); + _Thread_Dispatch_enable( cpu_self ); } else { _ASR_Post_signals( signal_set, &asr->signals_pending ); _ASR_Release( asr, &lock_context ); diff --git a/cpukit/rtems/src/taskmode.c b/cpukit/rtems/src/taskmode.c index e2dc7ed..2f8f354 100644 --- a/cpukit/rtems/src/taskmode.c +++ b/cpukit/rtems/src/taskmode.c @@ -32,6 +32,7 @@ rtems_status_code rtems_task_mode( rtems_mode *previous_mode_set ) { + ISR_lock_Context lock_context; Thread_Control *executing; RTEMS_API_Control *api; ASR_Information *asr; @@ -102,18 +103,19 @@ rtems_status_code rtems_task_mode( if ( _ASR_Swap_signals( asr ) != 0 ) { needs_asr_dispatching = true; + _Thread_State_acquire( executing, &lock_context ); _Thread_Add_post_switch_action( executing, &api->Signal_action, _Signal_Action_handler ); + _Thread_State_release( executing, &lock_context ); } } } if ( preempt_enabled || needs_asr_dispatching ) { Per_CPU_Control *cpu_self; - ISR_lock_Context lock_context; cpu_self = _Thread_Dispatch_disable(); _Scheduler_Acquire( executing, &lock_context ); diff --git a/cpukit/score/include/rtems/score/thread.h b/cpukit/score/include/rtems/score/thread.h index 8ea2db2..d4ca505 100644 --- a/cpukit/score/include/rtems/score/thread.h +++ b/cpukit/score/include/rtems/score/thread.h @@ -343,9 +343,14 @@ typedef struct { typedef struct { /** This field is the object management structure for each proxy. */ Objects_Control Object; + + /** + * @see Thread_Control::Join_queue + */ + Thread_queue_Control Join_queue; + /** This field is the current execution state of this proxy. */ States_Control current_state; - /** * @brief This field is the current priority state of this thread. * @@ -445,24 +450,23 @@ typedef struct Thread_Action Thread_Action; /** * @brief Thread action handler. * - * The thread action handler will be called with interrupts disabled and the - * thread action lock acquired. The handler must release the thread action - * lock with _Thread_Action_release_and_ISR_enable(). So the thread action - * lock can be used to protect private data fields of the particular action. + * The thread action handler will be called with interrupts disabled and a + * corresponding lock acquired, e.g. _Thread_State_acquire(). The handler must + * release the corresponding lock, e.g. _Thread_State_release(). So, the + * corresponding lock may be used to protect private data used by the + * particular action. * - * Since the action is passed to the handler private data fields can be added - * below the common thread action fields. + * Since the action is passed to the handler additional data may be accessed + * via RTEMS_CONTAINER_OF(). * - * @param[in] thread The thread performing the action. + * @param[in] the_thread The thread performing the action. * @param[in] action The thread action. - * @param[in] cpu The processor of the thread. - * @param[in] level The ISR level for _Thread_Action_release_and_ISR_enable(). + * @param[in] lock_context The lock context to use for the lock release. */ typedef void ( *Thread_Action_handler )( - Thread_Control *thread, - Thread_Action *action, - struct Per_CPU_Control *cpu, - ISR_Level level + Thread_Control *the_thread, + Thread_Action *action, + ISR_lock_Context *lock_context ); /** @@ -474,13 +478,10 @@ typedef void ( *Thread_Action_handler )( * * Thread actions are the building block for efficient implementation of * - Classic signals delivery, - * - POSIX signals delivery, - * - thread restart notification, - * - thread delete notification, - * - forced thread migration on SMP configurations, and - * - the Multiprocessor Resource Sharing Protocol (MrsP). + * - POSIX signals delivery, and + * - thread life-cycle changes. * - * @see _Thread_Run_post_switch_actions(). + * @see _Thread_Add_post_switch_action() and _Thread_Run_post_switch_actions(). */ struct Thread_Action { Chain_Node Node; @@ -710,6 +711,19 @@ typedef struct { struct _Thread_Control { /** This field is the object management structure for each thread. */ Objects_Control Object; + + /** + * @brief Thread queue for thread join operations and multi-purpose lock. + * + * The lock of this thread queue is used for various purposes. It protects + * the following fields + * + * - Thread_Control::Post_switch_actions. + * + * @see _Thread_State_acquire(). + */ + Thread_queue_Control Join_queue; + /** This field is the current execution state of this thread. */ States_Control current_state; diff --git a/cpukit/score/include/rtems/score/threadimpl.h b/cpukit/score/include/rtems/score/threadimpl.h index 1d0421f..931eec0 100644 --- a/cpukit/score/include/rtems/score/threadimpl.h +++ b/cpukit/score/include/rtems/score/threadimpl.h @@ -200,13 +200,6 @@ void _Thread_Yield( Thread_Control *executing ); bool _Thread_Set_life_protection( bool protect ); -void _Thread_Life_action_handler( - Thread_Control *executing, - Thread_Action *action, - Per_CPU_Control *cpu, - ISR_Level level -); - /** * @brief Kills all zombie threads in the system. * @@ -337,6 +330,52 @@ void _Thread_Delay_ended( void *ignored ); +RTEMS_INLINE_ROUTINE void _Thread_State_acquire_critical( + Thread_Control *the_thread, + ISR_lock_Context *lock_context +) +{ + _Thread_queue_Acquire_critical( &the_thread->Join_queue, lock_context ); +} + +RTEMS_INLINE_ROUTINE void _Thread_State_acquire( + Thread_Control *the_thread, + ISR_lock_Context *lock_context +) +{ + _Thread_queue_Acquire( &the_thread->Join_queue, lock_context ); +} + +RTEMS_INLINE_ROUTINE Thread_Control *_Thread_State_acquire_for_executing( + ISR_lock_Context *lock_context +) +{ + Thread_Control *executing; + + _ISR_lock_ISR_disable( lock_context ); + executing = _Thread_Executing; + _Thread_State_acquire_critical( executing, lock_context ); + + return executing; +} + +RTEMS_INLINE_ROUTINE void _Thread_State_release( + Thread_Control *the_thread, + ISR_lock_Context *lock_context +) +{ + _Thread_queue_Release( &the_thread->Join_queue, lock_context ); +} + +#if defined(RTEMS_DEBUG) +RTEMS_INLINE_ROUTINE bool _Thread_State_is_owner( + const Thread_Control *the_thread +) +{ + return _Thread_queue_Is_lock_owner( &the_thread->Join_queue ); +} +#endif + /** * @brief Returns true if the left thread priority is less than the right * thread priority in the intuitive sense of priority and false otherwise. @@ -841,50 +880,17 @@ RTEMS_INLINE_ROUTINE void _Thread_Action_initialize( _Chain_Set_off_chain( &action->Node ); } -RTEMS_INLINE_ROUTINE Per_CPU_Control * - _Thread_Action_ISR_disable_and_acquire_for_executing( ISR_Level *level ) -{ - Per_CPU_Control *cpu; - - _ISR_Disable_without_giant( *level ); - cpu = _Per_CPU_Get(); - _Per_CPU_Acquire( cpu ); - - return cpu; -} - -RTEMS_INLINE_ROUTINE Per_CPU_Control *_Thread_Action_ISR_disable_and_acquire( - Thread_Control *thread, - ISR_Level *level -) -{ - Per_CPU_Control *cpu; - - _ISR_Disable_without_giant( *level ); - cpu = _Thread_Get_CPU( thread ); - _Per_CPU_Acquire( cpu ); - - return cpu; -} - -RTEMS_INLINE_ROUTINE void _Thread_Action_release_and_ISR_enable( - Per_CPU_Control *cpu, - ISR_Level level -) -{ - _Per_CPU_Release_and_ISR_enable( cpu, level ); -} - RTEMS_INLINE_ROUTINE void _Thread_Add_post_switch_action( - Thread_Control *thread, + Thread_Control *the_thread, Thread_Action *action, Thread_Action_handler handler ) { Per_CPU_Control *cpu_of_thread; - ISR_Level level; - cpu_of_thread = _Thread_Action_ISR_disable_and_acquire( thread, &level ); + _Assert( _Thread_State_is_owner( the_thread ) ); + + cpu_of_thread = _Thread_Get_CPU( the_thread ); action->handler = handler; @@ -899,11 +905,9 @@ RTEMS_INLINE_ROUTINE void _Thread_Add_post_switch_action( #endif _Chain_Append_if_is_off_chain_unprotected( - &thread->Post_switch_actions.Chain, + &the_thread->Post_switch_actions.Chain, &action->Node ); - - _Thread_Action_release_and_ISR_enable( cpu_of_thread, level ); } RTEMS_INLINE_ROUTINE bool _Thread_Is_life_restarting( diff --git a/cpukit/score/src/thread.c b/cpukit/score/src/thread.c index 83e98cb..2e0bbd9 100644 --- a/cpukit/score/src/thread.c +++ b/cpukit/score/src/thread.c @@ -30,6 +30,7 @@ ) THREAD_OFFSET_ASSERT( Object ); +THREAD_OFFSET_ASSERT( Join_queue ); THREAD_OFFSET_ASSERT( current_state ); THREAD_OFFSET_ASSERT( current_priority ); THREAD_OFFSET_ASSERT( real_priority ); diff --git a/cpukit/score/src/threaddispatch.c b/cpukit/score/src/threaddispatch.c index ce5d118..a1f4c54 100644 --- a/cpukit/score/src/threaddispatch.c +++ b/cpukit/score/src/threaddispatch.c @@ -9,7 +9,7 @@ * COPYRIGHT (c) 1989-2009. * On-Line Applications Research Corporation (OAR). * - * Copyright (c) 2014 embedded brains GmbH. + * Copyright (c) 2014, 2016 embedded brains GmbH. * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at @@ -50,23 +50,22 @@ static Thread_Action *_Thread_Get_post_switch_action( static void _Thread_Run_post_switch_actions( Thread_Control *executing ) { - ISR_Level level; - Per_CPU_Control *cpu_self; - Thread_Action *action; + ISR_lock_Context lock_context; + Thread_Action *action; - cpu_self = _Thread_Action_ISR_disable_and_acquire( executing, &level ); + _Thread_State_acquire( executing, &lock_context ); action = _Thread_Get_post_switch_action( executing ); while ( action != NULL ) { _Chain_Set_off_chain( &action->Node ); - ( *action->handler )( executing, action, cpu_self, level ); + ( *action->handler )( executing, action, &lock_context ); - cpu_self = _Thread_Action_ISR_disable_and_acquire( executing, &level ); + _Thread_State_acquire( executing, &lock_context ); action = _Thread_Get_post_switch_action( executing ); } - _Thread_Action_release_and_ISR_enable( cpu_self, level ); + _Thread_State_release( executing, &lock_context ); } void _Thread_Do_dispatch( Per_CPU_Control *cpu_self, ISR_Level level ) diff --git a/cpukit/score/src/threadinitialize.c b/cpukit/score/src/threadinitialize.c index c3e6469..47d546e 100644 --- a/cpukit/score/src/threadinitialize.c +++ b/cpukit/score/src/threadinitialize.c @@ -190,6 +190,8 @@ bool _Thread_Initialize( /* Initialize the CPU for the non-SMP schedulers */ _Thread_Set_CPU( the_thread, cpu ); + _Thread_queue_Initialize( &the_thread->Join_queue ); + the_thread->current_state = STATES_DORMANT; the_thread->Wait.operations = &_Thread_queue_Operations_default; the_thread->current_priority = priority; diff --git a/cpukit/score/src/threadrestart.c b/cpukit/score/src/threadrestart.c index 13b4365..ca054fa 100644 --- a/cpukit/score/src/threadrestart.c +++ b/cpukit/score/src/threadrestart.c @@ -32,6 +32,12 @@ #include <rtems/score/watchdogimpl.h> #include <rtems/score/wkspace.h> +static void _Thread_Life_action_handler( + Thread_Control *executing, + Thread_Action *action, + ISR_lock_Context *lock_context +); + typedef struct { Chain_Control Chain; ISR_lock_Control Lock; @@ -133,6 +139,8 @@ static void _Thread_Free( Thread_Control *the_thread ) _SMP_lock_Stats_destroy( &the_thread->Potpourri_stats ); #endif + _Thread_queue_Destroy( &the_thread->Join_queue ); + _Objects_Free( &information->Objects, &the_thread->Object ); } @@ -179,11 +187,15 @@ static void _Thread_Add_life_change_action( Thread_Control *the_thread ) { + ISR_lock_Context lock_context; + + _Thread_State_acquire( the_thread, &lock_context ); _Thread_Add_post_switch_action( the_thread, &the_thread->Life.Action, _Thread_Life_action_handler ); + _Thread_State_release( the_thread, &lock_context ); } static void _Thread_Start_life_change_for_executing( @@ -202,10 +214,9 @@ static void _Thread_Start_life_change_for_executing( } void _Thread_Life_action_handler( - Thread_Control *executing, - Thread_Action *action, - Per_CPU_Control *cpu, - ISR_Level level + Thread_Control *executing, + Thread_Action *action, + ISR_lock_Context *lock_context ) { Thread_Life_state previous_life_state; @@ -215,7 +226,7 @@ void _Thread_Life_action_handler( previous_life_state = executing->Life.state; executing->Life.state = THREAD_LIFE_PROTECTED; - _Thread_Action_release_and_ISR_enable( cpu, level ); + _Thread_State_release( executing, lock_context ); if ( _Thread_Is_life_terminating( previous_life_state ) ) { _User_extensions_Thread_terminate( executing ); @@ -295,15 +306,14 @@ static void _Thread_Request_life_change( Thread_Life_state additional_life_state ) { - Thread_Life_state previous_life_state; - Per_CPU_Control *cpu; - ISR_Level level; + Thread_Life_state previous_life_state; + ISR_lock_Context lock_context; const Scheduler_Control *scheduler; - cpu = _Thread_Action_ISR_disable_and_acquire( the_thread, &level ); + _Thread_State_acquire( the_thread, &lock_context ); previous_life_state = the_thread->Life.state; the_thread->Life.state = previous_life_state | additional_life_state; - _Thread_Action_release_and_ISR_enable( cpu, level ); + _Thread_State_release( the_thread, &lock_context ); scheduler = _Scheduler_Get( the_thread ); if ( the_thread == executing ) { @@ -381,14 +391,12 @@ bool _Thread_Restart( bool _Thread_Set_life_protection( bool protect ) { - bool previous_life_protection; - ISR_Level level; - Per_CPU_Control *cpu; - Thread_Control *executing; - Thread_Life_state previous_life_state; + bool previous_life_protection; + ISR_lock_Context lock_context; + Thread_Control *executing; + Thread_Life_state previous_life_state; - cpu = _Thread_Action_ISR_disable_and_acquire_for_executing( &level ); - executing = cpu->executing; + executing = _Thread_State_acquire_for_executing( &lock_context ); previous_life_state = executing->Life.state; previous_life_protection = _Thread_Is_life_protected( previous_life_state ); @@ -399,7 +407,7 @@ bool _Thread_Set_life_protection( bool protect ) executing->Life.state = previous_life_state & ~THREAD_LIFE_PROTECTED; } - _Thread_Action_release_and_ISR_enable( cpu, level ); + _Thread_State_release( executing, &lock_context ); #if defined(RTEMS_SMP) /* -- 1.8.4.5 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel