[PATCH 06/14] score: Introduce thread state lock

Sebastian Huber sebastian.huber at embedded-brains.de
Wed May 11 13:23:33 UTC 2016


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



More information about the devel mailing list