From 9949d8a7d042da7ba53516300db5c34c8b9c8a31 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Thu, 12 May 2016 16:32:27 +0200 Subject: score: Add Thread_Change_life() Add _Thread_Change_life_locked() as a general function to alter the thread life state. Use it to implement _Thread_Set_life_protection() as a first step. Update #2555. Update #2626. --- cpukit/libcsupport/src/privateenv.c | 10 +-- cpukit/score/include/rtems/score/apimutex.h | 2 +- cpukit/score/include/rtems/score/mrspimpl.h | 6 +- cpukit/score/include/rtems/score/threadimpl.h | 6 +- cpukit/score/src/apimutexlock.c | 10 +-- cpukit/score/src/apimutexunlock.c | 11 ++-- cpukit/score/src/threadrestart.c | 95 ++++++++++++++++----------- 7 files changed, 79 insertions(+), 61 deletions(-) (limited to 'cpukit') diff --git a/cpukit/libcsupport/src/privateenv.c b/cpukit/libcsupport/src/privateenv.c index 29821e4045..bf6036a1b3 100644 --- a/cpukit/libcsupport/src/privateenv.c +++ b/cpukit/libcsupport/src/privateenv.c @@ -57,7 +57,8 @@ rtems_status_code rtems_libio_set_private_env(void) bool uses_global_env = old_env == &rtems_global_user_env; if (uses_global_env) { - bool life_protection = _Thread_Set_life_protection(true); + Thread_Life_state life_state = + _Thread_Set_life_protection(THREAD_LIFE_PROTECTED); rtems_user_env_t *new_env = calloc(1, sizeof(*new_env)); if (new_env != NULL) { @@ -92,7 +93,7 @@ rtems_status_code rtems_libio_set_private_env(void) sc = RTEMS_NO_MEMORY; } - _Thread_Set_life_protection(life_protection); + _Thread_Set_life_protection(life_state); } return sc; @@ -104,11 +105,12 @@ void rtems_libio_use_global_env(void) bool uses_private_env = env != &rtems_global_user_env; if (uses_private_env) { - bool life_protection = _Thread_Set_life_protection(true); + Thread_Life_state life_state = + _Thread_Set_life_protection(THREAD_LIFE_PROTECTED); rtems_libio_free_user_env(env); pthread_setspecific(rtems_current_user_env_key, NULL); - _Thread_Set_life_protection(life_protection); + _Thread_Set_life_protection(life_state); } } diff --git a/cpukit/score/include/rtems/score/apimutex.h b/cpukit/score/include/rtems/score/apimutex.h index 86561aac74..1a4b1ee445 100644 --- a/cpukit/score/include/rtems/score/apimutex.h +++ b/cpukit/score/include/rtems/score/apimutex.h @@ -52,7 +52,7 @@ typedef struct { * @brief The thread life protection state before the outer-most mutex * obtain. */ - bool previous_thread_life_protection; + Thread_Life_state previous_thread_life_state; } API_Mutex_Control; /** diff --git a/cpukit/score/include/rtems/score/mrspimpl.h b/cpukit/score/include/rtems/score/mrspimpl.h index 1be320236a..f2570eb7fc 100644 --- a/cpukit/score/include/rtems/score/mrspimpl.h +++ b/cpukit/score/include/rtems/score/mrspimpl.h @@ -218,7 +218,7 @@ RTEMS_INLINE_ROUTINE MRSP_Status _MRSP_Wait_for_ownership( { MRSP_Status status; MRSP_Rival rival; - bool initial_life_protection; + Thread_Life_state life_state; Per_CPU_Control *cpu_self; ISR_lock_Context giant_lock_context; ISR_Level level; @@ -256,7 +256,7 @@ RTEMS_INLINE_ROUTINE MRSP_Status _MRSP_Wait_for_ownership( _ISR_Enable_without_giant( level ); } - initial_life_protection = _Thread_Set_life_protection( true ); + life_state = _Thread_Set_life_protection( THREAD_LIFE_PROTECTED ); _Thread_Dispatch_enable( cpu_self ); _Assert( _Debug_Is_thread_dispatching_allowed() ); @@ -266,7 +266,7 @@ RTEMS_INLINE_ROUTINE MRSP_Status _MRSP_Wait_for_ownership( status = rival.status; } while ( status == MRSP_WAIT_FOR_OWNERSHIP ); - _Thread_Set_life_protection( initial_life_protection ); + _Thread_Set_life_protection( life_state ); if ( timeout > 0 ) { _ISR_Disable_without_giant( level ); diff --git a/cpukit/score/include/rtems/score/threadimpl.h b/cpukit/score/include/rtems/score/threadimpl.h index be2095e023..e68f1191f8 100644 --- a/cpukit/score/include/rtems/score/threadimpl.h +++ b/cpukit/score/include/rtems/score/threadimpl.h @@ -198,7 +198,7 @@ bool _Thread_Restart( void _Thread_Yield( Thread_Control *executing ); -bool _Thread_Set_life_protection( bool protect ); +Thread_Life_state _Thread_Set_life_protection( Thread_Life_state state ); /** * @brief Kills all zombie threads in the system. @@ -934,11 +934,11 @@ RTEMS_INLINE_ROUTINE bool _Thread_Is_life_terminating( return ( life_state & THREAD_LIFE_TERMINATING ) != 0; } -RTEMS_INLINE_ROUTINE bool _Thread_Is_life_protected( +RTEMS_INLINE_ROUTINE bool _Thread_Is_life_change_allowed( Thread_Life_state life_state ) { - return ( life_state & THREAD_LIFE_PROTECTED ) != 0; + return ( life_state & THREAD_LIFE_PROTECTED ) == 0; } RTEMS_INLINE_ROUTINE bool _Thread_Is_life_changing( diff --git a/cpukit/score/src/apimutexlock.c b/cpukit/score/src/apimutexlock.c index 2e36518c55..79729d4d24 100644 --- a/cpukit/score/src/apimutexlock.c +++ b/cpukit/score/src/apimutexlock.c @@ -25,10 +25,11 @@ void _API_Mutex_Lock( API_Mutex_Control *the_mutex ) { - bool previous_thread_life_protection; - ISR_lock_Context lock_context; + Thread_Life_state previous_thread_life_state; + ISR_lock_Context lock_context; - previous_thread_life_protection = _Thread_Set_life_protection( true ); + previous_thread_life_state = + _Thread_Set_life_protection( THREAD_LIFE_PROTECTED ); _ISR_lock_ISR_disable( &lock_context ); @@ -41,7 +42,6 @@ void _API_Mutex_Lock( API_Mutex_Control *the_mutex ) ); if ( the_mutex->Mutex.nest_count == 1 ) { - the_mutex->previous_thread_life_protection = - previous_thread_life_protection; + the_mutex->previous_thread_life_state = previous_thread_life_state; } } diff --git a/cpukit/score/src/apimutexunlock.c b/cpukit/score/src/apimutexunlock.c index 3545377b43..e129dd2091 100644 --- a/cpukit/score/src/apimutexunlock.c +++ b/cpukit/score/src/apimutexunlock.c @@ -24,12 +24,11 @@ void _API_Mutex_Unlock( API_Mutex_Control *the_mutex ) { - ISR_lock_Context lock_context; - bool previous_thread_life_protection; - bool restore_thread_life_protection; + ISR_lock_Context lock_context; + Thread_Life_state previous_thread_life_state; + bool restore_thread_life_protection; - previous_thread_life_protection = - the_mutex->previous_thread_life_protection; + previous_thread_life_state = the_mutex->previous_thread_life_state; restore_thread_life_protection = the_mutex->Mutex.nest_count == 1; _ISR_lock_ISR_disable( &lock_context ); @@ -41,6 +40,6 @@ void _API_Mutex_Unlock( API_Mutex_Control *the_mutex ) ); if ( restore_thread_life_protection ) { - _Thread_Set_life_protection( previous_thread_life_protection ); + _Thread_Set_life_protection( previous_thread_life_state ); } } diff --git a/cpukit/score/src/threadrestart.c b/cpukit/score/src/threadrestart.c index 96423702f6..1d131d4d51 100644 --- a/cpukit/score/src/threadrestart.c +++ b/cpukit/score/src/threadrestart.c @@ -9,7 +9,7 @@ * COPYRIGHT (c) 1989-1999. * 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 @@ -213,6 +213,42 @@ static void _Thread_Start_life_change_for_executing( _Thread_Add_life_change_action( executing ); } +static Thread_Life_state _Thread_Change_life_locked( + Thread_Control *the_thread, + Thread_Life_state clear, + Thread_Life_state set, + Thread_Life_state ignore +) +{ + Thread_Life_state previous; + Thread_Life_state state; + + previous = the_thread->Life.state; + state = previous; + state &= ~clear; + state |= set; + the_thread->Life.state = state; + + state &= ~ignore; + + if ( + _Thread_Is_life_change_allowed( state ) + && _Thread_Is_life_changing( state ) + ) { + the_thread->is_preemptible = the_thread->Start.is_preemptible; + the_thread->budget_algorithm = the_thread->Start.budget_algorithm; + the_thread->budget_callout = the_thread->Start.budget_callout; + + _Thread_Add_post_switch_action( + the_thread, + &the_thread->Life.Action, + _Thread_Life_action_handler + ); + } + + return previous; +} + void _Thread_Life_action_handler( Thread_Control *executing, Thread_Action *action, @@ -393,52 +429,33 @@ bool _Thread_Restart( return false; } -bool _Thread_Set_life_protection( bool protect ) +static Thread_Life_state _Thread_Change_life( + Thread_Life_state clear, + Thread_Life_state set, + Thread_Life_state ignore +) { - bool previous_life_protection; ISR_lock_Context lock_context; Thread_Control *executing; - Thread_Life_state previous_life_state; + Per_CPU_Control *cpu_self; + Thread_Life_state previous; executing = _Thread_State_acquire_for_executing( &lock_context ); - previous_life_state = executing->Life.state; - previous_life_protection = _Thread_Is_life_protected( previous_life_state ); - - if ( protect ) { - executing->Life.state = previous_life_state | THREAD_LIFE_PROTECTED; - } else { - executing->Life.state = previous_life_state & ~THREAD_LIFE_PROTECTED; - } + previous = _Thread_Change_life_locked( executing, clear, set, ignore ); + cpu_self = _Thread_Dispatch_disable_critical( &lock_context ); _Thread_State_release( executing, &lock_context ); + _Thread_Dispatch_enable( cpu_self ); -#if defined(RTEMS_SMP) - /* - * On SMP configurations it is possible that a life change of an executing - * thread is requested, but this thread didn't notice it yet. The life - * change is first marked in the life state field and then all scheduling and - * other thread state updates are performed. The last step is to issues an - * inter-processor interrupt if necessary. Since this takes some time we - * have to synchronize here. - */ - if ( - !_Thread_Is_life_protected( previous_life_state ) - && _Thread_Is_life_changing( previous_life_state ) - ) { - _Thread_Disable_dispatch(); - _Thread_Enable_dispatch(); - } -#endif - - if ( - !protect - && _Thread_Is_life_changing( previous_life_state ) - ) { - _Thread_Disable_dispatch(); - _Thread_Start_life_change_for_executing( executing ); - _Thread_Enable_dispatch(); - } + return previous; +} - return previous_life_protection; +Thread_Life_state _Thread_Set_life_protection( Thread_Life_state state ) +{ + return _Thread_Change_life( + THREAD_LIFE_PROTECTED, + state & THREAD_LIFE_PROTECTED, + 0 + ); } -- cgit v1.2.3