[PATCH 14/30] score: Add scheduler node requests

Sebastian Huber sebastian.huber at embedded-brains.de
Mon Oct 31 08:51:45 UTC 2016


Add the ability to add/remove scheduler nodes to/from the set of
scheduler nodes available to the schedulers for a particular thread.

Update #2556.
---
 cpukit/score/include/rtems/score/schedulerimpl.h |  8 +++
 cpukit/score/include/rtems/score/schedulernode.h | 62 +++++++++++++++++++++++-
 cpukit/score/include/rtems/score/thread.h        | 15 ++++++
 cpukit/score/include/rtems/score/threadimpl.h    | 47 +++++++++++++++++-
 cpukit/score/src/threadinitialize.c              |  4 ++
 5 files changed, 133 insertions(+), 3 deletions(-)

diff --git a/cpukit/score/include/rtems/score/schedulerimpl.h b/cpukit/score/include/rtems/score/schedulerimpl.h
index 6d2f5a1..26da986 100644
--- a/cpukit/score/include/rtems/score/schedulerimpl.h
+++ b/cpukit/score/include/rtems/score/schedulerimpl.h
@@ -1471,6 +1471,14 @@ RTEMS_INLINE_ROUTINE Status_Control _Scheduler_Set(
     &the_thread->Scheduler.Wait_nodes,
     &new_scheduler_node->Thread.Wait_node
   );
+  _Chain_Extract_unprotected(
+    &old_scheduler_node->Thread.Scheduler_node.Chain
+  );
+  _Assert( _Chain_Is_empty( &the_thread->Scheduler.Scheduler_nodes ) );
+  _Chain_Initialize_one(
+    &the_thread->Scheduler.Scheduler_nodes,
+    &new_scheduler_node->Thread.Scheduler_node.Chain
+  );
 
   {
     const Scheduler_Control *old_scheduler;
diff --git a/cpukit/score/include/rtems/score/schedulernode.h b/cpukit/score/include/rtems/score/schedulernode.h
index 2397ba4..2e0c2af 100644
--- a/cpukit/score/include/rtems/score/schedulernode.h
+++ b/cpukit/score/include/rtems/score/schedulernode.h
@@ -95,10 +95,43 @@ typedef enum {
 } Scheduler_Help_state;
 #endif
 
+#if defined(RTEMS_SMP)
+/**
+ * @brief The scheduler node requests.
+ */
+typedef enum {
+  /**
+   * @brief The scheduler node is not on the list of pending requests.
+   */
+  SCHEDULER_NODE_REQUEST_NOT_PENDING,
+
+  /**
+   * @brief There is a pending scheduler node request to add this scheduler
+   * node to the Thread_Control::Scheduler::Scheduler_nodes chain.
+   */
+  SCHEDULER_NODE_REQUEST_ADD,
+
+  /**
+   * @brief There is a pending scheduler node request to remove this scheduler
+   * node from the Thread_Control::Scheduler::Scheduler_nodes chain.
+   */
+  SCHEDULER_NODE_REQUEST_REMOVE,
+
+  /**
+   * @brief The scheduler node is on the list of pending requests, but nothing
+   * should change.
+   */
+  SCHEDULER_NODE_REQUEST_NOTHING,
+
+} Scheduler_Node_request;
+#endif
+
+typedef struct Scheduler_Node Scheduler_Node;
+
 /**
  * @brief Scheduler node for per-thread data.
  */
-typedef struct Scheduler_Node {
+struct Scheduler_Node {
 #if defined(RTEMS_SMP)
   /**
    * @brief Chain node for usage in various scheduler data structures.
@@ -149,6 +182,28 @@ typedef struct Scheduler_Node {
      * Thread_Control::Scheduler::Wait_nodes.
      */
     Chain_Node Wait_node;
+
+    /**
+     * @brief Node to add this scheduler node to
+     * Thread_Control::Scheduler::Scheduler_nodes.
+     */
+    union {
+      /**
+       * @brief The node for Thread_Control::Scheduler::Scheduler_nodes.
+       */
+      Chain_Node Chain;
+    } Scheduler_node;
+
+    /**
+     * @brief Link to the next scheduler node in the
+     * Thread_Control::Scheduler::requests list.
+     */
+    Scheduler_Node *next_request;
+
+    /**
+     * @brief The current scheduler node request.
+     */
+    Scheduler_Node_request request;
   } Thread;
 #endif
 
@@ -198,7 +253,7 @@ typedef struct Scheduler_Node {
      */
     bool prepend_it;
   } Priority;
-} Scheduler_Node;
+};
 
 #if defined(RTEMS_SMP)
 /**
@@ -212,6 +267,9 @@ extern const size_t _Scheduler_Node_size;
 #if defined(RTEMS_SMP)
 #define SCHEDULER_NODE_OF_THREAD_WAIT_NODE( node ) \
   RTEMS_CONTAINER_OF( node, Scheduler_Node, Thread.Wait_node )
+
+#define SCHEDULER_NODE_OF_THREAD_SCHEDULER_NODE( node ) \
+  RTEMS_CONTAINER_OF( node, Scheduler_Node, Thread.Scheduler_node.Chain )
 #endif
 
 #ifdef __cplusplus
diff --git a/cpukit/score/include/rtems/score/thread.h b/cpukit/score/include/rtems/score/thread.h
index e9f3465..8595ed0 100644
--- a/cpukit/score/include/rtems/score/thread.h
+++ b/cpukit/score/include/rtems/score/thread.h
@@ -300,6 +300,21 @@ typedef struct {
    * This chain is protected by the thread wait lock.
    */
   Chain_Control Wait_nodes;
+
+  /**
+   * @brief Scheduler nodes immediately available to the schedulers for this
+   * thread.
+   *
+   * This chain is protected by the thread state lock.
+   */
+  Chain_Control Scheduler_nodes;
+
+  /**
+   * @brief List of pending scheduler node requests.
+   *
+   * This list is protected by the thread scheduler lock.
+   */
+  Scheduler_Node *requests;
 #endif
 
   /**
diff --git a/cpukit/score/include/rtems/score/threadimpl.h b/cpukit/score/include/rtems/score/threadimpl.h
index b7e1b87..6f2037f 100644
--- a/cpukit/score/include/rtems/score/threadimpl.h
+++ b/cpukit/score/include/rtems/score/threadimpl.h
@@ -1044,6 +1044,42 @@ RTEMS_INLINE_ROUTINE void _Thread_Scheduler_release_critical(
   _ISR_lock_Release( &the_thread->Scheduler.Lock, lock_context );
 }
 
+RTEMS_INLINE_ROUTINE void _Thread_Scheduler_add_request(
+  Thread_Control         *the_thread,
+  Scheduler_Node         *scheduler_node,
+  Scheduler_Node_request  request
+)
+{
+  ISR_lock_Context       lock_context;
+  Scheduler_Node_request current_request;
+
+  _Thread_Scheduler_acquire_critical( the_thread, &lock_context );
+
+  current_request = scheduler_node->Thread.request;
+
+  if ( current_request == SCHEDULER_NODE_REQUEST_NOT_PENDING ) {
+    _Assert(
+      request == SCHEDULER_NODE_REQUEST_ADD
+        || request == SCHEDULER_NODE_REQUEST_REMOVE
+    );
+    _Assert( scheduler_node->Thread.next_request == NULL );
+    scheduler_node->Thread.next_request = the_thread->Scheduler.requests;
+    the_thread->Scheduler.requests = scheduler_node;
+  } else if ( current_request != SCHEDULER_NODE_REQUEST_NOTHING ) {
+    _Assert(
+      ( current_request == SCHEDULER_NODE_REQUEST_ADD
+        && request == SCHEDULER_NODE_REQUEST_REMOVE )
+      || ( current_request == SCHEDULER_NODE_REQUEST_REMOVE
+        && request == SCHEDULER_NODE_REQUEST_ADD )
+    );
+    request = SCHEDULER_NODE_REQUEST_NOTHING;
+  }
+
+  scheduler_node->Thread.request = request;
+
+  _Thread_Scheduler_release_critical( the_thread, &lock_context );
+}
+
 RTEMS_INLINE_ROUTINE void _Thread_Scheduler_add_wait_node(
   Thread_Control *the_thread,
   Scheduler_Node *scheduler_node
@@ -1053,6 +1089,11 @@ RTEMS_INLINE_ROUTINE void _Thread_Scheduler_add_wait_node(
     &the_thread->Scheduler.Wait_nodes,
     &scheduler_node->Thread.Wait_node
   );
+  _Thread_Scheduler_add_request(
+    the_thread,
+    scheduler_node,
+    SCHEDULER_NODE_REQUEST_ADD
+  );
 }
 
 RTEMS_INLINE_ROUTINE void _Thread_Scheduler_remove_wait_node(
@@ -1060,8 +1101,12 @@ RTEMS_INLINE_ROUTINE void _Thread_Scheduler_remove_wait_node(
   Scheduler_Node *scheduler_node
 )
 {
-  (void) the_thread;
   _Chain_Extract_unprotected( &scheduler_node->Thread.Wait_node );
+  _Thread_Scheduler_add_request(
+    the_thread,
+    scheduler_node,
+    SCHEDULER_NODE_REQUEST_REMOVE
+  );
 }
 #endif
 
diff --git a/cpukit/score/src/threadinitialize.c b/cpukit/score/src/threadinitialize.c
index 62c3066..8fe1785 100644
--- a/cpukit/score/src/threadinitialize.c
+++ b/cpukit/score/src/threadinitialize.c
@@ -210,6 +210,10 @@ bool _Thread_Initialize(
     &the_thread->Scheduler.Wait_nodes,
     &scheduler_node->Thread.Wait_node
   );
+  _Chain_Initialize_one(
+    &the_thread->Scheduler.Scheduler_nodes,
+    &scheduler_node->Thread.Scheduler_node.Chain
+  );
 #else
   scheduler_node = _Thread_Scheduler_get_own_node( the_thread );
   _Scheduler_Node_initialize(
-- 
1.8.4.5




More information about the devel mailing list