summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2013-08-13 13:13:25 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2013-08-20 10:14:05 +0200
commit48c4a556a26279f887f4c66056695cb04a986a72 (patch)
treeea56a04c433405365d597818aa100249148670f8
parentsmp: Optimize Simple SMP scheduler (diff)
downloadrtems-48c4a556a26279f887f4c66056695cb04a986a72.tar.bz2
smp: Generalize Simple SMP scheduler
-rw-r--r--cpukit/score/include/rtems/score/schedulersmpimpl.h165
-rw-r--r--cpukit/score/src/schedulersimplesmp.c160
2 files changed, 240 insertions, 85 deletions
diff --git a/cpukit/score/include/rtems/score/schedulersmpimpl.h b/cpukit/score/include/rtems/score/schedulersmpimpl.h
index 40e94cbdb4..34478623ae 100644
--- a/cpukit/score/include/rtems/score/schedulersmpimpl.h
+++ b/cpukit/score/include/rtems/score/schedulersmpimpl.h
@@ -24,6 +24,8 @@
#define _RTEMS_SCORE_SCHEDULERSMPIMPL_H
#include <rtems/score/schedulersmp.h>
+#include <rtems/score/schedulersimpleimpl.h>
+#include <rtems/score/chainimpl.h>
#include <rtems/score/scheduler.h>
#ifdef __cplusplus
@@ -36,6 +38,25 @@ extern "C" {
* @{
*/
+typedef Thread_Control *( *Scheduler_SMP_Get_highest_ready )(
+ Scheduler_SMP_Control *self
+);
+
+typedef void ( *Scheduler_SMP_Extract )(
+ Scheduler_SMP_Control *self,
+ Thread_Control *thread
+);
+
+typedef void ( *Scheduler_SMP_Insert )(
+ Scheduler_SMP_Control *self,
+ Thread_Control *thread_to_insert
+);
+
+typedef void ( *Scheduler_SMP_Move )(
+ Scheduler_SMP_Control *self,
+ Thread_Control *thread_to_move
+);
+
static inline Scheduler_SMP_Control *_Scheduler_SMP_Instance( void )
{
return _Scheduler.information;
@@ -97,6 +118,150 @@ static inline Thread_Control *_Scheduler_SMP_Get_lowest_scheduled(
return lowest_ready;
}
+static inline void _Scheduler_SMP_Enqueue_ordered(
+ Scheduler_SMP_Control *self,
+ 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_Move move_from_scheduled_to_ready
+)
+{
+ if ( thread->is_in_the_air ) {
+ Thread_Control *highest_ready = ( *get_highest_ready )( self );
+
+ thread->is_in_the_air = false;
+
+ /*
+ * The thread has been extracted from the scheduled chain. We have to
+ * place it now on the scheduled or ready chain.
+ *
+ * NOTE: Do not exchange parameters to do the negation of the order check.
+ */
+ if (
+ highest_ready != NULL
+ && !( *order )( &thread->Object.Node, &highest_ready->Object.Node )
+ ) {
+ _Scheduler_SMP_Allocate_processor( highest_ready, thread );
+
+ ( *insert_ready )( self, thread );
+ ( *move_from_ready_to_scheduled )( self, highest_ready );
+ } else {
+ thread->is_scheduled = true;
+
+ ( *insert_scheduled )( self, thread );
+ }
+ } else {
+ Thread_Control *lowest_scheduled = _Scheduler_SMP_Get_lowest_scheduled( self );
+
+ /*
+ * The scheduled chain is empty if nested interrupts change the priority of
+ * all scheduled threads. These threads are in the air.
+ */
+ if (
+ lowest_scheduled != NULL
+ && ( *order )( &thread->Object.Node, &lowest_scheduled->Object.Node )
+ ) {
+ _Scheduler_SMP_Allocate_processor( thread, lowest_scheduled );
+
+ ( *insert_scheduled )( self, thread );
+ ( *move_from_scheduled_to_ready )( self, lowest_scheduled );
+ } else {
+ ( *insert_ready )( self, thread );
+ }
+ }
+}
+
+static inline void _Scheduler_SMP_Schedule_highest_ready(
+ Scheduler_SMP_Control *self,
+ Thread_Control *victim,
+ Scheduler_SMP_Get_highest_ready get_highest_ready,
+ Scheduler_SMP_Move move_from_ready_to_scheduled
+)
+{
+ Thread_Control *highest_ready = ( *get_highest_ready )( self );
+
+ _Scheduler_SMP_Allocate_processor( highest_ready, victim );
+
+ ( *move_from_ready_to_scheduled )( self, highest_ready );
+}
+
+static inline void _Scheduler_SMP_Block(
+ Scheduler_SMP_Control *self,
+ Thread_Control *thread,
+ Scheduler_SMP_Extract extract,
+ Scheduler_SMP_Get_highest_ready get_highest_ready,
+ Scheduler_SMP_Move move_from_ready_to_scheduled
+)
+{
+ ( *extract )( self, thread );
+
+ if ( thread->is_in_the_air ) {
+ thread->is_in_the_air = false;
+
+ _Scheduler_SMP_Schedule_highest_ready(
+ self,
+ thread,
+ get_highest_ready,
+ move_from_ready_to_scheduled
+ );
+ }
+}
+
+static inline void _Scheduler_SMP_Extract(
+ Scheduler_SMP_Control *self,
+ Thread_Control *thread,
+ Scheduler_SMP_Extract extract
+)
+{
+ ( *extract )( self, thread );
+}
+
+static inline void _Scheduler_SMP_Schedule(
+ Scheduler_SMP_Control *self,
+ Thread_Control *thread,
+ Scheduler_SMP_Get_highest_ready get_highest_ready,
+ Scheduler_SMP_Move move_from_ready_to_scheduled
+)
+{
+ if ( thread->is_in_the_air ) {
+ thread->is_in_the_air = false;
+
+ _Scheduler_SMP_Schedule_highest_ready(
+ self,
+ thread,
+ get_highest_ready,
+ move_from_ready_to_scheduled
+ );
+ }
+}
+
+static inline void _Scheduler_SMP_Insert_scheduled_lifo(
+ Scheduler_SMP_Control *self,
+ Thread_Control *thread
+)
+{
+ _Chain_Insert_ordered_unprotected(
+ &self->scheduled,
+ &thread->Object.Node,
+ _Scheduler_simple_Insert_priority_lifo_order
+ );
+}
+
+static inline void _Scheduler_SMP_Insert_scheduled_fifo(
+ Scheduler_SMP_Control *self,
+ Thread_Control *thread
+)
+{
+ _Chain_Insert_ordered_unprotected(
+ &self->scheduled,
+ &thread->Object.Node,
+ _Scheduler_simple_Insert_priority_fifo_order
+ );
+}
+
/** @} */
#ifdef __cplusplus
diff --git a/cpukit/score/src/schedulersimplesmp.c b/cpukit/score/src/schedulersimplesmp.c
index a46f58e673..0aa26170cf 100644
--- a/cpukit/score/src/schedulersimplesmp.c
+++ b/cpukit/score/src/schedulersimplesmp.c
@@ -19,7 +19,6 @@
#endif
#include <rtems/score/schedulersimplesmp.h>
-#include <rtems/score/schedulersimpleimpl.h>
#include <rtems/score/schedulersmpimpl.h>
#include <rtems/score/wkspace.h>
@@ -72,121 +71,111 @@ static void _Scheduler_simple_smp_Move_from_ready_to_scheduled(
);
}
-static void _Scheduler_simple_smp_Insert(
- Chain_Control *chain,
- Thread_Control *thread,
- Chain_Node_order order
+static void _Scheduler_simple_smp_Insert_ready_lifo(
+ Scheduler_SMP_Control *self,
+ Thread_Control *thread
)
{
- _Chain_Insert_ordered_unprotected( chain, &thread->Object.Node, order );
+ _Chain_Insert_ordered_unprotected(
+ &self->ready[ 0 ],
+ &thread->Object.Node,
+ _Scheduler_simple_Insert_priority_lifo_order
+ );
}
-static void _Scheduler_simple_smp_Schedule_highest_ready(
+static void _Scheduler_simple_smp_Insert_ready_fifo(
Scheduler_SMP_Control *self,
- Thread_Control *victim
+ Thread_Control *thread
)
{
- Thread_Control *highest_ready =
- (Thread_Control *) _Chain_First( &self->ready[ 0 ] );
-
- _Scheduler_SMP_Allocate_processor( highest_ready, victim );
-
- _Scheduler_simple_smp_Move_from_ready_to_scheduled( self, highest_ready );
+ _Chain_Insert_ordered_unprotected(
+ &self->ready[ 0 ],
+ &thread->Object.Node,
+ _Scheduler_simple_Insert_priority_fifo_order
+ );
}
-static void _Scheduler_simple_smp_Enqueue_ordered(
- Thread_Control *thread,
- Chain_Node_order order
+static void _Scheduler_simple_smp_Do_extract(
+ Scheduler_SMP_Control *self,
+ Thread_Control *thread
)
{
- Scheduler_SMP_Control *self = _Scheduler_SMP_Instance();
+ ( void ) self;
- if ( thread->is_in_the_air ) {
- Thread_Control *highest_ready =
- _Scheduler_simple_smp_Get_highest_ready( self );
-
- thread->is_in_the_air = false;
-
- /*
- * The thread has been extracted from the scheduled chain. We have to
- * place it now on the scheduled or ready chain.
- *
- * NOTE: Do not exchange parameters to do the negation of the order check.
- */
- if (
- highest_ready != NULL
- && !( *order )( &thread->Object.Node, &highest_ready->Object.Node )
- ) {
- _Scheduler_SMP_Allocate_processor( highest_ready, thread );
-
- _Scheduler_simple_smp_Insert( &self->ready[ 0 ], thread, order );
-
- _Scheduler_simple_smp_Move_from_ready_to_scheduled(
- self,
- highest_ready
- );
- } else {
- thread->is_scheduled = true;
-
- _Scheduler_simple_smp_Insert( &self->scheduled, thread, order );
- }
- } else {
- Thread_Control *lowest_scheduled = _Scheduler_SMP_Get_lowest_scheduled( self );
-
- /*
- * The scheduled chain is empty if nested interrupts change the priority of
- * all scheduled threads. These threads are in the air.
- */
- if (
- lowest_scheduled != NULL
- && ( *order )( &thread->Object.Node, &lowest_scheduled->Object.Node )
- ) {
- _Scheduler_SMP_Allocate_processor( thread, lowest_scheduled );
-
- _Scheduler_simple_smp_Insert( &self->scheduled, thread, order );
-
- _Scheduler_simple_smp_Move_from_scheduled_to_ready(
- self,
- lowest_scheduled
- );
- } else {
- _Scheduler_simple_smp_Insert( &self->ready[ 0 ], thread, order );
- }
- }
+ thread->is_in_the_air = thread->is_scheduled;
+ thread->is_scheduled = false;
+
+ _Chain_Extract_unprotected( &thread->Object.Node );
}
void _Scheduler_simple_smp_Block( Thread_Control *thread )
{
- _Chain_Extract_unprotected( &thread->Object.Node );
+ Scheduler_SMP_Control *self = _Scheduler_SMP_Instance();
- if ( thread->is_scheduled ) {
- Scheduler_SMP_Control *self = _Scheduler_SMP_Instance();
+ _Scheduler_SMP_Block(
+ self,
+ thread,
+ _Scheduler_simple_smp_Do_extract,
+ _Scheduler_simple_smp_Get_highest_ready,
+ _Scheduler_simple_smp_Move_from_ready_to_scheduled
+ );
+}
- _Scheduler_simple_smp_Schedule_highest_ready( self, thread );
- }
+static void _Scheduler_simple_smp_Enqueue_ordered(
+ Scheduler_SMP_Control *self,
+ Thread_Control *thread,
+ Chain_Node_order order,
+ Scheduler_SMP_Insert insert_ready,
+ Scheduler_SMP_Insert insert_scheduled
+)
+{
+ _Scheduler_SMP_Enqueue_ordered(
+ self,
+ thread,
+ order,
+ _Scheduler_simple_smp_Get_highest_ready,
+ insert_ready,
+ insert_scheduled,
+ _Scheduler_simple_smp_Move_from_ready_to_scheduled,
+ _Scheduler_simple_smp_Move_from_scheduled_to_ready
+ );
}
void _Scheduler_simple_smp_Enqueue_priority_lifo( Thread_Control *thread )
{
+ Scheduler_SMP_Control *self = _Scheduler_SMP_Instance();
+
_Scheduler_simple_smp_Enqueue_ordered(
+ self,
thread,
- _Scheduler_simple_Insert_priority_lifo_order
+ _Scheduler_simple_Insert_priority_lifo_order,
+ _Scheduler_simple_smp_Insert_ready_lifo,
+ _Scheduler_SMP_Insert_scheduled_lifo
);
}
void _Scheduler_simple_smp_Enqueue_priority_fifo( Thread_Control *thread )
{
+ Scheduler_SMP_Control *self = _Scheduler_SMP_Instance();
+
_Scheduler_simple_smp_Enqueue_ordered(
+ self,
thread,
- _Scheduler_simple_Insert_priority_fifo_order
+ _Scheduler_simple_Insert_priority_fifo_order,
+ _Scheduler_simple_smp_Insert_ready_fifo,
+ _Scheduler_SMP_Insert_scheduled_fifo
);
}
void _Scheduler_simple_smp_Extract( Thread_Control *thread )
{
- thread->is_in_the_air = true;
+ Scheduler_SMP_Control *self = _Scheduler_SMP_Instance();
- _Chain_Extract_unprotected( &thread->Object.Node );
+ _Scheduler_SMP_Extract(
+ self,
+ thread,
+ _Scheduler_simple_smp_Do_extract
+ );
}
void _Scheduler_simple_smp_Yield( Thread_Control *thread )
@@ -203,11 +192,12 @@ void _Scheduler_simple_smp_Yield( Thread_Control *thread )
void _Scheduler_simple_smp_Schedule( Thread_Control *thread )
{
- if ( thread->is_in_the_air ) {
- Scheduler_SMP_Control *self = _Scheduler_SMP_Instance();
-
- thread->is_in_the_air = false;
+ Scheduler_SMP_Control *self = _Scheduler_SMP_Instance();
- _Scheduler_simple_smp_Schedule_highest_ready( self, thread );
- }
+ _Scheduler_SMP_Schedule(
+ self,
+ thread,
+ _Scheduler_simple_smp_Get_highest_ready,
+ _Scheduler_simple_smp_Move_from_ready_to_scheduled
+ );
}