summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2016-09-23 13:24:06 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2016-11-02 10:05:42 +0100
commitebdd2a343181ef5f3fc2f1330930b0ea5c0ed8a4 (patch)
treed3d50b10d232eb7e1ccc743b07b8f7ab1d195660
parentscore: Protect thread CPU by thread scheduler lock (diff)
downloadrtems-ebdd2a343181ef5f3fc2f1330930b0ea5c0ed8a4.tar.bz2
score: Add scheduler node requests
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.
-rw-r--r--cpukit/score/include/rtems/score/schedulerimpl.h8
-rw-r--r--cpukit/score/include/rtems/score/schedulernode.h62
-rw-r--r--cpukit/score/include/rtems/score/thread.h15
-rw-r--r--cpukit/score/include/rtems/score/threadimpl.h47
-rw-r--r--cpukit/score/src/threadinitialize.c4
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 6d2f5a1981..26da986c4f 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 2397ba4b79..2e0c2afb88 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 eb272e6c01..236eaed064 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 8254b97183..eadcb10198 100644
--- a/cpukit/score/include/rtems/score/threadimpl.h
+++ b/cpukit/score/include/rtems/score/threadimpl.h
@@ -1051,6 +1051,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
@@ -1060,6 +1096,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(
@@ -1067,8 +1108,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 62c3066aab..8fe1785cf5 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(