summaryrefslogtreecommitdiffstats
path: root/cpukit/score
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2016-05-06 06:44:41 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2016-05-12 13:24:40 +0200
commit6e4f929296b1cfd50fc8f41f117459e65214b816 (patch)
tree9819ea160f6c745dae1936ae296709026d3d47a2 /cpukit/score
parentscore: Add _Thread_queue_Is_lock_owner() (diff)
downloadrtems-6e4f929296b1cfd50fc8f41f117459e65214b816.tar.bz2
score: Introduce thread state lock
Update #2556.
Diffstat (limited to 'cpukit/score')
-rw-r--r--cpukit/score/include/rtems/score/thread.h54
-rw-r--r--cpukit/score/include/rtems/score/threadimpl.h98
-rw-r--r--cpukit/score/src/thread.c1
-rw-r--r--cpukit/score/src/threaddispatch.c15
-rw-r--r--cpukit/score/src/threadinitialize.c2
-rw-r--r--cpukit/score/src/threadrestart.c44
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)
/*