diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2013-08-13 13:13:25 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2013-08-20 10:14:05 +0200 |
commit | 48c4a556a26279f887f4c66056695cb04a986a72 (patch) | |
tree | ea56a04c433405365d597818aa100249148670f8 /cpukit/score | |
parent | smp: Optimize Simple SMP scheduler (diff) | |
download | rtems-48c4a556a26279f887f4c66056695cb04a986a72.tar.bz2 |
smp: Generalize Simple SMP scheduler
Diffstat (limited to 'cpukit/score')
-rw-r--r-- | cpukit/score/include/rtems/score/schedulersmpimpl.h | 165 | ||||
-rw-r--r-- | cpukit/score/src/schedulersimplesmp.c | 160 |
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 + ); } |