[rtems commit] score: Add _Scheduler_Help()

Sebastian Huber sebh at rtems.org
Tue Jul 8 14:57:17 UTC 2014


Module:    rtems
Branch:    master
Commit:    ac532f33508cc052108a8f8d9ab1eb933bb5a6f8
Changeset: http://git.rtems.org/rtems/commit/?id=ac532f33508cc052108a8f8d9ab1eb933bb5a6f8

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Fri Jul  4 13:40:10 2014 +0200

score: Add _Scheduler_Help()

Manage the help state of threads with respect to scheduling decisions.

---

 cpukit/score/include/rtems/score/mrspimpl.h        |   32 ++++---
 cpukit/score/include/rtems/score/scheduler.h       |   96 ++++++++++++++++++++
 cpukit/score/include/rtems/score/schedulerimpl.h   |   41 +++++++++
 .../score/include/rtems/score/schedulersmpimpl.h   |    4 +-
 4 files changed, 159 insertions(+), 14 deletions(-)

diff --git a/cpukit/score/include/rtems/score/mrspimpl.h b/cpukit/score/include/rtems/score/mrspimpl.h
index 5efb619..6aa45a8 100644
--- a/cpukit/score/include/rtems/score/mrspimpl.h
+++ b/cpukit/score/include/rtems/score/mrspimpl.h
@@ -102,6 +102,7 @@ RTEMS_INLINE_ROUTINE void _MRSP_Claim_ownership(
   _Resource_Set_owner( &mrsp->Resource, &new_owner->Resource_node );
   mrsp->initial_priority_of_owner = initial_priority;
   _MRSP_Elevate_priority( mrsp, new_owner, ceiling_priority );
+  _Scheduler_Thread_change_help_state( new_owner, SCHEDULER_HELP_ACTIVE_OWNER );
 }
 
 RTEMS_INLINE_ROUTINE MRSP_Status _MRSP_Initialize(
@@ -185,6 +186,7 @@ RTEMS_INLINE_ROUTINE MRSP_Status _MRSP_Wait_for_ownership(
   MRSP_Rival rival;
   bool previous_life_protection;
   unsigned int state;
+  Scheduler_Help_state previous_help_state;
 
   _MRSP_Elevate_priority( mrsp, executing, ceiling_priority );
 
@@ -193,6 +195,8 @@ RTEMS_INLINE_ROUTINE MRSP_Status _MRSP_Wait_for_ownership(
   _Chain_Append_unprotected( &mrsp->Rivals, &rival.Node );
   _Resource_Add_rival( &mrsp->Resource, &executing->Resource_node );
   _Resource_Node_set_dependency( &executing->Resource_node, &mrsp->Resource );
+  previous_help_state =
+    _Scheduler_Thread_change_help_state( executing, SCHEDULER_HELP_ACTIVE_RIVAL );
   _MRSP_Set_root(
     &executing->Resource_node,
     _Resource_Node_get_root( owner )
@@ -234,11 +238,10 @@ RTEMS_INLINE_ROUTINE MRSP_Status _MRSP_Wait_for_ownership(
     mrsp->initial_priority_of_owner = initial_priority;
     status = MRSP_SUCCESSFUL;
   } else {
-    Resource_Node *executing_node = &executing->Resource_node;
-
-    _Resource_Node_extract( executing_node );
-    _Resource_Node_set_dependency( executing_node, NULL );
-    _MRSP_Set_root( executing_node, executing_node );
+    _Resource_Node_extract( &executing->Resource_node );
+    _Resource_Node_set_dependency( &executing->Resource_node, NULL );
+    _Scheduler_Thread_change_help_state( executing, previous_help_state );
+    _MRSP_Set_root( &executing->Resource_node, &executing->Resource_node );
     _MRSP_Restore_priority( mrsp, executing, initial_priority );
 
     status = MRSP_TIMEOUT;
@@ -324,16 +327,21 @@ RTEMS_INLINE_ROUTINE MRSP_Status _MRSP_Release(
     _Resource_Set_owner( &mrsp->Resource, NULL );
   } else {
     MRSP_Rival *rival = (MRSP_Rival *) _Chain_First( &mrsp->Rivals );
-    Resource_Node *new_owner = &rival->thread->Resource_node;
-
-    _Resource_Node_extract( new_owner );
-    _Resource_Node_set_dependency( new_owner, NULL );
-    _Resource_Node_add_resource( new_owner, &mrsp->Resource );
-    _Resource_Set_owner( &mrsp->Resource, new_owner );
-    _MRSP_Set_root( new_owner, new_owner );
+    Thread_Control *new_owner = rival->thread;
+
+    _Resource_Node_extract( &new_owner->Resource_node );
+    _Resource_Node_set_dependency( &new_owner->Resource_node, NULL );
+    _Resource_Node_add_resource( &new_owner->Resource_node, &mrsp->Resource );
+    _Resource_Set_owner( &mrsp->Resource, &new_owner->Resource_node );
+    _Scheduler_Thread_change_help_state( new_owner, SCHEDULER_HELP_ACTIVE_OWNER );
+    _MRSP_Set_root( &new_owner->Resource_node, &new_owner->Resource_node );
     _MRSP_Add_state( rival, MRSP_RIVAL_STATE_NEW_OWNER );
   }
 
+  if ( !_Resource_Node_owns_resources( &executing->Resource_node ) ) {
+    _Scheduler_Thread_change_help_state( executing, SCHEDULER_HELP_YOURSELF );
+  }
+
   return MRSP_SUCCESSFUL;
 }
 
diff --git a/cpukit/score/include/rtems/score/scheduler.h b/cpukit/score/include/rtems/score/scheduler.h
index 831accb..bb30a8e 100644
--- a/cpukit/score/include/rtems/score/scheduler.h
+++ b/cpukit/score/include/rtems/score/scheduler.h
@@ -161,6 +161,75 @@ struct Scheduler_Control {
   uint32_t name;
 };
 
+#if defined(RTEMS_SMP)
+/**
+ * @brief State to indicate potential help for other threads.
+ *
+ * @dot
+ * digraph state {
+ *   y [label="HELP YOURSELF"];
+ *   ao [label="HELP ACTIVE OWNER"];
+ *   ar [label="HELP ACTIVE RIVAL"];
+ *
+ *   y -> ao [label="obtain"];
+ *   y -> ar [label="wait for obtain"];
+ *   ao -> y [label="last release"];
+ *   ao -> r [label="wait for obtain"];
+ *   ar -> r [label="timeout"];
+ *   ar -> ao [label="timeout"];
+ * }
+ * @enddot
+ */
+typedef enum {
+  /**
+   * @brief This scheduler node is solely used by the owner thread.
+   *
+   * This thread owns no resources using a helping protocol and thus does not
+   * take part in the scheduler helping protocol.  No help will be provided for
+   * other thread.
+   */
+  SCHEDULER_HELP_YOURSELF,
+
+  /**
+   * @brief This scheduler node is owned by a thread actively owning a resource.
+   *
+   * This scheduler node can be used to help out threads.
+   *
+   * In case this scheduler node changes its state from ready to scheduled and
+   * the thread executes using another node, then an idle thread will be
+   * provided as a user of this node to temporarily execute on behalf of the
+   * owner thread.  Thus lower priority threads are denied access to the
+   * processors of this scheduler instance.
+   *
+   * In case a thread actively owning a resource performs a blocking operation,
+   * then an idle thread will be used also in case this node is in the
+   * scheduled state.
+   */
+  SCHEDULER_HELP_ACTIVE_OWNER,
+
+  /**
+   * @brief This scheduler node is owned by a thread actively obtaining a
+   * resource currently owned by another thread.
+   *
+   * This scheduler node can be used to help out threads.
+   *
+   * The thread owning this node is ready and will give away its processor in
+   * case the thread owning the resource asks for help.
+   */
+  SCHEDULER_HELP_ACTIVE_RIVAL,
+
+  /**
+   * @brief This scheduler node is owned by a thread obtaining a
+   * resource currently owned by another thread.
+   *
+   * This scheduler node can be used to help out threads.
+   *
+   * The thread owning this node is blocked.
+   */
+  SCHEDULER_HELP_PASSIVE
+} Scheduler_Help_state;
+#endif
+
 /**
  * @brief Scheduler node for per-thread data.
  */
@@ -179,9 +248,36 @@ struct Scheduler_Node {
   Chain_Node Node;
 
   /**
+   * @brief The thread using this node.
+   */
+  Thread_Control *user;
+
+  /**
+   * @brief The help state of this node.
+   */
+  Scheduler_Help_state help_state;
+
+  /**
    * @brief The thread owning this node.
    */
   Thread_Control *owner;
+
+  /**
+   * @brief The idle thread claimed by this node in case the help state is
+   * SCHEDULER_HELP_ACTIVE_OWNER.
+   *
+   * Active owners will lend their own node to an idle thread in case they
+   * execute currently using another node or in case they perform a blocking
+   * operation.  This is necessary to ensure the priority ceiling protocols
+   * work across scheduler boundaries.
+   */
+  Thread_Control *idle;
+
+  /**
+   * @brief The thread accepting help by this node in case the help state is
+   * not SCHEDULER_HELP_YOURSELF.
+   */
+  Thread_Control *accepts_help;
 #endif
 };
 
diff --git a/cpukit/score/include/rtems/score/schedulerimpl.h b/cpukit/score/include/rtems/score/schedulerimpl.h
index 1a8b6b0..edb68b6 100644
--- a/cpukit/score/include/rtems/score/schedulerimpl.h
+++ b/cpukit/score/include/rtems/score/schedulerimpl.h
@@ -77,6 +77,15 @@ RTEMS_INLINE_ROUTINE const Scheduler_Control *_Scheduler_Get_by_CPU(
   return _Scheduler_Get_by_CPU_index( cpu_index );
 }
 
+#if defined(RTEMS_SMP)
+RTEMS_INLINE_ROUTINE Thread_Control *_Scheduler_Node_get_user(
+  const Scheduler_Node *node
+)
+{
+  return node->user;
+}
+#endif
+
 /**
  * The preferred method to add a new scheduler is to define the jump table
  * entries and add a case to the _Scheduler_Initialize routine.
@@ -658,7 +667,11 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Node_do_initialize(
 )
 {
 #if defined(RTEMS_SMP)
+  node->user = the_thread;
+  node->help_state = SCHEDULER_HELP_YOURSELF;
   node->owner = the_thread;
+  node->idle = NULL;
+  node->accepts_help = the_thread;
 #else
   (void) node;
   (void) the_thread;
@@ -672,6 +685,34 @@ RTEMS_INLINE_ROUTINE Thread_Control *_Scheduler_Node_get_owner(
 {
   return node->owner;
 }
+
+RTEMS_INLINE_ROUTINE Thread_Control *_Scheduler_Node_get_idle(
+  const Scheduler_Node *node
+)
+{
+  return node->idle;
+}
+
+/**
+ * @brief Changes the scheduler help state of a thread.
+ *
+ * @param[in] the_thread The thread.
+ * @param[in] new_help_state The new help state.
+ *
+ * @return The previous help state.
+ */
+RTEMS_INLINE_ROUTINE Scheduler_Help_state _Scheduler_Thread_change_help_state(
+  Thread_Control       *the_thread,
+  Scheduler_Help_state  new_help_state
+)
+{
+  Scheduler_Node *node = _Scheduler_Thread_get_node( the_thread );
+  Scheduler_Help_state previous_help_state = node->help_state;
+
+  node->help_state = new_help_state;
+
+  return previous_help_state;
+}
 #endif
 
 /** @} */
diff --git a/cpukit/score/include/rtems/score/schedulersmpimpl.h b/cpukit/score/include/rtems/score/schedulersmpimpl.h
index 3ec499b..b7d86a3 100644
--- a/cpukit/score/include/rtems/score/schedulersmpimpl.h
+++ b/cpukit/score/include/rtems/score/schedulersmpimpl.h
@@ -455,8 +455,8 @@ static inline void _Scheduler_SMP_Allocate_processor(
   Scheduler_SMP_Allocate_processor  allocate_processor
 )
 {
-  Thread_Control *scheduled_thread = _Scheduler_Node_get_owner( scheduled );
-  Thread_Control *victim_thread = _Scheduler_Node_get_owner( victim );
+  Thread_Control *scheduled_thread = _Scheduler_Node_get_user( scheduled );
+  Thread_Control *victim_thread = _Scheduler_Node_get_user( victim );
 
   _Scheduler_SMP_Node_change_state(
     _Scheduler_SMP_Node_downcast( scheduled ),



More information about the vc mailing list