diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2016-05-06 06:44:41 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2016-05-12 13:24:40 +0200 |
commit | 6e4f929296b1cfd50fc8f41f117459e65214b816 (patch) | |
tree | 9819ea160f6c745dae1936ae296709026d3d47a2 /cpukit/score | |
parent | score: Add _Thread_queue_Is_lock_owner() (diff) | |
download | rtems-6e4f929296b1cfd50fc8f41f117459e65214b816.tar.bz2 |
score: Introduce thread state lock
Update #2556.
Diffstat (limited to 'cpukit/score')
-rw-r--r-- | cpukit/score/include/rtems/score/thread.h | 54 | ||||
-rw-r--r-- | cpukit/score/include/rtems/score/threadimpl.h | 98 | ||||
-rw-r--r-- | cpukit/score/src/thread.c | 1 | ||||
-rw-r--r-- | cpukit/score/src/threaddispatch.c | 15 | ||||
-rw-r--r-- | cpukit/score/src/threadinitialize.c | 2 | ||||
-rw-r--r-- | cpukit/score/src/threadrestart.c | 44 |
6 files changed, 121 insertions, 93 deletions
diff --git a/cpukit/score/include/rtems/score/thread.h b/cpukit/score/include/rtems/score/thread.h index 8ea2db2cc1..d4ca5056ce 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 1d0421f0ce..931eec0d1b 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 83e98cbab2..2e0bbd91bb 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 ce5d118a22..a1f4c54f93 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 c3e6469679..47d546e67e 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 13b4365b35..ca054fab55 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) /* |