From f3d9f2288e957caabaa1a312096cb72f8e748807 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Mon, 26 Jun 2017 10:35:45 +0200 Subject: score: Add SMP EDF scheduler Update #3056. --- cpukit/score/src/scheduleredfsmp.c | 499 +++++++++++++++++++++++++++++++++++++ 1 file changed, 499 insertions(+) create mode 100644 cpukit/score/src/scheduleredfsmp.c (limited to 'cpukit/score/src/scheduleredfsmp.c') diff --git a/cpukit/score/src/scheduleredfsmp.c b/cpukit/score/src/scheduleredfsmp.c new file mode 100644 index 0000000000..270f9a44e9 --- /dev/null +++ b/cpukit/score/src/scheduleredfsmp.c @@ -0,0 +1,499 @@ +/** + * @file + * + * @brief EDF SMP Scheduler Implementation + * + * @ingroup ScoreSchedulerSMPEDF + */ + +/* + * Copyright (c) 2017 embedded brains GmbH. + * + * 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. + */ + +#if HAVE_CONFIG_H + #include "config.h" +#endif + +#include +#include + +static Scheduler_EDF_SMP_Context * +_Scheduler_EDF_SMP_Get_context( const Scheduler_Control *scheduler ) +{ + return (Scheduler_EDF_SMP_Context *) _Scheduler_Get_context( scheduler ); +} + +static Scheduler_EDF_SMP_Context * +_Scheduler_EDF_SMP_Get_self( Scheduler_Context *context ) +{ + return (Scheduler_EDF_SMP_Context *) context; +} + +static inline Scheduler_EDF_SMP_Node * +_Scheduler_EDF_SMP_Node_downcast( Scheduler_Node *node ) +{ + return (Scheduler_EDF_SMP_Node *) node; +} + +static inline bool _Scheduler_EDF_SMP_Less( + const void *left, + const RBTree_Node *right +) +{ + const Priority_Control *the_left; + const Scheduler_SMP_Node *the_right; + Priority_Control prio_left; + Priority_Control prio_right; + + the_left = left; + the_right = RTEMS_CONTAINER_OF( right, Scheduler_SMP_Node, Base.Node.RBTree ); + + prio_left = *the_left; + prio_right = the_right->priority; + + return prio_left < prio_right; +} + +static inline bool _Scheduler_EDF_SMP_Less_or_equal( + const void *left, + const RBTree_Node *right +) +{ + const Priority_Control *the_left; + const Scheduler_SMP_Node *the_right; + Priority_Control prio_left; + Priority_Control prio_right; + + the_left = left; + the_right = RTEMS_CONTAINER_OF( right, Scheduler_SMP_Node, Base.Node.RBTree ); + + prio_left = *the_left; + prio_right = the_right->priority; + + return prio_left <= prio_right; +} + +void _Scheduler_EDF_SMP_Initialize( const Scheduler_Control *scheduler ) +{ + Scheduler_EDF_SMP_Context *self = + _Scheduler_EDF_SMP_Get_context( scheduler ); + + _Scheduler_SMP_Initialize( &self->Base ); + _RBTree_Initialize_empty( &self->Ready ); +} + +void _Scheduler_EDF_SMP_Node_initialize( + const Scheduler_Control *scheduler, + Scheduler_Node *node, + Thread_Control *the_thread, + Priority_Control priority +) +{ + Scheduler_SMP_Node *smp_node; + + smp_node = _Scheduler_SMP_Node_downcast( node ); + _Scheduler_SMP_Node_initialize( scheduler, smp_node, the_thread, priority ); +} + +static void _Scheduler_EDF_SMP_Do_update( + Scheduler_Context *context, + Scheduler_Node *node, + Priority_Control new_priority +) +{ + Scheduler_SMP_Node *smp_node; + + (void) context; + + smp_node = _Scheduler_SMP_Node_downcast( node ); + _Scheduler_SMP_Node_update_priority( smp_node, new_priority ); +} + +static bool _Scheduler_EDF_SMP_Has_ready( Scheduler_Context *context ) +{ + Scheduler_EDF_SMP_Context *self = + _Scheduler_EDF_SMP_Get_self( context ); + + return !_RBTree_Is_empty( &self->Ready ); +} + +static Scheduler_Node *_Scheduler_EDF_SMP_Get_highest_ready( + Scheduler_Context *context, + Scheduler_Node *node +) +{ + Scheduler_EDF_SMP_Context *self = + _Scheduler_EDF_SMP_Get_self( context ); + Scheduler_Node *first = (Scheduler_Node *) _RBTree_Minimum( &self->Ready ); + + (void) node; + + _Assert( &first->Node != NULL ); + + return first; +} + +static void _Scheduler_EDF_SMP_Move_from_scheduled_to_ready( + Scheduler_Context *context, + Scheduler_Node *scheduled_to_ready +) +{ + Scheduler_EDF_SMP_Context *self = + _Scheduler_EDF_SMP_Get_self( context ); + Scheduler_EDF_SMP_Node *node = + _Scheduler_EDF_SMP_Node_downcast( scheduled_to_ready ); + + _Chain_Extract_unprotected( &node->Base.Base.Node.Chain ); + _RBTree_Initialize_node( &node->Base.Base.Node.RBTree ); + _RBTree_Insert_inline( + &self->Ready, + &node->Base.Base.Node.RBTree, + &node->Base.priority, + _Scheduler_EDF_SMP_Less + ); +} + +static void _Scheduler_EDF_SMP_Move_from_ready_to_scheduled( + Scheduler_Context *context, + Scheduler_Node *ready_to_scheduled +) +{ + Scheduler_EDF_SMP_Context *self = + _Scheduler_EDF_SMP_Get_self( context ); + Scheduler_EDF_SMP_Node *node = + _Scheduler_EDF_SMP_Node_downcast( ready_to_scheduled ); + + _RBTree_Extract( &self->Ready, &node->Base.Base.Node.RBTree ); + _Chain_Initialize_node( &node->Base.Base.Node.Chain ); + _Chain_Insert_ordered_unprotected( + &self->Base.Scheduled, + &node->Base.Base.Node.Chain, + _Scheduler_SMP_Insert_priority_fifo_order + ); +} + +static void _Scheduler_EDF_SMP_Insert_ready_lifo( + Scheduler_Context *context, + Scheduler_Node *node_to_insert +) +{ + Scheduler_EDF_SMP_Context *self = + _Scheduler_EDF_SMP_Get_self( context ); + Scheduler_EDF_SMP_Node *node = + _Scheduler_EDF_SMP_Node_downcast( node_to_insert ); + + _RBTree_Initialize_node( &node->Base.Base.Node.RBTree ); + _RBTree_Insert_inline( + &self->Ready, + &node->Base.Base.Node.RBTree, + &node->Base.priority, + _Scheduler_EDF_SMP_Less_or_equal + ); +} + +static void _Scheduler_EDF_SMP_Insert_ready_fifo( + Scheduler_Context *context, + Scheduler_Node *node_to_insert +) +{ + Scheduler_EDF_SMP_Context *self = + _Scheduler_EDF_SMP_Get_self( context ); + Scheduler_EDF_SMP_Node *node = + _Scheduler_EDF_SMP_Node_downcast( node_to_insert ); + + _RBTree_Initialize_node( &node->Base.Base.Node.RBTree ); + _RBTree_Insert_inline( + &self->Ready, + &node->Base.Base.Node.RBTree, + &node->Base.priority, + _Scheduler_EDF_SMP_Less + ); +} + +static void _Scheduler_EDF_SMP_Extract_from_ready( + Scheduler_Context *context, + Scheduler_Node *node_to_extract +) +{ + Scheduler_EDF_SMP_Context *self = + _Scheduler_EDF_SMP_Get_self( context ); + Scheduler_EDF_SMP_Node *node = + _Scheduler_EDF_SMP_Node_downcast( node_to_extract ); + + _RBTree_Extract( &self->Ready, &node->Base.Base.Node.RBTree ); + _Chain_Initialize_node( &node->Base.Base.Node.Chain ); +} + +void _Scheduler_EDF_SMP_Block( + const Scheduler_Control *scheduler, + Thread_Control *thread, + Scheduler_Node *node +) +{ + Scheduler_Context *context = _Scheduler_Get_context( scheduler ); + + _Scheduler_SMP_Block( + context, + thread, + node, + _Scheduler_EDF_SMP_Extract_from_ready, + _Scheduler_EDF_SMP_Get_highest_ready, + _Scheduler_EDF_SMP_Move_from_ready_to_scheduled, + _Scheduler_SMP_Allocate_processor_lazy + ); +} + +static bool _Scheduler_EDF_SMP_Enqueue_ordered( + Scheduler_Context *context, + Scheduler_Node *node, + Chain_Node_order order, + Scheduler_SMP_Insert insert_ready, + Scheduler_SMP_Insert insert_scheduled +) +{ + return _Scheduler_SMP_Enqueue_ordered( + context, + node, + order, + insert_ready, + insert_scheduled, + _Scheduler_EDF_SMP_Move_from_scheduled_to_ready, + _Scheduler_SMP_Get_lowest_scheduled, + _Scheduler_SMP_Allocate_processor_lazy + ); +} + +static bool _Scheduler_EDF_SMP_Enqueue_lifo( + Scheduler_Context *context, + Scheduler_Node *node +) +{ + return _Scheduler_EDF_SMP_Enqueue_ordered( + context, + node, + _Scheduler_SMP_Insert_priority_lifo_order, + _Scheduler_EDF_SMP_Insert_ready_lifo, + _Scheduler_SMP_Insert_scheduled_lifo + ); +} + +static bool _Scheduler_EDF_SMP_Enqueue_fifo( + Scheduler_Context *context, + Scheduler_Node *node +) +{ + return _Scheduler_EDF_SMP_Enqueue_ordered( + context, + node, + _Scheduler_SMP_Insert_priority_fifo_order, + _Scheduler_EDF_SMP_Insert_ready_fifo, + _Scheduler_SMP_Insert_scheduled_fifo + ); +} + +static bool _Scheduler_EDF_SMP_Enqueue_scheduled_ordered( + Scheduler_Context *context, + Scheduler_Node *node, + Chain_Node_order order, + Scheduler_SMP_Insert insert_ready, + Scheduler_SMP_Insert insert_scheduled +) +{ + return _Scheduler_SMP_Enqueue_scheduled_ordered( + context, + node, + order, + _Scheduler_EDF_SMP_Extract_from_ready, + _Scheduler_EDF_SMP_Get_highest_ready, + insert_ready, + insert_scheduled, + _Scheduler_EDF_SMP_Move_from_ready_to_scheduled, + _Scheduler_SMP_Allocate_processor_lazy + ); +} + +static bool _Scheduler_EDF_SMP_Enqueue_scheduled_lifo( + Scheduler_Context *context, + Scheduler_Node *node +) +{ + return _Scheduler_EDF_SMP_Enqueue_scheduled_ordered( + context, + node, + _Scheduler_SMP_Insert_priority_lifo_order, + _Scheduler_EDF_SMP_Insert_ready_lifo, + _Scheduler_SMP_Insert_scheduled_lifo + ); +} + +static bool _Scheduler_EDF_SMP_Enqueue_scheduled_fifo( + Scheduler_Context *context, + Scheduler_Node *node +) +{ + return _Scheduler_EDF_SMP_Enqueue_scheduled_ordered( + context, + node, + _Scheduler_SMP_Insert_priority_fifo_order, + _Scheduler_EDF_SMP_Insert_ready_fifo, + _Scheduler_SMP_Insert_scheduled_fifo + ); +} + +void _Scheduler_EDF_SMP_Unblock( + const Scheduler_Control *scheduler, + Thread_Control *thread, + Scheduler_Node *node +) +{ + Scheduler_Context *context = _Scheduler_Get_context( scheduler ); + + _Scheduler_SMP_Unblock( + context, + thread, + node, + _Scheduler_EDF_SMP_Do_update, + _Scheduler_EDF_SMP_Enqueue_fifo + ); +} + +static bool _Scheduler_EDF_SMP_Do_ask_for_help( + Scheduler_Context *context, + Thread_Control *the_thread, + Scheduler_Node *node +) +{ + return _Scheduler_SMP_Ask_for_help( + context, + the_thread, + node, + _Scheduler_SMP_Insert_priority_lifo_order, + _Scheduler_EDF_SMP_Insert_ready_lifo, + _Scheduler_SMP_Insert_scheduled_lifo, + _Scheduler_EDF_SMP_Move_from_scheduled_to_ready, + _Scheduler_SMP_Get_lowest_scheduled, + _Scheduler_SMP_Allocate_processor_lazy + ); +} + +void _Scheduler_EDF_SMP_Update_priority( + const Scheduler_Control *scheduler, + Thread_Control *thread, + Scheduler_Node *node +) +{ + Scheduler_Context *context = _Scheduler_Get_context( scheduler ); + + _Scheduler_SMP_Update_priority( + context, + thread, + node, + _Scheduler_EDF_SMP_Extract_from_ready, + _Scheduler_EDF_SMP_Do_update, + _Scheduler_EDF_SMP_Enqueue_fifo, + _Scheduler_EDF_SMP_Enqueue_lifo, + _Scheduler_EDF_SMP_Enqueue_scheduled_fifo, + _Scheduler_EDF_SMP_Enqueue_scheduled_lifo, + _Scheduler_EDF_SMP_Do_ask_for_help + ); +} + +bool _Scheduler_EDF_SMP_Ask_for_help( + const Scheduler_Control *scheduler, + Thread_Control *the_thread, + Scheduler_Node *node +) +{ + Scheduler_Context *context = _Scheduler_Get_context( scheduler ); + + return _Scheduler_EDF_SMP_Do_ask_for_help( context, the_thread, node ); +} + +void _Scheduler_EDF_SMP_Reconsider_help_request( + const Scheduler_Control *scheduler, + Thread_Control *the_thread, + Scheduler_Node *node +) +{ + Scheduler_Context *context = _Scheduler_Get_context( scheduler ); + + _Scheduler_SMP_Reconsider_help_request( + context, + the_thread, + node, + _Scheduler_EDF_SMP_Extract_from_ready + ); +} + +void _Scheduler_EDF_SMP_Withdraw_node( + const Scheduler_Control *scheduler, + Thread_Control *the_thread, + Scheduler_Node *node, + Thread_Scheduler_state next_state +) +{ + Scheduler_Context *context = _Scheduler_Get_context( scheduler ); + + _Scheduler_SMP_Withdraw_node( + context, + the_thread, + node, + next_state, + _Scheduler_EDF_SMP_Extract_from_ready, + _Scheduler_EDF_SMP_Get_highest_ready, + _Scheduler_EDF_SMP_Move_from_ready_to_scheduled, + _Scheduler_SMP_Allocate_processor_lazy + ); +} + +void _Scheduler_EDF_SMP_Add_processor( + const Scheduler_Control *scheduler, + Thread_Control *idle +) +{ + Scheduler_Context *context = _Scheduler_Get_context( scheduler ); + + _Scheduler_SMP_Add_processor( + context, + idle, + _Scheduler_EDF_SMP_Has_ready, + _Scheduler_EDF_SMP_Enqueue_scheduled_fifo + ); +} + +Thread_Control *_Scheduler_EDF_SMP_Remove_processor( + const Scheduler_Control *scheduler, + Per_CPU_Control *cpu +) +{ + Scheduler_Context *context = _Scheduler_Get_context( scheduler ); + + return _Scheduler_SMP_Remove_processor( + context, + cpu, + _Scheduler_EDF_SMP_Extract_from_ready, + _Scheduler_EDF_SMP_Enqueue_fifo + ); +} + +void _Scheduler_EDF_SMP_Yield( + const Scheduler_Control *scheduler, + Thread_Control *thread, + Scheduler_Node *node +) +{ + Scheduler_Context *context = _Scheduler_Get_context( scheduler ); + + _Scheduler_SMP_Yield( + context, + thread, + node, + _Scheduler_EDF_SMP_Extract_from_ready, + _Scheduler_EDF_SMP_Enqueue_fifo, + _Scheduler_EDF_SMP_Enqueue_scheduled_fifo + ); +} -- cgit v1.2.3