summaryrefslogtreecommitdiffstats
path: root/cpukit
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2016-05-12 16:32:27 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2016-05-20 07:49:37 +0200
commit9949d8a7d042da7ba53516300db5c34c8b9c8a31 (patch)
tree614aded79bd69e1134dc1b83711b0636ca8e044d /cpukit
parentscore: Delete unused variable (diff)
downloadrtems-9949d8a7d042da7ba53516300db5c34c8b9c8a31.tar.bz2
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.
Diffstat (limited to 'cpukit')
-rw-r--r--cpukit/libcsupport/src/privateenv.c10
-rw-r--r--cpukit/score/include/rtems/score/apimutex.h2
-rw-r--r--cpukit/score/include/rtems/score/mrspimpl.h6
-rw-r--r--cpukit/score/include/rtems/score/threadimpl.h6
-rw-r--r--cpukit/score/src/apimutexlock.c10
-rw-r--r--cpukit/score/src/apimutexunlock.c11
-rw-r--r--cpukit/score/src/threadrestart.c95
7 files changed, 79 insertions, 61 deletions
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
+ );
}