summaryrefslogtreecommitdiffstats
path: root/cpukit/score/include/rtems
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@oarcorp.com>2014-05-19 15:26:55 -0500
committerJennifer Averett <jennifer.averett@oarcorp.com>2014-06-11 09:27:06 -0500
commit238629f2f144807abd29e9fefc9d20746ae16b2c (patch)
treeb156738a4f3764a717288c3b7546bfbcaf4ee749 /cpukit/score/include/rtems
parentsamples/pppd: Fix extra drivers initializer (diff)
downloadrtems-238629f2f144807abd29e9fefc9d20746ae16b2c.tar.bz2
Add SMP Priority Scheduler with Affinity
This scheduler attempts to account for needed thread migrations caused as a side-effect of a thread state, affinity, or priority change operation. This scheduler has its own allocate_processor handler named _Scheduler_SMP_Allocate_processor_exact() because _Scheduler_SMP_Allocate_processor() attempts to prevent an executing thread from moving off its current CPU without considering affinity. Without this, the scheduler makes all the right decisions and then they are discarded at the end. ==Side Effects of Adding This Scheduler== Added Thread_Control * parameter to Scheduler_SMP_Get_highest_ready type so methods looking for the highest ready thread can filter by the processor on which the thread blocking resides. This allows affinity to be considered. Simple Priority SMP and Priority SMP ignore this parameter. + Added get_lowest_scheduled argument to _Scheduler_SMP_Enqueue_ordered(). + Added allocate_processor argument to the following methods: - _Scheduler_SMP_Block() - _Scheduler_SMP_Enqueue_scheduled_ordered() - _Scheduler_SMP_Enqueue_scheduled_ordered() + schedulerprioritysmpimpl.h is a new file with prototypes for methods which were formerly static in schedulerprioritysmp.c but now need to be public to be shared with this scheduler. NOTE: _Scheduler_SMP_Get_lowest_ready() appears to have a path which would allow it to return a NULL. Previously, _Scheduler_SMP_Enqueue_ordered() would have asserted on it. If it cannot return a NULL, _Scheduler_SMP_Get_lowest_ready() should have an assertions.
Diffstat (limited to 'cpukit/score/include/rtems')
-rw-r--r--cpukit/score/include/rtems/score/schedulerpriorityaffinitysmp.h68
-rw-r--r--cpukit/score/include/rtems/score/schedulerprioritysmpimpl.h84
-rw-r--r--cpukit/score/include/rtems/score/schedulersmpimpl.h113
3 files changed, 220 insertions, 45 deletions
diff --git a/cpukit/score/include/rtems/score/schedulerpriorityaffinitysmp.h b/cpukit/score/include/rtems/score/schedulerpriorityaffinitysmp.h
index 0ba8191e44..831d1d47a6 100644
--- a/cpukit/score/include/rtems/score/schedulerpriorityaffinitysmp.h
+++ b/cpukit/score/include/rtems/score/schedulerpriorityaffinitysmp.h
@@ -52,9 +52,9 @@ extern "C" {
_Scheduler_priority_SMP_Initialize, \
_Scheduler_default_Schedule, \
_Scheduler_priority_SMP_Yield, \
- _Scheduler_priority_SMP_Block, \
- _Scheduler_priority_SMP_Unblock, \
- _Scheduler_priority_SMP_Change_priority, \
+ _Scheduler_priority_affinity_SMP_Block, \
+ _Scheduler_priority_affinity_SMP_Unblock, \
+ _Scheduler_priority_affinity_SMP_Change_priority, \
_Scheduler_priority_affinity_SMP_Node_initialize, \
_Scheduler_default_Node_destroy, \
_Scheduler_priority_SMP_Update_priority, \
@@ -67,21 +67,47 @@ extern "C" {
}
/**
- * @brief Allocates @a the_thread->scheduler.
+ * @brief Initializes per thread scheduler information
*
- * This routine allocates @a the_thread->scheduler.
+ * This routine allocates @a thread->scheduler.
*
* @param[in] scheduler points to the scheduler specific information.
- * @param[in] the_thread is the thread the scheduler is allocating
+ * @param[in] thread is the thread the scheduler is allocating
* management memory for.
*/
void _Scheduler_priority_affinity_SMP_Node_initialize(
const Scheduler_Control *scheduler,
- Thread_Control *the_thread
+ Thread_Control *thread
);
/**
- * @brief Get affinity for the priority affinity smp scheduler.
+ * @brief SMP Priority Affinity Scheduler Block Operation
+ *
+ * This method is the block operation for this scheduler.
+ *
+ * @param[in] scheduler is the scheduler instance information
+ * @param[in] thread is the thread to block
+ */
+void _Scheduler_priority_affinity_SMP_Block(
+ const Scheduler_Control *scheduler,
+ Thread_Control *thread
+);
+
+/**
+ * @brief SMP Priority Affinity Scheduler Unblock Operation
+ *
+ * This method is the unblock operation for this scheduler.
+ *
+ * @param[in] scheduler is the scheduler instance information
+ * @param[in] thread is the thread to unblock
+ */
+void _Scheduler_priority_affinity_SMP_Unblock(
+ const Scheduler_Control *scheduler,
+ Thread_Control *thread
+);
+
+/**
+ * @brief Get affinity for the priority affinity SMP scheduler.
*
* @param[in] scheduler The scheduler of the thread.
* @param[in] thread The associated thread.
@@ -98,26 +124,44 @@ bool _Scheduler_priority_affinity_SMP_Get_affinity(
cpu_set_t *cpuset
);
+/**
+ * @brief Change priority for the priority affinity SMP scheduler.
+ *
+ * @param[in] scheduler The scheduler of the thread.
+ * @param[in] thread The associated thread.
+ * @param[in] new_priority The new priority for the thread.
+ * @param[in] prepend_it Append or prepend the thread to its priority FIFO.
+ */
+void _Scheduler_priority_affinity_SMP_Change_priority(
+ const Scheduler_Control *scheduler,
+ Thread_Control *the_thread,
+ Priority_Control new_priority,
+ bool prepend_it
+);
+
/**
- * @brief Set affinity for the priority affinity smp scheduler.
+ * @brief Set affinity for the priority affinity SMP scheduler.
*
* @param[in] scheduler The scheduler of the thread.
* @param[in] thread The associated thread.
* @param[in] cpusetsize The size of the cpuset.
* @param[in] cpuset Affinity new affinity set.
*
- * @retval 0 Successful
+ * @retval true if successful
+ * @retval false if unsuccessful
*/
bool _Scheduler_priority_affinity_SMP_Set_affinity(
const Scheduler_Control *scheduler,
Thread_Control *thread,
size_t cpusetsize,
- cpu_set_t *cpuset
+ const cpu_set_t *cpuset
);
/**
* @brief Scheduler node specialization for Deterministic Priority Affinity SMP
* schedulers.
+ *
+ * This is a per thread structure.
*/
typedef struct {
/**
@@ -137,4 +181,4 @@ typedef struct {
}
#endif /* __cplusplus */
-#endif /* _RTEMS_SCORE_SCHEDULERPRIORITYSMP_H */
+#endif /* _RTEMS_SCORE_SCHEDULERPRIORITYAFFINITYSMP_H */
diff --git a/cpukit/score/include/rtems/score/schedulerprioritysmpimpl.h b/cpukit/score/include/rtems/score/schedulerprioritysmpimpl.h
new file mode 100644
index 0000000000..2d8d1a5aed
--- /dev/null
+++ b/cpukit/score/include/rtems/score/schedulerprioritysmpimpl.h
@@ -0,0 +1,84 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreSchedulerPrioritySMP
+ *
+ * @brief Deterministic Priority SMP Scheduler API
+ */
+
+/*
+ * Copyright (c) 2013-2014 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Dornierstr. 4
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#ifndef _RTEMS_SCORE_SCHEDULERPRIORITYSMPIMPL_H
+#define _RTEMS_SCORE_SCHEDULERPRIORITYSMPIMPL_H
+
+#include <rtems/score/scheduler.h>
+#include <rtems/score/schedulerpriority.h>
+#include <rtems/score/schedulersmp.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @ingroup ScoreSchedulerPrioritySMP
+ * @{
+ */
+
+Scheduler_priority_SMP_Context *_Scheduler_priority_SMP_Get_self(
+ Scheduler_Context *context
+);
+
+Scheduler_priority_SMP_Node *_Scheduler_priority_SMP_Node_get(
+ Thread_Control *thread
+);
+
+void _Scheduler_priority_SMP_Insert_ready_fifo(
+ Scheduler_Context *context,
+ Thread_Control *thread
+);
+
+void _Scheduler_priority_SMP_Insert_ready_lifo(
+ Scheduler_Context *context,
+ Thread_Control *thread
+);
+
+void _Scheduler_priority_SMP_Move_from_scheduled_to_ready(
+ Scheduler_Context *context,
+ Thread_Control *scheduled_to_ready
+);
+
+void _Scheduler_priority_SMP_Move_from_ready_to_scheduled(
+ Scheduler_Context *context,
+ Thread_Control *ready_to_scheduled
+);
+
+void _Scheduler_priority_SMP_Extract_from_ready(
+ Scheduler_Context *context,
+ Thread_Control *thread
+);
+
+void _Scheduler_priority_SMP_Do_update(
+ Scheduler_Context *context,
+ Scheduler_Node *base_node,
+ Priority_Control new_priority
+);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _RTEMS_SCORE_SCHEDULERPRIORITYSMPIMPL_H */
diff --git a/cpukit/score/include/rtems/score/schedulersmpimpl.h b/cpukit/score/include/rtems/score/schedulersmpimpl.h
index bb7c41e8c0..c3b0ab3864 100644
--- a/cpukit/score/include/rtems/score/schedulersmpimpl.h
+++ b/cpukit/score/include/rtems/score/schedulersmpimpl.h
@@ -275,7 +275,14 @@ extern "C" {
*/
typedef Thread_Control *( *Scheduler_SMP_Get_highest_ready )(
- Scheduler_Context *context
+ Scheduler_Context *context,
+ Thread_Control *blocking
+);
+
+typedef Thread_Control *( *Scheduler_SMP_Get_lowest_scheduled )(
+ Scheduler_Context *context,
+ Thread_Control *thread,
+ Chain_Node_order order
);
typedef void ( *Scheduler_SMP_Extract )(
@@ -304,6 +311,12 @@ typedef void ( *Scheduler_SMP_Enqueue )(
Thread_Control *thread_to_enqueue
);
+typedef void ( *Scheduler_SMP_Allocate_processor )(
+ Scheduler_SMP_Context *self,
+ Thread_Control *scheduled,
+ Thread_Control *victim
+);
+
static inline Scheduler_SMP_Context *_Scheduler_SMP_Get_self(
Scheduler_Context *context
)
@@ -382,7 +395,7 @@ static inline void _Scheduler_SMP_Update_heir(
}
}
-static inline void _Scheduler_SMP_Allocate_processor(
+static void _Scheduler_SMP_Allocate_processor(
Scheduler_SMP_Context *self,
Thread_Control *scheduled,
Thread_Control *victim
@@ -420,10 +433,13 @@ static inline void _Scheduler_SMP_Allocate_processor(
}
}
-static inline Thread_Control *_Scheduler_SMP_Get_lowest_scheduled(
- Scheduler_SMP_Context *self
+static Thread_Control *_Scheduler_SMP_Get_lowest_scheduled(
+ Scheduler_Context *context,
+ Thread_Control *filter,
+ Chain_Node_order order
)
{
+ Scheduler_SMP_Context *self = _Scheduler_SMP_Get_self( context );
Thread_Control *lowest_ready = NULL;
Chain_Control *scheduled = &self->Scheduled;
@@ -431,6 +447,12 @@ static inline Thread_Control *_Scheduler_SMP_Get_lowest_scheduled(
lowest_ready = (Thread_Control *) _Chain_Last( scheduled );
}
+ /*
+ * _Scheduler_SMP_Enqueue_ordered() assumes that get_lowest_scheduled
+ * helpers may return NULL. But this method never should.
+ */
+ _Assert( lowest_ready != NULL );
+
return lowest_ready;
}
@@ -443,28 +465,45 @@ static inline Thread_Control *_Scheduler_SMP_Get_lowest_scheduled(
* @param[in] thread The thread to enqueue.
* @param[in] order The order function.
* @param[in] insert_ready Function to insert a node into the set of ready
- * nodes.
+ * nodes.
* @param[in] insert_scheduled Function to insert a node into the set of
- * scheduled nodes.
+ * scheduled nodes.
* @param[in] move_from_scheduled_to_ready Function to move a node from the set
- * of scheduled nodes to the set of ready nodes.
+ * of scheduled nodes to the set of ready nodes.
+ * @param[in] get_lowest_scheduled Function to select the thread from the
+ * scheduled nodes to replace. It may not be possible to find one.
+ * @param[in] allocate_processor Function to allocate a processor to a thread
+ * based on the rules of the scheduler.
*/
static inline void _Scheduler_SMP_Enqueue_ordered(
- Scheduler_Context *context,
- Thread_Control *thread,
- Chain_Node_order order,
- Scheduler_SMP_Insert insert_ready,
- Scheduler_SMP_Insert insert_scheduled,
- Scheduler_SMP_Move move_from_scheduled_to_ready
+ Scheduler_Context *context,
+ Thread_Control *thread,
+ Chain_Node_order order,
+ Scheduler_SMP_Insert insert_ready,
+ Scheduler_SMP_Insert insert_scheduled,
+ Scheduler_SMP_Move move_from_scheduled_to_ready,
+ Scheduler_SMP_Get_lowest_scheduled get_lowest_scheduled,
+ Scheduler_SMP_Allocate_processor allocate_processor
)
{
Scheduler_SMP_Context *self = _Scheduler_SMP_Get_self( context );
Thread_Control *lowest_scheduled =
- _Scheduler_SMP_Get_lowest_scheduled( self );
+ ( *get_lowest_scheduled )( context, thread, order );
- _Assert( lowest_scheduled != NULL );
+ /*
+ * get_lowest_scheduled can return a NULL if no scheduled threads
+ * should be removed from their processor based on the selection
+ * criteria. For example, this can occur when the affinity of the
+ * thread being enqueued schedules it against higher priority threads.
+ * A low priority thread with affinity can only consider the threads
+ * which are on the cores if has affinity for.
+ *
+ * The get_lowest_scheduled helper should assert on not returning NULL
+ * if that is not possible for that scheduler.
+ */
- if ( ( *order )( &thread->Object.Node, &lowest_scheduled->Object.Node ) ) {
+ if ( lowest_scheduled &&
+ ( *order )( &thread->Object.Node, &lowest_scheduled->Object.Node ) ) {
Scheduler_SMP_Node *lowest_scheduled_node =
_Scheduler_SMP_Node_get( lowest_scheduled );
@@ -472,7 +511,7 @@ static inline void _Scheduler_SMP_Enqueue_ordered(
lowest_scheduled_node,
SCHEDULER_SMP_NODE_READY
);
- _Scheduler_SMP_Allocate_processor( self, thread, lowest_scheduled );
+ ( *allocate_processor )( self, thread, lowest_scheduled );
( *insert_scheduled )( &self->Base, thread );
( *move_from_scheduled_to_ready )( &self->Base, lowest_scheduled );
} else {
@@ -489,25 +528,29 @@ static inline void _Scheduler_SMP_Enqueue_ordered(
* @param[in] order The order function.
* @param[in] get_highest_ready Function to get the highest ready node.
* @param[in] insert_ready Function to insert a node into the set of ready
- * nodes.
+ * nodes.
* @param[in] insert_scheduled Function to insert a node into the set of
- * scheduled nodes.
+ * scheduled nodes.
* @param[in] move_from_ready_to_scheduled Function to move a node from the set
- * of ready nodes to the set of scheduled nodes.
+ * of ready nodes to the set of scheduled nodes.
+ * @param[in] allocate_processor Function to allocate a processor to a thread
+ * based on the rules of the scheduler.
*/
static inline void _Scheduler_SMP_Enqueue_scheduled_ordered(
Scheduler_Context *context,
- Thread_Control *thread,
- Chain_Node_order order,
- Scheduler_SMP_Get_highest_ready get_highest_ready,
- Scheduler_SMP_Insert insert_ready,
- Scheduler_SMP_Insert insert_scheduled,
- Scheduler_SMP_Move move_from_ready_to_scheduled
+ Thread_Control *thread,
+ Chain_Node_order order,
+ Scheduler_SMP_Get_highest_ready get_highest_ready,
+ Scheduler_SMP_Insert insert_ready,
+ Scheduler_SMP_Insert insert_scheduled,
+ Scheduler_SMP_Move move_from_ready_to_scheduled,
+ Scheduler_SMP_Allocate_processor allocate_processor
)
{
Scheduler_SMP_Context *self = _Scheduler_SMP_Get_self( context );
Scheduler_SMP_Node *node = _Scheduler_SMP_Node_get( thread );
- Thread_Control *highest_ready = ( *get_highest_ready )( &self->Base );
+ Thread_Control *highest_ready =
+ ( *get_highest_ready )( &self->Base, thread );
_Assert( highest_ready != NULL );
@@ -519,7 +562,7 @@ static inline void _Scheduler_SMP_Enqueue_scheduled_ordered(
( *insert_scheduled )( &self->Base, thread );
} else {
_Scheduler_SMP_Node_change_state( node, SCHEDULER_SMP_NODE_READY );
- _Scheduler_SMP_Allocate_processor( self, highest_ready, thread );
+ ( *allocate_processor) ( self, highest_ready, thread );
( *insert_ready )( &self->Base, thread );
( *move_from_ready_to_scheduled )( &self->Base, highest_ready );
}
@@ -536,13 +579,15 @@ static inline void _Scheduler_SMP_Schedule_highest_ready(
Scheduler_Context *context,
Thread_Control *victim,
Scheduler_SMP_Get_highest_ready get_highest_ready,
- Scheduler_SMP_Move move_from_ready_to_scheduled
+ Scheduler_SMP_Move move_from_ready_to_scheduled,
+ Scheduler_SMP_Allocate_processor allocate_processor
)
{
Scheduler_SMP_Context *self = _Scheduler_SMP_Get_self( context );
- Thread_Control *highest_ready = ( *get_highest_ready )( &self->Base );
+ Thread_Control *highest_ready =
+ ( *get_highest_ready )( &self->Base, victim );
- _Scheduler_SMP_Allocate_processor( self, highest_ready, victim );
+ ( *allocate_processor )( self, highest_ready, victim );
( *move_from_ready_to_scheduled )( &self->Base, highest_ready );
}
@@ -563,7 +608,8 @@ static inline void _Scheduler_SMP_Block(
Thread_Control *thread,
Scheduler_SMP_Extract extract_from_ready,
Scheduler_SMP_Get_highest_ready get_highest_ready,
- Scheduler_SMP_Move move_from_ready_to_scheduled
+ Scheduler_SMP_Move move_from_ready_to_scheduled,
+ Scheduler_SMP_Allocate_processor allocate_processor
)
{
Scheduler_SMP_Node *node = _Scheduler_SMP_Node_get( thread );
@@ -578,7 +624,8 @@ static inline void _Scheduler_SMP_Block(
context,
thread,
get_highest_ready,
- move_from_ready_to_scheduled
+ move_from_ready_to_scheduled,
+ allocate_processor
);
} else {
( *extract_from_ready )( context, thread );