From 520882a2461e96728ae5bdb95966b126ad100044 Mon Sep 17 00:00:00 2001 From: richidubey Date: Sat, 25 Jul 2020 22:43:05 +0530 Subject: [PATCH 1/9] Added files for version 1.1 --- .../include/rtems/score/schedulerstrongapa.h | 307 +++--- cpukit/score/src/schedulerstrongapa.c | 966 ++++++++++++++---- 2 files changed, 962 insertions(+), 311 deletions(-) diff --git a/cpukit/include/rtems/score/schedulerstrongapa.h b/cpukit/include/rtems/score/schedulerstrongapa.h index 0ac28cb4393..4ddae3235a4 100644 --- a/cpukit/include/rtems/score/schedulerstrongapa.h +++ b/cpukit/include/rtems/score/schedulerstrongapa.h @@ -6,25 +6,24 @@ * @brief Strong APA Scheduler API */ -/* - * Copyright (c) 2013, 2018 embedded brains GmbH. All rights reserved. - * - * embedded brains GmbH - * Dornierstr. 4 - * 82178 Puchheim - * Germany - * - * - * 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. +/* + * Copyright (c) 2013, 2018 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * + * + * 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_SCHEDULERSTRONGAPA_H #define _RTEMS_SCORE_SCHEDULERSTRONGAPA_H #include -#include #include #ifdef __cplusplus @@ -38,25 +37,32 @@ extern "C" { * * @brief Strong APA Scheduler * - * This is an implementation of the global fixed priority scheduler (G-FP). It - * uses one ready chain per priority to ensure constant time insert operations. - * The scheduled chain uses linear insert operations and has at most processor - * count entries. Since the processor and priority count are constants all - * scheduler operations complete in a bounded execution time. - * - * The the_thread preempt mode will be ignored. + * This is an implementation of the Strong APA scheduler defined by + * Bradenbug et. al in Linux's Processor Affinity API, Refined: Shifting Real-Time Tasks Towards Higher Schedulability. * * @{ */ -/** - * @brief Scheduler context specialization for Strong APA - * schedulers. + /** + * @brief Scheduler context for Strong APA + * scheduler. + * + * Has the structure for scheduler context + * and Node defintion for Strong APA scheduler */ typedef struct { - Scheduler_SMP_Context Base; - Priority_bit_map_Control Bit_map; - Chain_Control Ready[ RTEMS_ZERO_LENGTH_ARRAY ]; + /** + * @brief SMP Context to refer to SMP implementation + * code. + */ + Scheduler_SMP_Context Base; + + /** + * @brief Chain of all the nodes present in + * the system. Accounts for ready and scheduled nodes. + */ + Chain_Control allNodes; + } Scheduler_strong_APA_Context; /** @@ -64,17 +70,51 @@ typedef struct { * schedulers. */ typedef struct { + /** + * @brief Chain node for + * Scheduler_strong_APA_Context::allNodes + * + */ + Chain_Node Node; + /** * @brief SMP scheduler node. */ Scheduler_SMP_Node Base; /** - * @brief The associated ready queue of this node. + * @brief The associated affinity set of this node. + */ + Processor_mask affinity; + + /** + * @brief The associated affinity set of this node + * to be used while unpinning the node. */ - Scheduler_priority_Ready_queue Ready_queue; + Processor_mask unpin_affinity; + } Scheduler_strong_APA_Node; +/** + * @brief CPU structure to be used + * while traversing in the FIFO Queue + */ +typedef struct CPU +{ + /** + * @brief Chain node for + * _Scheduler_strong_APA_Get_highest_ready::Queue + * and _Scheduler_strong_APA_Get_lowest_scheduled::Queue + */ + Chain_Node node; + + /** + * @brief cpu associated with the node + */ + Per_CPU_Control cpu; + +}CPU; + /** * @brief Entry points for the Strong APA Scheduler. */ @@ -91,8 +131,8 @@ typedef struct { _Scheduler_strong_APA_Ask_for_help, \ _Scheduler_strong_APA_Reconsider_help_request, \ _Scheduler_strong_APA_Withdraw_node, \ - _Scheduler_default_Pin_or_unpin, \ - _Scheduler_default_Pin_or_unpin, \ + _Scheduler_strong_APA_Pin, \ + _Scheduler_strong_APA_Unpin, \ _Scheduler_strong_APA_Add_processor, \ _Scheduler_strong_APA_Remove_processor, \ _Scheduler_strong_APA_Node_initialize, \ @@ -100,25 +140,15 @@ typedef struct { _Scheduler_default_Release_job, \ _Scheduler_default_Cancel_job, \ _Scheduler_default_Tick, \ - _Scheduler_SMP_Start_idle \ - SCHEDULER_OPERATION_DEFAULT_GET_SET_AFFINITY \ + _Scheduler_strong_APA_Start_idle \ + _Scheduler_strong_APA_Set_affinity \ } -/** - * @brief Initializes the scheduler. - * - * @param scheduler The scheduler to initialize. - */ -void _Scheduler_strong_APA_Initialize( const Scheduler_Control *scheduler ); +void _Scheduler_strong_APA_Initialize( + const Scheduler_Control *scheduler + ); + -/** - * @brief Initializes the node with the given priority. - * - * @param scheduler The scheduler control instance. - * @param[out] node The node to initialize. - * @param the_thread The thread of the node to initialize. - * @param priority The priority for @a node. - */ void _Scheduler_strong_APA_Node_initialize( const Scheduler_Control *scheduler, Scheduler_Node *node, @@ -126,82 +156,101 @@ void _Scheduler_strong_APA_Node_initialize( Priority_Control priority ); -/** - * @brief Blocks the thread. - * - * @param scheduler The scheduler control instance. - * @param[in, out] the_thread The thread to block. - * @param[in, out] node The node of the thread to block. - */ +void _Scheduler_strong_APA_Do_update( + Scheduler_Context *context, + Scheduler_Node *node, + Priority_Control new_priority +); + +bool _Scheduler_strong_APA_Has_ready( + Scheduler_Context *context + ); + +Scheduler_Node *_Scheduler_strong_APA_Get_highest_ready( + Scheduler_Context *context, + Scheduler_Node *filter +); + +Scheduler_Node *_Scheduler_strong_APA_Get_lowest_scheduled( + Scheduler_Context *context, + Scheduler_Node *filter_base +); + +void _Scheduler_strong_APA_Extract_from_scheduled( + Scheduler_Context *context, + Scheduler_Node *node_to_extract +); + +void _Scheduler_strong_APA_Extract_from_ready( + Scheduler_Context *context, + Scheduler_Node *node_to_extract +); + +void _Scheduler_strong_APA_Move_from_scheduled_to_ready( + Scheduler_Context *context, + Scheduler_Node *scheduled_to_ready +); + +void _Scheduler_strong_APA_Move_from_ready_to_scheduled( + Scheduler_Context *context, + Scheduler_Node *ready_to_scheduled +); + +void _Scheduler_strong_APA_Insert_ready( + Scheduler_Context *context, + Scheduler_Node *node_base, + Priority_Control insert_priority +); + +void _Scheduler_strong_APA_Allocate_processor( + Scheduler_Context *context, + Scheduler_Node *scheduled_base, + Scheduler_Node *victim_base, + Per_CPU_Control *victim_cpu +); + void _Scheduler_strong_APA_Block( const Scheduler_Control *scheduler, - Thread_Control *the_thread, + Thread_Control *thread, Scheduler_Node *node ); -/** - * @brief Unblocks the thread. - * - * @param scheduler The scheduler control instance. - * @param[in, out] the_thread The thread to unblock. - * @param[in, out] node The node of the thread to unblock. - */ +bool _Scheduler_strong_APA_Enqueue( + Scheduler_Context *context, + Scheduler_Node *node, + Priority_Control insert_priority +); + +bool _Scheduler_strong_APA_Enqueue_scheduled( + Scheduler_Context *context, + Scheduler_Node *node, + Priority_Control insert_priority +); + void _Scheduler_strong_APA_Unblock( const Scheduler_Control *scheduler, - Thread_Control *the_thread, + Thread_Control *thread, Scheduler_Node *node ); -/** - * @brief Updates the priority of the node. - * - * @param scheduler The scheduler control instance. - * @param the_thread The thread for the operation. - * @param[in, out] node The node to update the priority of. - */ -void _Scheduler_strong_APA_Update_priority( +bool _Scheduler_strong_APA_Ask_for_help( const Scheduler_Control *scheduler, Thread_Control *the_thread, Scheduler_Node *node ); -/** - * @brief Asks for help. - * - * @param scheduler The scheduler control instance. - * @param the_thread The thread that asks for help. - * @param node The node of @a the_thread. - * - * @retval true The request for help was successful. - * @retval false The request for help was not successful. - */ -bool _Scheduler_strong_APA_Ask_for_help( +void _Scheduler_strong_APA_Update_priority( const Scheduler_Control *scheduler, - Thread_Control *the_thread, + Thread_Control *thread, Scheduler_Node *node ); -/** - * @brief Reconsiders help request. - * - * @param scheduler The scheduler control instance. - * @param the_thread The thread to reconsider the help request of. - * @param[in, out] node The node of @a the_thread - */ void _Scheduler_strong_APA_Reconsider_help_request( const Scheduler_Control *scheduler, Thread_Control *the_thread, Scheduler_Node *node ); -/** - * @brief Withdraws the node. - * - * @param scheduler The scheduler control instance. - * @param[in, out] the_thread The thread to change the state to @a next_state. - * @param[in, out] node The node to withdraw. - * @param next_state The next state for @a the_thread. - */ void _Scheduler_strong_APA_Withdraw_node( const Scheduler_Control *scheduler, Thread_Control *the_thread, @@ -209,43 +258,61 @@ void _Scheduler_strong_APA_Withdraw_node( Thread_Scheduler_state next_state ); -/** - * @brief Adds the idle thread to a processor. - * - * @param scheduler The scheduler control instance. - * @param[in, out] The idle thread to add to the processor. - */ +void _Scheduler_strong_APA_Register_idle( + Scheduler_Context *context, + Scheduler_Node *idle_base, + Per_CPU_Control *cpu +); + void _Scheduler_strong_APA_Add_processor( const Scheduler_Control *scheduler, Thread_Control *idle ); -/** - * @brief Removes an idle thread from the given cpu. - * - * @param scheduler The scheduler instance. - * @param cpu The cpu control to remove from @a scheduler. - * - * @return The idle thread of the processor. - */ Thread_Control *_Scheduler_strong_APA_Remove_processor( const Scheduler_Control *scheduler, - struct Per_CPU_Control *cpu + Per_CPU_Control *cpu ); -/** - * @brief Performs a yield operation. - * - * @param scheduler The scheduler control instance. - * @param the_thread The thread to yield. - * @param[in, out] node The node of @a the_thread. - */ void _Scheduler_strong_APA_Yield( const Scheduler_Control *scheduler, - Thread_Control *the_thread, + Thread_Control *thread, Scheduler_Node *node ); +void _Scheduler_strong_APA_Do_set_affinity( + Scheduler_Context *context, + Scheduler_Node *node_base, + void *arg +); + +void _Scheduler_strong_APA_Start_idle( + const Scheduler_Control *scheduler, + Thread_Control *idle, + Per_CPU_Control *cpu +); + +void _Scheduler_strong_APA_Pin( + const Scheduler_Control *scheduler, + Thread_Control *thread, + Scheduler_Node *node_base, + struct Per_CPU_Control *cpu +); + +void _Scheduler_strong_APA_Unpin( + const Scheduler_Control *scheduler, + Thread_Control *thread, + Scheduler_Node *node_base, + struct Per_CPU_Control *cpu +); + +bool _Scheduler_strong_APA_Set_affinity( + const Scheduler_Control *scheduler, + Thread_Control *thread, + Scheduler_Node *node_base, + const Processor_mask *affinity +); + /** @} */ #ifdef __cplusplus diff --git a/cpukit/score/src/schedulerstrongapa.c b/cpukit/score/src/schedulerstrongapa.c index 924cd86412c..c26c2488566 100644 --- a/cpukit/score/src/schedulerstrongapa.c +++ b/cpukit/score/src/schedulerstrongapa.c @@ -5,249 +5,579 @@ * * @brief Strong APA Scheduler Implementation */ - -/* - * Copyright (c) 2013, 2016 embedded brains GmbH. All rights reserved. - * - * embedded brains GmbH - * Dornierstr. 4 - * 82178 Puchheim - * Germany - * - * - * 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. - */ + +/* + * Copyright (c) 2013, 2016 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * + * + * 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. + */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include -#include #include -static Scheduler_strong_APA_Context *_Scheduler_strong_APA_Get_self( - Scheduler_Context *context -) +static inline Scheduler_strong_APA_Context * +_Scheduler_strong_APA_Get_context( const Scheduler_Control *scheduler ) +{ + return (Scheduler_strong_APA_Context *) _Scheduler_Get_context( scheduler ); +} + +static inline Scheduler_strong_APA_Context * +_Scheduler_strong_APA_Get_self( Scheduler_Context *context ) { return (Scheduler_strong_APA_Context *) context; } -static Scheduler_strong_APA_Node * +static inline Scheduler_strong_APA_Node * _Scheduler_strong_APA_Node_downcast( Scheduler_Node *node ) { return (Scheduler_strong_APA_Node *) node; } - -static void _Scheduler_strong_APA_Move_from_scheduled_to_ready( - Scheduler_Context *context, - Scheduler_Node *scheduled_to_ready -) +/** + * @brief Initializes the Strong_APA scheduler. + * + * Sets the chain containing all the nodes to empty + * and initializes the SMP scheduler. + * + * @param scheduler used to get + * reference to Strong APA scheduler context + * @retval void + * @see _Scheduler_strong_APA_Node_initialize() + * + */ +void _Scheduler_strong_APA_Initialize( const Scheduler_Control *scheduler ) { Scheduler_strong_APA_Context *self = - _Scheduler_strong_APA_Get_self( context ); - Scheduler_strong_APA_Node *node = - _Scheduler_strong_APA_Node_downcast( scheduled_to_ready ); - - _Chain_Extract_unprotected( &node->Base.Base.Node.Chain ); - _Scheduler_priority_Ready_queue_enqueue_first( - &node->Base.Base.Node.Chain, - &node->Ready_queue, - &self->Bit_map - ); + _Scheduler_strong_APA_Get_context( scheduler ); + + _Scheduler_SMP_Initialize( &self->Base ); + _Chain_Initialize_empty( &self->allNodes ); } -static void _Scheduler_strong_APA_Move_from_ready_to_scheduled( - Scheduler_Context *context, - Scheduler_Node *ready_to_scheduled +/** + * @brief Initializes the node with the given priority. + * + * @param scheduler The scheduler control instance. + * @param[out] node The node to initialize. + * @param the_thread The thread of the node to initialize. + * @param priority The priority for @a node. + */ +void _Scheduler_strong_APA_Node_initialize( + const Scheduler_Control *scheduler, + Scheduler_Node *node, + Thread_Control *the_thread, + Priority_Control priority ) { - Scheduler_strong_APA_Context *self; - Scheduler_strong_APA_Node *node; - Priority_Control insert_priority; - - self = _Scheduler_strong_APA_Get_self( context ); - node = _Scheduler_strong_APA_Node_downcast( ready_to_scheduled ); - - _Scheduler_priority_Ready_queue_extract( - &node->Base.Base.Node.Chain, - &node->Ready_queue, - &self->Bit_map - ); - insert_priority = _Scheduler_SMP_Node_priority( &node->Base.Base ); - insert_priority = SCHEDULER_PRIORITY_APPEND( insert_priority ); - _Chain_Insert_ordered_unprotected( - &self->Base.Scheduled, - &node->Base.Base.Node.Chain, - &insert_priority, - _Scheduler_SMP_Priority_less_equal - ); + 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_strong_APA_Insert_ready( +/** + * @brief Helper function for /a update entry function + * + * Calls _Scheduler_SMP_Node_update_priority() + * + * @param scheduler The scheduler context. + * @param[out] node The node to update the priority of. + * @param new_priority Node's new priority. + * @see _Scheduler_strong_APA_Do_update() + */ +void _Scheduler_strong_APA_Do_update( Scheduler_Context *context, - Scheduler_Node *node_base, - Priority_Control insert_priority + Scheduler_Node *node, + Priority_Control new_priority ) { - Scheduler_strong_APA_Context *self; - Scheduler_strong_APA_Node *node; + Scheduler_SMP_Node *smp_node; - self = _Scheduler_strong_APA_Get_self( context ); - node = _Scheduler_strong_APA_Node_downcast( node_base ); + (void) context; + + smp_node = _Scheduler_SMP_Node_downcast( node ); + _Scheduler_SMP_Node_update_priority( smp_node, new_priority ); +} + +/** + * @brief Checks if scheduler has a ready node + * + * Iterates through all the nodes in /a allNodes to + * look for a ready node + * + * @param scheduler The scheduler context. + * @retval true if scheduler has a ready node available + * @retval false if scheduler has no ready nodes available + */ - if ( SCHEDULER_PRIORITY_IS_APPEND( insert_priority ) ) { - _Scheduler_priority_Ready_queue_enqueue( - &node->Base.Base.Node.Chain, - &node->Ready_queue, - &self->Bit_map - ); - } else { - _Scheduler_priority_Ready_queue_enqueue_first( - &node->Base.Base.Node.Chain, - &node->Ready_queue, - &self->Bit_map - ); +bool _Scheduler_strong_APA_Has_ready( Scheduler_Context *context ) +{ + Scheduler_strong_APA_Context *self = _Scheduler_strong_APA_Get_self( context ); + + bool ret; + const Chain_Node *tail; + Chain_Node *next; + + tail = _Chain_Immutable_tail( &self->allNodes ); + next = _Chain_First( &self->allNodes ); + + ret=false; + + while ( next != tail ) { + Scheduler_strong_APA_Node *node; + + node = (Scheduler_strong_APA_Node *) next; + + if( _Scheduler_SMP_Node_state( &node->Base.Base ) + == SCHEDULER_SMP_NODE_READY ) { + ret=true; + break; + } } + + return ret; } -static void _Scheduler_strong_APA_Extract_from_ready( +/** + * @brief Checks the next highest node ready on run + * on the CPU on which @filter node was running on + * + */ +Scheduler_Node *_Scheduler_strong_APA_Get_highest_ready( Scheduler_Context *context, - Scheduler_Node *the_thread -) + Scheduler_Node *filter +) //TODO { - Scheduler_strong_APA_Context *self = - _Scheduler_strong_APA_Get_self( context ); - Scheduler_strong_APA_Node *node = - _Scheduler_strong_APA_Node_downcast( the_thread ); - - _Scheduler_priority_Ready_queue_extract( - &node->Base.Base.Node.Chain, - &node->Ready_queue, - &self->Bit_map - ); + //Plan for this function: (Pseudo Code): + Scheduler_strong_APA_Context *self=_Scheduler_strong_APA_Get_self( context ); + + CPU *Qcpu; + Thread_Control *thread; + Per_CPU_Control *thread_cpu; + Per_CPU_Control *curr_CPU; + Per_CPU_Control *assigned_cpu; + Scheduler_Node *ret; + Priority_Control max_priority; + Priority_Control curr_priority; + Chain_Control Queue; + bool visited[10]; //Temporary Compilation Fix + + + + thread = filter->user; + thread_cpu = _Thread_Get_CPU( thread ); + + //Implement the BFS Algorithm for task departure + //to get the highest ready task for a particular CPU + + + max_priority = _Scheduler_Node_get_priority( filter ); + max_priority = SCHEDULER_PRIORITY_PURIFY( max_priority ); + + ret=filter; + + const Chain_Node *tail; + Chain_Node *next; + + _Chain_Initialize_empty(&Queue); + + Qcpu = malloc( sizeof(CPU) ); + assert (Qcpu != NULL); //Should it be NULL? + Qcpu->cpu=thread_cpu; + + _Chain_Initialize_node( &Qcpu->node ); + _Chain_Append_unprotected( &Queue, &Qcpu->node ); //Insert thread_CPU in the Queue + visited[ _Per_CPU_Get_index( thread_cpu ) ]=true; + + + while( !_Chain_Is_empty( &Queue) ) { + Qcpu = (CPU*) _Chain_Get_first_unprotected( &Queue ); + curr_CPU = Qcpu->cpu; + tail = _Chain_Immutable_tail( &self->allNodes ); + next = _Chain_First( &self->allNodes ); + + while ( next != tail ) { + Scheduler_strong_APA_Node *node; + node = (Scheduler_strong_APA_Node *) next; + + if( node->affinity & (1 << _Per_CPU_Get_index( curr_CPU ) ) ) { + //Checks if the thread_CPU is in the affinity set of the node + + if(_Scheduler_SMP_Node_state( &node->Base.Base ) + == SCHEDULER_SMP_NODE_SCHEDULED) { + + assigned_cpu = _Thread_Get_CPU( node->Base.Base.user ); + + if(visited[ _Per_CPU_Get_index( assigned_cpu ) ] == false) { + Qcpu = malloc( sizeof(CPU) ); + assert (Qcpu != NULL); //Should it be NULL? + Qcpu->cpu=*assigned_cpu; + + _Chain_Initialize_node( &Qcpu->node ); + _Chain_Append_unprotected( &Queue, &Qcpu->node ); + //Insert thread_CPU in the Queue + visited[ _Per_CPU_Get_index (assigned_cpu) ]=true; + } + } + else if(_Scheduler_SMP_Node_state( &node->Base.Base ) + == SCHEDULER_SMP_NODE_READY) { + curr_priority = _Scheduler_Node_get_priority( (Scheduler_Node *) next ); + curr_priority = SCHEDULER_PRIORITY_PURIFY( curr_priority ); + + if(curr_priorityBase.Base; + } + } + } + next = _Chain_Next( next ); + } + } + + if( ret != filter) + { + //Backtrack on the path from + //thread_cpu to ret, shifting along every task. + + //After this, thread_cpu receives the ret task + // So the ready task ret gets scheduled as well. + } + + return ret; +} +/** + * @brief Checks the lowest scheduled node + * running on a processor on which the + * @filter_base node could be running on + * + * @param context The scheduler context instance. + * @param filter_base The node which wants to get scheduled. + * + * @retval node The lowest scheduled node that can be + * replaced by @filter_base + */ +Scheduler_Node *_Scheduler_strong_APA_Get_lowest_scheduled( + Scheduler_Context *context, + Scheduler_Node *filter_base +) +{ + //Idea: BFS Algorithm for task arrival + + uint32_t cpu_max; + uint32_t cpu_index; + CPU *Qcpu; + + Per_CPU_Control *curr_CPU; + Thread_Control *curr_thread; + Scheduler_Node *curr_node; + Scheduler_Node *ret; + Chain_Control Queue; + Priority_Control max_priority; + Priority_Control curr_priority; + bool visited[10]; //Temporary Compilation Fix + + Scheduler_strong_APA_Node *Scurr_node; //Current Strong_APA_Node + Scheduler_strong_APA_Node *filter_node; + + filter_node = _Scheduler_strong_APA_Node_downcast( filter_base ); + + max_priority = 300;//Max (Lowest) priority encountered so far. + + cpu_max = _SMP_Get_processor_maximum(); + _Chain_Initialize_empty(&Queue); + + for ( cpu_index = 0 ; cpu_index < cpu_max ; ++cpu_index ) { + if( ( filter_node->affinity & (1<cpu=*cpu; + + _Chain_Initialize_node( &Qcpu->node ); + _Chain_Append_unprotected( &Queue, &Qcpu->node ); + //Insert cpu in the Queue + visited[ cpu_index ]=true; + } + } + } + + while( !_Chain_Is_empty( &Queue) ) { + Qcpu = (CPU*) _Chain_Get_first_unprotected( &Queue ); + curr_CPU = &Qcpu->cpu; + curr_thread = curr_CPU->executing; + + curr_node = (Scheduler_Node *) _Chain_First( &curr_thread->Scheduler.Scheduler_nodes ); + + //How to check if the thread is not participating + //in helping on this processor? + + curr_priority = _Scheduler_Node_get_priority( curr_node ); + curr_priority = SCHEDULER_PRIORITY_PURIFY( curr_priority ); + + if(curr_priority < max_priority) { + ret = curr_node; + max_priority = curr_priority; + } + + Scurr_node = _Scheduler_strong_APA_Node_downcast( curr_node ); + if( !curr_thread->is_idle ) { + for ( cpu_index = 0 ; cpu_index < cpu_max ; ++cpu_index ) { + if( ( Scurr_node->affinity & (1<cpu=*cpu; + + _Chain_Initialize_node( &Qcpu->node ); + _Chain_Append_unprotected( &Queue, &Qcpu->node ); + //Insert the cpu in the affinty set of curr_thread in the Queue + visited[ cpu_index ]=true; + } + } + } + } + } + + Priority_Control filter_priority; + filter_priority = _Scheduler_Node_get_priority( filter_base ); + filter_priority = SCHEDULER_PRIORITY_PURIFY( filter_priority ); + + if( ret->Priority.value < filter_priority ) { + //Lowest priority task found has higher priority + // than filter_base. + //So, filter_base remains unassigned + //No task shifting. + } + + else { + //Backtrack on the path from + //_Thread_Get_CPU(ret->user) to ret, shifting along every task + } + + return ret; } -static void _Scheduler_strong_APA_Do_update( +/** + * @brief Extracts a node from the scheduled node's list + * + * Calls _Scheduler_SMP_Extract_from_scheduled() + * + * @param scheduler The scheduler context + * @param[in] node_to_extract The node to extract. + */ +void _Scheduler_strong_APA_Extract_from_scheduled( Scheduler_Context *context, - Scheduler_Node *node_to_update, - Priority_Control new_priority + Scheduler_Node *node_to_extract ) { - Scheduler_strong_APA_Context *self = - _Scheduler_strong_APA_Get_self( context ); - Scheduler_strong_APA_Node *node = - _Scheduler_strong_APA_Node_downcast( node_to_update ); - - _Scheduler_SMP_Node_update_priority( &node->Base, new_priority ); - _Scheduler_priority_Ready_queue_update( - &node->Ready_queue, - SCHEDULER_PRIORITY_UNMAP( new_priority ), - &self->Bit_map, - &self->Ready[ 0 ] - ); + Scheduler_strong_APA_Context *self; + Scheduler_strong_APA_Node *node; + + self = _Scheduler_strong_APA_Get_self( context ); + node = _Scheduler_strong_APA_Node_downcast( node_to_extract ); + + _Scheduler_SMP_Extract_from_scheduled( &self->Base.Base, &node->Base.Base ); + //Not removing it from allNodes since the node could go in the ready state. } -static Scheduler_strong_APA_Context * -_Scheduler_strong_APA_Get_context( const Scheduler_Control *scheduler ) +/** + * @brief Extracts a node from the ready queue + * + * Removes the node from /a allNodes chain. + * + * @param scheduler The scheduler context + * @param[in] node_to_extract The node to extract. + */ +void _Scheduler_strong_APA_Extract_from_ready( + Scheduler_Context *context, + Scheduler_Node *node_to_extract +) { - return (Scheduler_strong_APA_Context *) _Scheduler_Get_context( scheduler ); + Scheduler_strong_APA_Context *self; + Scheduler_strong_APA_Node *node; + + self = _Scheduler_strong_APA_Get_self( context ); + node = _Scheduler_strong_APA_Node_downcast( node_to_extract ); + + _Assert( _Chain_Is_empty(self->allNodes) == false ); + _Assert( _Chain_Is_node_off_chain( &node->Node ) == false ); + + _Chain_Extract_unprotected( &node->Node ); //Removed from allNodes + _Chain_Set_off_chain( &node->Node ); } -void _Scheduler_strong_APA_Initialize( const Scheduler_Control *scheduler ) +/** + * @brief Moves a node from scheduled to ready state + * + * Calls _Scheduler_SMP_Extract_from_scheduled() to remove it from + * scheduled nodes list + * + * @param scheduler The scheduler context + * @param[in] scheduled_to_ready The node to move. + * @see _Scheduler_strong_APA_Insert_ready() + * + */ +void _Scheduler_strong_APA_Move_from_scheduled_to_ready( + Scheduler_Context *context, + Scheduler_Node *scheduled_to_ready +) { - Scheduler_strong_APA_Context *self = - _Scheduler_strong_APA_Get_context( scheduler ); + Priority_Control insert_priority; - _Scheduler_SMP_Initialize( &self->Base ); - _Priority_bit_map_Initialize( &self->Bit_map ); - _Scheduler_priority_Ready_queue_initialize( - &self->Ready[ 0 ], - scheduler->maximum_priority + _Scheduler_SMP_Extract_from_scheduled( context, scheduled_to_ready ); + insert_priority = _Scheduler_SMP_Node_priority( scheduled_to_ready ); + + _Scheduler_strong_APA_Insert_ready( + context, + scheduled_to_ready, + insert_priority ); } -void _Scheduler_strong_APA_Node_initialize( - const Scheduler_Control *scheduler, - Scheduler_Node *node, - Thread_Control *the_thread, - Priority_Control priority +/** + * @brief Moves a node from ready to scheduled state. + * + * Calls the corresponding SMP function \a _Scheduler_SMP_Insert_scheduled() + * with append insert_priority + * + * @param context The scheduler context. + * @param ready_to_scheduled Node which moves from ready state. + */ +void _Scheduler_strong_APA_Move_from_ready_to_scheduled( + Scheduler_Context *context, + Scheduler_Node *ready_to_scheduled ) { - Scheduler_Context *context; - Scheduler_strong_APA_Context *self; - Scheduler_strong_APA_Node *the_node; - - the_node = _Scheduler_strong_APA_Node_downcast( node ); - _Scheduler_SMP_Node_initialize( - scheduler, - &the_node->Base, - the_thread, - priority - ); + Priority_Control insert_priority; - context = _Scheduler_Get_context( scheduler ); - self = _Scheduler_strong_APA_Get_self( context ); - _Scheduler_priority_Ready_queue_update( - &the_node->Ready_queue, - SCHEDULER_PRIORITY_UNMAP( priority ), - &self->Bit_map, - &self->Ready[ 0 ] + _Scheduler_strong_APA_Extract_from_ready( context, ready_to_scheduled ); + insert_priority = _Scheduler_SMP_Node_priority( ready_to_scheduled ); + insert_priority = SCHEDULER_PRIORITY_APPEND( insert_priority ); + _Scheduler_SMP_Insert_scheduled( + context, + ready_to_scheduled, + insert_priority ); + //Note: The node still stays in the allNodes chain } -static bool _Scheduler_strong_APA_Has_ready( Scheduler_Context *context ) +/** + * @brief Inserts a node in the ready queue. + * + * Adds it into the /a allNodes chain. + * + * @param context The scheduler context. + * @param node_base Node which is inserted into the queue. + * @param insert_priority priority at which the node is inserted + */ + +void _Scheduler_strong_APA_Insert_ready( + Scheduler_Context *context, + Scheduler_Node *node_base, + Priority_Control insert_priority +) { - Scheduler_strong_APA_Context *self = - _Scheduler_strong_APA_Get_self( context ); + Scheduler_strong_APA_Context *self; + Scheduler_strong_APA_Node *node; - return !_Priority_bit_map_Is_empty( &self->Bit_map ); + self = _Scheduler_strong_APA_Get_self( context ); + node = _Scheduler_strong_APA_Node_downcast( node_base ); + + _Assert( _Chain_Is_node_off_chain( &node->Node ) == true ); + + _Chain_Append_unprotected( &self->allNodes, &node->Node ); } -static Scheduler_Node *_Scheduler_strong_APA_Get_highest_ready( +/** + * @brief Allocates a processor for the node. + * + * Calls _Scheduler_SMP_Allocate_processor_exact() + * + * @param context The scheduler context. + * @param scheduled_base Node which is to be allocated the @victim_cpu. + * @param victim_base Node which was executing earlier on @victim_cpu + * @victim_cpu CPU on which the @scheduled_base would be allocated on + */ +void _Scheduler_strong_APA_Allocate_processor( Scheduler_Context *context, - Scheduler_Node *node + Scheduler_Node *scheduled_base, + Scheduler_Node *victim_base, + Per_CPU_Control *victim_cpu ) { - Scheduler_strong_APA_Context *self = - _Scheduler_strong_APA_Get_self( context ); - - (void) node; + Scheduler_strong_APA_Node *scheduled; + + (void) victim_base; + scheduled = _Scheduler_strong_APA_Node_downcast( scheduled_base ); - return (Scheduler_Node *) _Scheduler_priority_Ready_queue_first( - &self->Bit_map, - &self->Ready[ 0 ] + _Scheduler_SMP_Allocate_processor_exact( + context, + &(scheduled->Base.Base), + NULL, + victim_cpu ); } +/** + * @brief Blocks a node + * + * Changes the state of the node and extracts it from the queue + * calls _Scheduler_SMP_Block(). + * + * @param context The scheduler control instance. + * @param thread Thread correspoding to the @node. + * @param node node which is to be blocked + */ void _Scheduler_strong_APA_Block( const Scheduler_Control *scheduler, - Thread_Control *the_thread, + Thread_Control *thread, Scheduler_Node *node ) { Scheduler_Context *context = _Scheduler_Get_context( scheduler ); - +//The extract from ready automatically removes the node from allNodes chain. _Scheduler_SMP_Block( context, - the_thread, + thread, node, - _Scheduler_SMP_Extract_from_scheduled, + _Scheduler_strong_APA_Extract_from_scheduled, _Scheduler_strong_APA_Extract_from_ready, _Scheduler_strong_APA_Get_highest_ready, _Scheduler_strong_APA_Move_from_ready_to_scheduled, - _Scheduler_SMP_Allocate_processor_exact + _Scheduler_strong_APA_Allocate_processor ); } -static bool _Scheduler_strong_APA_Enqueue( +/** + * @brief Enqueues a node + * + * + * @param context The scheduler context. + * @param node node which is to be enqueued + * @param insert_priority priority at which the node should be enqueued. + */ +bool _Scheduler_strong_APA_Enqueue( Scheduler_Context *context, Scheduler_Node *node, Priority_Control insert_priority ) -{ +{//I'm hoping all this works on its own. return _Scheduler_SMP_Enqueue( context, node, @@ -256,17 +586,25 @@ static bool _Scheduler_strong_APA_Enqueue( _Scheduler_strong_APA_Insert_ready, _Scheduler_SMP_Insert_scheduled, _Scheduler_strong_APA_Move_from_scheduled_to_ready, - _Scheduler_SMP_Get_lowest_scheduled, - _Scheduler_SMP_Allocate_processor_exact + _Scheduler_strong_APA_Get_lowest_scheduled, + _Scheduler_strong_APA_Allocate_processor ); } -static bool _Scheduler_strong_APA_Enqueue_scheduled( +/** + * @brief Enqueues a node in the scheduled queue + * + * + * @param context The scheduler context. + * @param node node which is to be enqueued + * @param insert_priority priority at which the node should be enqueued. + */ +bool _Scheduler_strong_APA_Enqueue_scheduled( Scheduler_Context *context, Scheduler_Node *node, - Priority_Control insert_priority + Priority_Control insert_priority ) -{ +{ return _Scheduler_SMP_Enqueue_scheduled( context, node, @@ -277,13 +615,24 @@ static bool _Scheduler_strong_APA_Enqueue_scheduled( _Scheduler_strong_APA_Insert_ready, _Scheduler_SMP_Insert_scheduled, _Scheduler_strong_APA_Move_from_ready_to_scheduled, - _Scheduler_SMP_Allocate_processor_exact + _Scheduler_strong_APA_Allocate_processor ); } +/** + * @brief Unblocks a node + * + * Changes the state of the node and calls _Scheduler_SMP_Unblock(). + * + * @param scheduler The scheduler control instance. + * @param thread Thread correspoding to the @node. + * @param node node which is to be unblocked + * @see _Scheduler_strong_APA_Enqueue() + * @see _Scheduler_strong_APA_Do_update() + */ void _Scheduler_strong_APA_Unblock( const Scheduler_Control *scheduler, - Thread_Control *the_thread, + Thread_Control *thread, Scheduler_Node *node ) { @@ -291,19 +640,29 @@ void _Scheduler_strong_APA_Unblock( _Scheduler_SMP_Unblock( context, - the_thread, + thread, node, _Scheduler_strong_APA_Do_update, _Scheduler_strong_APA_Enqueue ); } -static bool _Scheduler_strong_APA_Do_ask_for_help( - Scheduler_Context *context, - Thread_Control *the_thread, - Scheduler_Node *node +/** + * @brief Calls the smp Ask_for_help + * + * + * @param scheduler The scheduler control instance. + * @param thread Thread correspoding to the @node that asks for help. + * @param node node associated with @thread + */ +bool _Scheduler_strong_APA_Ask_for_help( + const Scheduler_Control *scheduler, + Thread_Control *the_thread, + Scheduler_Node *node ) { + Scheduler_Context *context = _Scheduler_Get_context( scheduler ); + return _Scheduler_SMP_Ask_for_help( context, the_thread, @@ -312,14 +671,21 @@ static bool _Scheduler_strong_APA_Do_ask_for_help( _Scheduler_strong_APA_Insert_ready, _Scheduler_SMP_Insert_scheduled, _Scheduler_strong_APA_Move_from_scheduled_to_ready, - _Scheduler_SMP_Get_lowest_scheduled, - _Scheduler_SMP_Allocate_processor_lazy + _Scheduler_strong_APA_Get_lowest_scheduled, + _Scheduler_strong_APA_Allocate_processor ); } +/** + * @brief Updates the priority of the node + * + * @param scheduler The scheduler control instance. + * @param thread Thread correspoding to the @node. + * @param node Node whose priority has to be updated + */ void _Scheduler_strong_APA_Update_priority( const Scheduler_Control *scheduler, - Thread_Control *the_thread, + Thread_Control *thread, Scheduler_Node *node ) { @@ -327,27 +693,23 @@ void _Scheduler_strong_APA_Update_priority( _Scheduler_SMP_Update_priority( context, - the_thread, + thread, node, _Scheduler_strong_APA_Extract_from_ready, _Scheduler_strong_APA_Do_update, _Scheduler_strong_APA_Enqueue, _Scheduler_strong_APA_Enqueue_scheduled, - _Scheduler_strong_APA_Do_ask_for_help + _Scheduler_strong_APA_Ask_for_help ); } - -bool _Scheduler_strong_APA_Ask_for_help( - const Scheduler_Control *scheduler, - Thread_Control *the_thread, - Scheduler_Node *node -) -{ - Scheduler_Context *context = _Scheduler_Get_context( scheduler ); - - return _Scheduler_strong_APA_Do_ask_for_help( context, the_thread, node ); -} - +/** + * @brief To Reconsider the help request + * + * @param scheduler The scheduler control instance. + * @param thread Thread correspoding to the @node. + * @param node Node corresponding to @thread which asks for + * reconsideration + */ void _Scheduler_strong_APA_Reconsider_help_request( const Scheduler_Control *scheduler, Thread_Control *the_thread, @@ -364,6 +726,14 @@ void _Scheduler_strong_APA_Reconsider_help_request( ); } +/** + * @brief Withdraws a node + * + * @param scheduler The scheduler control instance. + * @param thread Thread correspoding to the @node. + * @param node Node that has to be withdrawn + * @param next_state the state that the node goes to + */ void _Scheduler_strong_APA_Withdraw_node( const Scheduler_Control *scheduler, Thread_Control *the_thread, @@ -381,10 +751,38 @@ void _Scheduler_strong_APA_Withdraw_node( _Scheduler_strong_APA_Extract_from_ready, _Scheduler_strong_APA_Get_highest_ready, _Scheduler_strong_APA_Move_from_ready_to_scheduled, - _Scheduler_SMP_Allocate_processor_lazy + _Scheduler_strong_APA_Allocate_processor ); } +/** + * @brief To register an idle thread on a cpu + * + * For compatibility with SMP functions, + * does nothing in our implementation + */ +void _Scheduler_strong_APA_Register_idle( + Scheduler_Context *context, + Scheduler_Node *idle_base, + Per_CPU_Control *cpu +) +{ + (void) context; + (void) idle_base; + (void) cpu; + //We do not maintain a variable to access the scheduled + //node for a CPU. So this function does nothing. +} + +/** + * @brief Adds a processor to the scheduler instance + * + * and allocates an idle thread to the processor. + * + * @param scheduler The scheduler control instance. + * @param idle Idle thread to be allocated to the processor + * + */ void _Scheduler_strong_APA_Add_processor( const Scheduler_Control *scheduler, Thread_Control *idle @@ -397,10 +795,18 @@ void _Scheduler_strong_APA_Add_processor( idle, _Scheduler_strong_APA_Has_ready, _Scheduler_strong_APA_Enqueue_scheduled, - _Scheduler_SMP_Do_nothing_register_idle + _Scheduler_strong_APA_Register_idle ); } + +/** + * @brief Removes a processor from the scheduler instance + * + * @param scheduler The scheduler control instance. + * @param cpu processor that is removed + * + */ Thread_Control *_Scheduler_strong_APA_Remove_processor( const Scheduler_Control *scheduler, Per_CPU_Control *cpu @@ -416,9 +822,18 @@ Thread_Control *_Scheduler_strong_APA_Remove_processor( ); } + +/** + * @brief Called when a node yields the processor + * + * @param scheduler The scheduler control instance. + * @param thread Thread corresponding to @node + * @param node Node that yield the processor + * + */ void _Scheduler_strong_APA_Yield( const Scheduler_Control *scheduler, - Thread_Control *the_thread, + Thread_Control *thread, Scheduler_Node *node ) { @@ -426,10 +841,179 @@ void _Scheduler_strong_APA_Yield( _Scheduler_SMP_Yield( context, - the_thread, + thread, node, _Scheduler_strong_APA_Extract_from_ready, _Scheduler_strong_APA_Enqueue, _Scheduler_strong_APA_Enqueue_scheduled ); } + +/** + * @brief Called by _Scheduler_strong_APA_Set_affinity() + * + */ +void _Scheduler_strong_APA_Do_set_affinity( + Scheduler_Context *context, + Scheduler_Node *node_base, + void *arg +) +{ + Scheduler_strong_APA_Node *node; + const Processor_mask *affinity; + + node = _Scheduler_strong_APA_Node_downcast( node_base ); + affinity = arg; + node->affinity = *affinity; +} + +/** + * @brief Starts an idle thread on a CPU + * + * @param scheduler The scheduler control instance. + * @param idle Idle Thread + * @param cpu processor that gets the idle thread + * + */ +void _Scheduler_strong_APA_Start_idle( + const Scheduler_Control *scheduler, + Thread_Control *idle, + Per_CPU_Control *cpu +) +{ + Scheduler_Context *context; + + context = _Scheduler_Get_context( scheduler ); + + _Scheduler_SMP_Do_start_idle( + context, + idle, + cpu, + _Scheduler_strong_APA_Register_idle + ); +} + +/** + * @brief Pins a node to a cpu + * + * @param scheduler The scheduler control instance. + * @param thread Thread corresponding to @node + * @param node_base node which gets pinned + * @param cpu processor that the node gets pinned to + * + */ +void _Scheduler_strong_APA_Pin( + const Scheduler_Control *scheduler, + Thread_Control *thread, + Scheduler_Node *node_base, + struct Per_CPU_Control *cpu +) +{ + Scheduler_strong_APA_Node *node; + uint32_t pin_cpu; + + (void) scheduler; + node = _Scheduler_strong_APA_Node_downcast( node_base ); + pin_cpu = (uint32_t) _Per_CPU_Get_index( cpu ); + + _Assert( + _Scheduler_SMP_Node_state( &node->Base.Base ) == SCHEDULER_SMP_NODE_BLOCKED + ); + + node = _Scheduler_strong_APA_Node_downcast( node_base ); + + _Processor_mask_Zero( &node->affinity ); + _Processor_mask_Set( &node->affinity, pin_cpu ); +} + +/** + * @brief Unpins a node + * + * and sets it affinity back to normal. + * + * @param scheduler The scheduler control instance. + * @param thread Thread corresponding to @node + * @param node_base node which gets unpinned + * @param cpu processor that the node gets unpinned from : UNUSED + * + */ +void _Scheduler_strong_APA_Unpin( + const Scheduler_Control *scheduler, + Thread_Control *thread, + Scheduler_Node *node_base, + struct Per_CPU_Control *cpu +) +{ + Scheduler_strong_APA_Node *node; + + (void) scheduler; + (void) cpu; + node = _Scheduler_strong_APA_Node_downcast( node_base ); + + _Assert( + _Scheduler_SMP_Node_state( &node->Base.Base ) == SCHEDULER_SMP_NODE_BLOCKED + ); + + _Processor_mask_Zero( &node->affinity ); + _Processor_mask_Assign( &node->affinity, &node->unpin_affinity ); +} + +/** + * @brief Checks if the processor set of the scheduler is the subset of the affinity set. + * + * Default implementation of the set affinity scheduler operation. + * + * @param scheduler This parameter is unused. + * @param thread This parameter is unused. + * @param node This parameter is unused. + * @param affinity The new processor affinity set for the thread. + * + * @see _Scheduler_strong_APA_Do_set_affinity() + * + * @retval true The processor set of the scheduler is a subset of the affinity set. + * @retval false The processor set of the scheduler is not a subset of the affinity set. + */ +bool _Scheduler_strong_APA_Set_affinity( + const Scheduler_Control *scheduler, + Thread_Control *thread, + Scheduler_Node *node_base, + const Processor_mask *affinity +) +{ + Scheduler_Context *context; + Scheduler_strong_APA_Node *node; + Processor_mask local_affinity; + + context = _Scheduler_Get_context( scheduler ); + _Processor_mask_And( &local_affinity, &context->Processors, affinity ); + + if ( _Processor_mask_Is_zero( &local_affinity ) ) { + return false; + } + + node = _Scheduler_strong_APA_Node_downcast( node_base ); + + if ( _Processor_mask_Is_equal( &node->affinity, affinity ) ) + return true; //Nothing to do. Return true. + + _Processor_mask_Zero( &node->affinity ); + _Processor_mask_Zero( &node->unpin_affinity ); + + _Processor_mask_Assign( &node->affinity, &local_affinity ); + _Processor_mask_Assign( &node->unpin_affinity, &local_affinity ); + + _Scheduler_SMP_Set_affinity( + context, + thread, + node_base, + &local_affinity, + _Scheduler_strong_APA_Do_set_affinity, + _Scheduler_strong_APA_Extract_from_ready, + _Scheduler_strong_APA_Get_highest_ready, + _Scheduler_strong_APA_Move_from_ready_to_scheduled, + _Scheduler_strong_APA_Enqueue, + _Scheduler_strong_APA_Allocate_processor + ); + + return true; +} From 8731311060a877a860fe6a64820fbb354f20dfc0 Mon Sep 17 00:00:00 2001 From: richidubey Date: Mon, 27 Jul 2020 14:00:23 +0530 Subject: [PATCH 2/9] Removed all compilation errors --- .../include/rtems/score/schedulerstrongapa.h | 14 +- cpukit/score/src/schedulerstrongapa.h | 310 ++++++++++++++++++ 2 files changed, 311 insertions(+), 13 deletions(-) create mode 100644 cpukit/score/src/schedulerstrongapa.h diff --git a/cpukit/include/rtems/score/schedulerstrongapa.h b/cpukit/include/rtems/score/schedulerstrongapa.h index 4ddae3235a4..eaef8873df8 100644 --- a/cpukit/include/rtems/score/schedulerstrongapa.h +++ b/cpukit/include/rtems/score/schedulerstrongapa.h @@ -6,25 +6,13 @@ * @brief Strong APA Scheduler API */ -/* - * Copyright (c) 2013, 2018 embedded brains GmbH. All rights reserved. - * - * embedded brains GmbH - * Dornierstr. 4 - * 82178 Puchheim - * Germany - * - * - * 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_SCHEDULERSTRONGAPA_H #define _RTEMS_SCORE_SCHEDULERSTRONGAPA_H #include #include +#include #ifdef __cplusplus extern "C" { diff --git a/cpukit/score/src/schedulerstrongapa.h b/cpukit/score/src/schedulerstrongapa.h new file mode 100644 index 00000000000..eaef8873df8 --- /dev/null +++ b/cpukit/score/src/schedulerstrongapa.h @@ -0,0 +1,310 @@ +/** + * @file + * + * @ingroup RTEMSScoreSchedulerStrongAPA + * + * @brief Strong APA Scheduler API + */ + + +#ifndef _RTEMS_SCORE_SCHEDULERSTRONGAPA_H +#define _RTEMS_SCORE_SCHEDULERSTRONGAPA_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup RTEMSScoreSchedulerStrongAPA Strong APA Scheduler + * + * @ingroup RTEMSScoreSchedulerSMP + * + * @brief Strong APA Scheduler + * + * This is an implementation of the Strong APA scheduler defined by + * Bradenbug et. al in Linux's Processor Affinity API, Refined: Shifting Real-Time Tasks Towards Higher Schedulability. + * + * @{ + */ + + /** + * @brief Scheduler context for Strong APA + * scheduler. + * + * Has the structure for scheduler context + * and Node defintion for Strong APA scheduler + */ +typedef struct { + /** + * @brief SMP Context to refer to SMP implementation + * code. + */ + Scheduler_SMP_Context Base; + + /** + * @brief Chain of all the nodes present in + * the system. Accounts for ready and scheduled nodes. + */ + Chain_Control allNodes; + +} Scheduler_strong_APA_Context; + +/** + * @brief Scheduler node specialization for Strong APA + * schedulers. + */ +typedef struct { + /** + * @brief Chain node for + * Scheduler_strong_APA_Context::allNodes + * + */ + Chain_Node Node; + + /** + * @brief SMP scheduler node. + */ + Scheduler_SMP_Node Base; + + /** + * @brief The associated affinity set of this node. + */ + Processor_mask affinity; + + /** + * @brief The associated affinity set of this node + * to be used while unpinning the node. + */ + Processor_mask unpin_affinity; + +} Scheduler_strong_APA_Node; + +/** + * @brief CPU structure to be used + * while traversing in the FIFO Queue + */ +typedef struct CPU +{ + /** + * @brief Chain node for + * _Scheduler_strong_APA_Get_highest_ready::Queue + * and _Scheduler_strong_APA_Get_lowest_scheduled::Queue + */ + Chain_Node node; + + /** + * @brief cpu associated with the node + */ + Per_CPU_Control cpu; + +}CPU; + +/** + * @brief Entry points for the Strong APA Scheduler. + */ +#define SCHEDULER_STRONG_APA_ENTRY_POINTS \ + { \ + _Scheduler_strong_APA_Initialize, \ + _Scheduler_default_Schedule, \ + _Scheduler_strong_APA_Yield, \ + _Scheduler_strong_APA_Block, \ + _Scheduler_strong_APA_Unblock, \ + _Scheduler_strong_APA_Update_priority, \ + _Scheduler_default_Map_priority, \ + _Scheduler_default_Unmap_priority, \ + _Scheduler_strong_APA_Ask_for_help, \ + _Scheduler_strong_APA_Reconsider_help_request, \ + _Scheduler_strong_APA_Withdraw_node, \ + _Scheduler_strong_APA_Pin, \ + _Scheduler_strong_APA_Unpin, \ + _Scheduler_strong_APA_Add_processor, \ + _Scheduler_strong_APA_Remove_processor, \ + _Scheduler_strong_APA_Node_initialize, \ + _Scheduler_default_Node_destroy, \ + _Scheduler_default_Release_job, \ + _Scheduler_default_Cancel_job, \ + _Scheduler_default_Tick, \ + _Scheduler_strong_APA_Start_idle \ + _Scheduler_strong_APA_Set_affinity \ + } + +void _Scheduler_strong_APA_Initialize( + const Scheduler_Control *scheduler + ); + + +void _Scheduler_strong_APA_Node_initialize( + const Scheduler_Control *scheduler, + Scheduler_Node *node, + Thread_Control *the_thread, + Priority_Control priority +); + +void _Scheduler_strong_APA_Do_update( + Scheduler_Context *context, + Scheduler_Node *node, + Priority_Control new_priority +); + +bool _Scheduler_strong_APA_Has_ready( + Scheduler_Context *context + ); + +Scheduler_Node *_Scheduler_strong_APA_Get_highest_ready( + Scheduler_Context *context, + Scheduler_Node *filter +); + +Scheduler_Node *_Scheduler_strong_APA_Get_lowest_scheduled( + Scheduler_Context *context, + Scheduler_Node *filter_base +); + +void _Scheduler_strong_APA_Extract_from_scheduled( + Scheduler_Context *context, + Scheduler_Node *node_to_extract +); + +void _Scheduler_strong_APA_Extract_from_ready( + Scheduler_Context *context, + Scheduler_Node *node_to_extract +); + +void _Scheduler_strong_APA_Move_from_scheduled_to_ready( + Scheduler_Context *context, + Scheduler_Node *scheduled_to_ready +); + +void _Scheduler_strong_APA_Move_from_ready_to_scheduled( + Scheduler_Context *context, + Scheduler_Node *ready_to_scheduled +); + +void _Scheduler_strong_APA_Insert_ready( + Scheduler_Context *context, + Scheduler_Node *node_base, + Priority_Control insert_priority +); + +void _Scheduler_strong_APA_Allocate_processor( + Scheduler_Context *context, + Scheduler_Node *scheduled_base, + Scheduler_Node *victim_base, + Per_CPU_Control *victim_cpu +); + +void _Scheduler_strong_APA_Block( + const Scheduler_Control *scheduler, + Thread_Control *thread, + Scheduler_Node *node +); + +bool _Scheduler_strong_APA_Enqueue( + Scheduler_Context *context, + Scheduler_Node *node, + Priority_Control insert_priority +); + +bool _Scheduler_strong_APA_Enqueue_scheduled( + Scheduler_Context *context, + Scheduler_Node *node, + Priority_Control insert_priority +); + +void _Scheduler_strong_APA_Unblock( + const Scheduler_Control *scheduler, + Thread_Control *thread, + Scheduler_Node *node +); + +bool _Scheduler_strong_APA_Ask_for_help( + const Scheduler_Control *scheduler, + Thread_Control *the_thread, + Scheduler_Node *node +); + +void _Scheduler_strong_APA_Update_priority( + const Scheduler_Control *scheduler, + Thread_Control *thread, + Scheduler_Node *node +); + +void _Scheduler_strong_APA_Reconsider_help_request( + const Scheduler_Control *scheduler, + Thread_Control *the_thread, + Scheduler_Node *node +); + +void _Scheduler_strong_APA_Withdraw_node( + const Scheduler_Control *scheduler, + Thread_Control *the_thread, + Scheduler_Node *node, + Thread_Scheduler_state next_state +); + +void _Scheduler_strong_APA_Register_idle( + Scheduler_Context *context, + Scheduler_Node *idle_base, + Per_CPU_Control *cpu +); + +void _Scheduler_strong_APA_Add_processor( + const Scheduler_Control *scheduler, + Thread_Control *idle +); + +Thread_Control *_Scheduler_strong_APA_Remove_processor( + const Scheduler_Control *scheduler, + Per_CPU_Control *cpu +); + +void _Scheduler_strong_APA_Yield( + const Scheduler_Control *scheduler, + Thread_Control *thread, + Scheduler_Node *node +); + +void _Scheduler_strong_APA_Do_set_affinity( + Scheduler_Context *context, + Scheduler_Node *node_base, + void *arg +); + +void _Scheduler_strong_APA_Start_idle( + const Scheduler_Control *scheduler, + Thread_Control *idle, + Per_CPU_Control *cpu +); + +void _Scheduler_strong_APA_Pin( + const Scheduler_Control *scheduler, + Thread_Control *thread, + Scheduler_Node *node_base, + struct Per_CPU_Control *cpu +); + +void _Scheduler_strong_APA_Unpin( + const Scheduler_Control *scheduler, + Thread_Control *thread, + Scheduler_Node *node_base, + struct Per_CPU_Control *cpu +); + +bool _Scheduler_strong_APA_Set_affinity( + const Scheduler_Control *scheduler, + Thread_Control *thread, + Scheduler_Node *node_base, + const Processor_mask *affinity +); + +/** @} */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _RTEMS_SCORE_SCHEDULERSTRONGAPA_H */ From 3a9843f61bbd547d150d2ee2d791668cfb5aa282 Mon Sep 17 00:00:00 2001 From: richidubey Date: Mon, 27 Jul 2020 14:01:46 +0530 Subject: [PATCH 3/9] Removed file from wrong place --- cpukit/score/src/schedulerstrongapa.h | 310 -------------------------- 1 file changed, 310 deletions(-) delete mode 100644 cpukit/score/src/schedulerstrongapa.h diff --git a/cpukit/score/src/schedulerstrongapa.h b/cpukit/score/src/schedulerstrongapa.h deleted file mode 100644 index eaef8873df8..00000000000 --- a/cpukit/score/src/schedulerstrongapa.h +++ /dev/null @@ -1,310 +0,0 @@ -/** - * @file - * - * @ingroup RTEMSScoreSchedulerStrongAPA - * - * @brief Strong APA Scheduler API - */ - - -#ifndef _RTEMS_SCORE_SCHEDULERSTRONGAPA_H -#define _RTEMS_SCORE_SCHEDULERSTRONGAPA_H - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/** - * @defgroup RTEMSScoreSchedulerStrongAPA Strong APA Scheduler - * - * @ingroup RTEMSScoreSchedulerSMP - * - * @brief Strong APA Scheduler - * - * This is an implementation of the Strong APA scheduler defined by - * Bradenbug et. al in Linux's Processor Affinity API, Refined: Shifting Real-Time Tasks Towards Higher Schedulability. - * - * @{ - */ - - /** - * @brief Scheduler context for Strong APA - * scheduler. - * - * Has the structure for scheduler context - * and Node defintion for Strong APA scheduler - */ -typedef struct { - /** - * @brief SMP Context to refer to SMP implementation - * code. - */ - Scheduler_SMP_Context Base; - - /** - * @brief Chain of all the nodes present in - * the system. Accounts for ready and scheduled nodes. - */ - Chain_Control allNodes; - -} Scheduler_strong_APA_Context; - -/** - * @brief Scheduler node specialization for Strong APA - * schedulers. - */ -typedef struct { - /** - * @brief Chain node for - * Scheduler_strong_APA_Context::allNodes - * - */ - Chain_Node Node; - - /** - * @brief SMP scheduler node. - */ - Scheduler_SMP_Node Base; - - /** - * @brief The associated affinity set of this node. - */ - Processor_mask affinity; - - /** - * @brief The associated affinity set of this node - * to be used while unpinning the node. - */ - Processor_mask unpin_affinity; - -} Scheduler_strong_APA_Node; - -/** - * @brief CPU structure to be used - * while traversing in the FIFO Queue - */ -typedef struct CPU -{ - /** - * @brief Chain node for - * _Scheduler_strong_APA_Get_highest_ready::Queue - * and _Scheduler_strong_APA_Get_lowest_scheduled::Queue - */ - Chain_Node node; - - /** - * @brief cpu associated with the node - */ - Per_CPU_Control cpu; - -}CPU; - -/** - * @brief Entry points for the Strong APA Scheduler. - */ -#define SCHEDULER_STRONG_APA_ENTRY_POINTS \ - { \ - _Scheduler_strong_APA_Initialize, \ - _Scheduler_default_Schedule, \ - _Scheduler_strong_APA_Yield, \ - _Scheduler_strong_APA_Block, \ - _Scheduler_strong_APA_Unblock, \ - _Scheduler_strong_APA_Update_priority, \ - _Scheduler_default_Map_priority, \ - _Scheduler_default_Unmap_priority, \ - _Scheduler_strong_APA_Ask_for_help, \ - _Scheduler_strong_APA_Reconsider_help_request, \ - _Scheduler_strong_APA_Withdraw_node, \ - _Scheduler_strong_APA_Pin, \ - _Scheduler_strong_APA_Unpin, \ - _Scheduler_strong_APA_Add_processor, \ - _Scheduler_strong_APA_Remove_processor, \ - _Scheduler_strong_APA_Node_initialize, \ - _Scheduler_default_Node_destroy, \ - _Scheduler_default_Release_job, \ - _Scheduler_default_Cancel_job, \ - _Scheduler_default_Tick, \ - _Scheduler_strong_APA_Start_idle \ - _Scheduler_strong_APA_Set_affinity \ - } - -void _Scheduler_strong_APA_Initialize( - const Scheduler_Control *scheduler - ); - - -void _Scheduler_strong_APA_Node_initialize( - const Scheduler_Control *scheduler, - Scheduler_Node *node, - Thread_Control *the_thread, - Priority_Control priority -); - -void _Scheduler_strong_APA_Do_update( - Scheduler_Context *context, - Scheduler_Node *node, - Priority_Control new_priority -); - -bool _Scheduler_strong_APA_Has_ready( - Scheduler_Context *context - ); - -Scheduler_Node *_Scheduler_strong_APA_Get_highest_ready( - Scheduler_Context *context, - Scheduler_Node *filter -); - -Scheduler_Node *_Scheduler_strong_APA_Get_lowest_scheduled( - Scheduler_Context *context, - Scheduler_Node *filter_base -); - -void _Scheduler_strong_APA_Extract_from_scheduled( - Scheduler_Context *context, - Scheduler_Node *node_to_extract -); - -void _Scheduler_strong_APA_Extract_from_ready( - Scheduler_Context *context, - Scheduler_Node *node_to_extract -); - -void _Scheduler_strong_APA_Move_from_scheduled_to_ready( - Scheduler_Context *context, - Scheduler_Node *scheduled_to_ready -); - -void _Scheduler_strong_APA_Move_from_ready_to_scheduled( - Scheduler_Context *context, - Scheduler_Node *ready_to_scheduled -); - -void _Scheduler_strong_APA_Insert_ready( - Scheduler_Context *context, - Scheduler_Node *node_base, - Priority_Control insert_priority -); - -void _Scheduler_strong_APA_Allocate_processor( - Scheduler_Context *context, - Scheduler_Node *scheduled_base, - Scheduler_Node *victim_base, - Per_CPU_Control *victim_cpu -); - -void _Scheduler_strong_APA_Block( - const Scheduler_Control *scheduler, - Thread_Control *thread, - Scheduler_Node *node -); - -bool _Scheduler_strong_APA_Enqueue( - Scheduler_Context *context, - Scheduler_Node *node, - Priority_Control insert_priority -); - -bool _Scheduler_strong_APA_Enqueue_scheduled( - Scheduler_Context *context, - Scheduler_Node *node, - Priority_Control insert_priority -); - -void _Scheduler_strong_APA_Unblock( - const Scheduler_Control *scheduler, - Thread_Control *thread, - Scheduler_Node *node -); - -bool _Scheduler_strong_APA_Ask_for_help( - const Scheduler_Control *scheduler, - Thread_Control *the_thread, - Scheduler_Node *node -); - -void _Scheduler_strong_APA_Update_priority( - const Scheduler_Control *scheduler, - Thread_Control *thread, - Scheduler_Node *node -); - -void _Scheduler_strong_APA_Reconsider_help_request( - const Scheduler_Control *scheduler, - Thread_Control *the_thread, - Scheduler_Node *node -); - -void _Scheduler_strong_APA_Withdraw_node( - const Scheduler_Control *scheduler, - Thread_Control *the_thread, - Scheduler_Node *node, - Thread_Scheduler_state next_state -); - -void _Scheduler_strong_APA_Register_idle( - Scheduler_Context *context, - Scheduler_Node *idle_base, - Per_CPU_Control *cpu -); - -void _Scheduler_strong_APA_Add_processor( - const Scheduler_Control *scheduler, - Thread_Control *idle -); - -Thread_Control *_Scheduler_strong_APA_Remove_processor( - const Scheduler_Control *scheduler, - Per_CPU_Control *cpu -); - -void _Scheduler_strong_APA_Yield( - const Scheduler_Control *scheduler, - Thread_Control *thread, - Scheduler_Node *node -); - -void _Scheduler_strong_APA_Do_set_affinity( - Scheduler_Context *context, - Scheduler_Node *node_base, - void *arg -); - -void _Scheduler_strong_APA_Start_idle( - const Scheduler_Control *scheduler, - Thread_Control *idle, - Per_CPU_Control *cpu -); - -void _Scheduler_strong_APA_Pin( - const Scheduler_Control *scheduler, - Thread_Control *thread, - Scheduler_Node *node_base, - struct Per_CPU_Control *cpu -); - -void _Scheduler_strong_APA_Unpin( - const Scheduler_Control *scheduler, - Thread_Control *thread, - Scheduler_Node *node_base, - struct Per_CPU_Control *cpu -); - -bool _Scheduler_strong_APA_Set_affinity( - const Scheduler_Control *scheduler, - Thread_Control *thread, - Scheduler_Node *node_base, - const Processor_mask *affinity -); - -/** @} */ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* _RTEMS_SCORE_SCHEDULERSTRONGAPA_H */ From af96cca61c755e0470497e2401a7cd0a1a9b1821 Mon Sep 17 00:00:00 2001 From: richidubey Date: Mon, 27 Jul 2020 17:52:21 +0530 Subject: [PATCH 4/9] Corrected Assert Statements --- cpukit/score/src/schedulerstrongapa.c | 84 ++++++++++++++------------- 1 file changed, 43 insertions(+), 41 deletions(-) diff --git a/cpukit/score/src/schedulerstrongapa.c b/cpukit/score/src/schedulerstrongapa.c index c26c2488566..7c5077e9729 100644 --- a/cpukit/score/src/schedulerstrongapa.c +++ b/cpukit/score/src/schedulerstrongapa.c @@ -5,20 +5,6 @@ * * @brief Strong APA Scheduler Implementation */ - -/* - * Copyright (c) 2013, 2016 embedded brains GmbH. All rights reserved. - * - * embedded brains GmbH - * Dornierstr. 4 - * 82178 Puchheim - * Germany - * - * - * 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. - */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -26,6 +12,8 @@ #include #include +#include +#include static inline Scheduler_strong_APA_Context * _Scheduler_strong_APA_Get_context( const Scheduler_Control *scheduler ) @@ -103,7 +91,6 @@ void _Scheduler_strong_APA_Do_update( ) { Scheduler_SMP_Node *smp_node; - (void) context; smp_node = _Scheduler_SMP_Node_downcast( node ); @@ -192,9 +179,8 @@ Scheduler_Node *_Scheduler_strong_APA_Get_highest_ready( _Chain_Initialize_empty(&Queue); - Qcpu = malloc( sizeof(CPU) ); - assert (Qcpu != NULL); //Should it be NULL? - Qcpu->cpu=thread_cpu; + Qcpu = rtems_malloc( sizeof(CPU) ); //Does not return any errornum on failure + Qcpu->cpu=*thread_cpu; _Chain_Initialize_node( &Qcpu->node ); _Chain_Append_unprotected( &Queue, &Qcpu->node ); //Insert thread_CPU in the Queue @@ -203,7 +189,7 @@ Scheduler_Node *_Scheduler_strong_APA_Get_highest_ready( while( !_Chain_Is_empty( &Queue) ) { Qcpu = (CPU*) _Chain_Get_first_unprotected( &Queue ); - curr_CPU = Qcpu->cpu; + curr_CPU = &Qcpu->cpu; tail = _Chain_Immutable_tail( &self->allNodes ); next = _Chain_First( &self->allNodes ); @@ -211,7 +197,7 @@ Scheduler_Node *_Scheduler_strong_APA_Get_highest_ready( Scheduler_strong_APA_Node *node; node = (Scheduler_strong_APA_Node *) next; - if( node->affinity & (1 << _Per_CPU_Get_index( curr_CPU ) ) ) { + if( _Processor_mask_Is_set( &node->affinity, _Per_CPU_Get_index( curr_CPU ) ) ) { //Checks if the thread_CPU is in the affinity set of the node if(_Scheduler_SMP_Node_state( &node->Base.Base ) @@ -220,8 +206,8 @@ Scheduler_Node *_Scheduler_strong_APA_Get_highest_ready( assigned_cpu = _Thread_Get_CPU( node->Base.Base.user ); if(visited[ _Per_CPU_Get_index( assigned_cpu ) ] == false) { - Qcpu = malloc( sizeof(CPU) ); - assert (Qcpu != NULL); //Should it be NULL? + Qcpu = rtems_malloc( sizeof(CPU) ); + //rtems_malloc does not return a errnum in case of failure Qcpu->cpu=*assigned_cpu; _Chain_Initialize_node( &Qcpu->node ); @@ -289,6 +275,10 @@ Scheduler_Node *_Scheduler_strong_APA_Get_lowest_scheduled( Scheduler_strong_APA_Node *Scurr_node; //Current Strong_APA_Node Scheduler_strong_APA_Node *filter_node; + + ret=NULL; //To remove compiler warning. + //ret would always point to the node with the lowest priority + //node unless the affinity of filter_base is NULL. filter_node = _Scheduler_strong_APA_Node_downcast( filter_base ); @@ -298,12 +288,12 @@ Scheduler_Node *_Scheduler_strong_APA_Get_lowest_scheduled( _Chain_Initialize_empty(&Queue); for ( cpu_index = 0 ; cpu_index < cpu_max ; ++cpu_index ) { - if( ( filter_node->affinity & (1<affinity , cpu_index) + && visited[ cpu_index ] == false ) ) { //Checks if the thread_CPU is in the affinity set of the node Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index ); if( _Per_CPU_Is_processor_online( cpu ) ) { - Qcpu = malloc( sizeof(CPU) ); - assert (Qcpu != NULL); //Should it be NULL? + Qcpu = rtems_malloc( sizeof(CPU) ); //No errornum returned in case of failure Qcpu->cpu=*cpu; _Chain_Initialize_node( &Qcpu->node ); @@ -335,13 +325,12 @@ Scheduler_Node *_Scheduler_strong_APA_Get_lowest_scheduled( Scurr_node = _Scheduler_strong_APA_Node_downcast( curr_node ); if( !curr_thread->is_idle ) { for ( cpu_index = 0 ; cpu_index < cpu_max ; ++cpu_index ) { - if( ( Scurr_node->affinity & (1<affinity , cpu_index ) ) { //Checks if the thread_CPU is in the affinity set of the node Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index ); if( _Per_CPU_Is_processor_online( cpu ) && visited[ cpu_index ] == false ) { - Qcpu = malloc( sizeof(CPU) ); - assert (Qcpu != NULL); //Should it be NULL? + Qcpu = rtems_malloc( sizeof(CPU) ); Qcpu->cpu=*cpu; _Chain_Initialize_node( &Qcpu->node ); @@ -369,7 +358,6 @@ Scheduler_Node *_Scheduler_strong_APA_Get_lowest_scheduled( //Backtrack on the path from //_Thread_Get_CPU(ret->user) to ret, shifting along every task } - return ret; } @@ -415,8 +403,8 @@ void _Scheduler_strong_APA_Extract_from_ready( self = _Scheduler_strong_APA_Get_self( context ); node = _Scheduler_strong_APA_Node_downcast( node_to_extract ); - _Assert( _Chain_Is_empty(self->allNodes) == false ); - _Assert( _Chain_Is_node_off_chain( &node->Node ) == false ); + _Assert( !_Chain_Is_empty(self->allNodes) ); + _Assert( !_Chain_Is_node_off_chain( &node->Node ) ); _Chain_Extract_unprotected( &node->Node ); //Removed from allNodes _Chain_Set_off_chain( &node->Node ); @@ -499,7 +487,7 @@ void _Scheduler_strong_APA_Insert_ready( self = _Scheduler_strong_APA_Get_self( context ); node = _Scheduler_strong_APA_Node_downcast( node_base ); - _Assert( _Chain_Is_node_off_chain( &node->Node ) == true ); + _Assert( !_Chain_Is_node_off_chain( &node->Node ) ); _Chain_Append_unprotected( &self->allNodes, &node->Node ); } @@ -647,6 +635,25 @@ void _Scheduler_strong_APA_Unblock( ); } +static inline bool _Scheduler_strong_APA_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_Priority_less_equal, + _Scheduler_strong_APA_Insert_ready, + _Scheduler_SMP_Insert_scheduled, + _Scheduler_strong_APA_Move_from_scheduled_to_ready, + _Scheduler_strong_APA_Get_lowest_scheduled, + _Scheduler_strong_APA_Allocate_processor + ); +} + /** * @brief Calls the smp Ask_for_help * @@ -663,19 +670,14 @@ bool _Scheduler_strong_APA_Ask_for_help( { Scheduler_Context *context = _Scheduler_Get_context( scheduler ); - return _Scheduler_SMP_Ask_for_help( + return _Scheduler_strong_APA_Do_ask_for_help( context, the_thread, - node, - _Scheduler_SMP_Priority_less_equal, - _Scheduler_strong_APA_Insert_ready, - _Scheduler_SMP_Insert_scheduled, - _Scheduler_strong_APA_Move_from_scheduled_to_ready, - _Scheduler_strong_APA_Get_lowest_scheduled, - _Scheduler_strong_APA_Allocate_processor + node ); } + /** * @brief Updates the priority of the node * @@ -699,7 +701,7 @@ void _Scheduler_strong_APA_Update_priority( _Scheduler_strong_APA_Do_update, _Scheduler_strong_APA_Enqueue, _Scheduler_strong_APA_Enqueue_scheduled, - _Scheduler_strong_APA_Ask_for_help + _Scheduler_strong_APA_Do_ask_for_help ); } /** From dfda77a4828b1e00d41ea6b7af53ddbbcffde346 Mon Sep 17 00:00:00 2001 From: richidubey Date: Tue, 28 Jul 2020 19:09:49 +0530 Subject: [PATCH 5/9] Removed all compiler errors --- cpukit/include/rtems/score/schedulerstrongapa.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpukit/include/rtems/score/schedulerstrongapa.h b/cpukit/include/rtems/score/schedulerstrongapa.h index eaef8873df8..ef3677ba893 100644 --- a/cpukit/include/rtems/score/schedulerstrongapa.h +++ b/cpukit/include/rtems/score/schedulerstrongapa.h @@ -128,7 +128,7 @@ typedef struct CPU _Scheduler_default_Release_job, \ _Scheduler_default_Cancel_job, \ _Scheduler_default_Tick, \ - _Scheduler_strong_APA_Start_idle \ + _Scheduler_strong_APA_Start_idle, \ _Scheduler_strong_APA_Set_affinity \ } From 66455b82afe405dbd5cc0ee3453eb72958f75dac Mon Sep 17 00:00:00 2001 From: richidubey Date: Thu, 30 Jul 2020 17:23:20 +0530 Subject: [PATCH 6/9] Resolving reviews on pull request --- .../include/rtems/score/schedulerstrongapa.h | 297 +++++---- cpukit/score/src/schedulerstrongapa.c | 594 ++++++------------ 2 files changed, 348 insertions(+), 543 deletions(-) diff --git a/cpukit/include/rtems/score/schedulerstrongapa.h b/cpukit/include/rtems/score/schedulerstrongapa.h index ef3677ba893..cae588a1570 100644 --- a/cpukit/include/rtems/score/schedulerstrongapa.h +++ b/cpukit/include/rtems/score/schedulerstrongapa.h @@ -6,7 +6,23 @@ * @brief Strong APA Scheduler API */ - +/* + * Copyright (c) 2013, 2018 embedded brains GmbH, 2020 Richi Dubey. + * All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * + * + * Richi Dubey: richidubey@gmail.com + * + * 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_SCHEDULERSTRONGAPA_H #define _RTEMS_SCORE_SCHEDULERSTRONGAPA_H @@ -26,14 +42,14 @@ extern "C" { * @brief Strong APA Scheduler * * This is an implementation of the Strong APA scheduler defined by - * Bradenbug et. al in Linux's Processor Affinity API, Refined: Shifting Real-Time Tasks Towards Higher Schedulability. + * Cerqueira et al. in Linux's Processor Affinity API, Refined: + * Shifting Real-Time Tasks Towards Higher Schedulability. * * @{ */ /** - * @brief Scheduler context for Strong APA - * scheduler. + * @brief Scheduler context for Strong APA scheduler. * * Has the structure for scheduler context * and Node defintion for Strong APA scheduler @@ -49,19 +65,15 @@ typedef struct { * @brief Chain of all the nodes present in * the system. Accounts for ready and scheduled nodes. */ - Chain_Control allNodes; - + Chain_Control all_nodes; } Scheduler_strong_APA_Context; /** - * @brief Scheduler node specialization for Strong APA - * schedulers. + * @brief Scheduler node specialization for Strong APA schedulers. */ typedef struct { /** - * @brief Chain node for - * Scheduler_strong_APA_Context::allNodes - * + * @brief Chain node for Scheduler_strong_APA_Context::allNodes */ Chain_Node Node; @@ -73,21 +85,18 @@ typedef struct { /** * @brief The associated affinity set of this node. */ - Processor_mask affinity; + Processor_mask Affinity; /** - * @brief The associated affinity set of this node - * to be used while unpinning the node. + * @brief The associated affinity set of this node to be used while unpinning the node. */ - Processor_mask unpin_affinity; - + Processor_mask Unpin_affinity; } Scheduler_strong_APA_Node; /** - * @brief CPU structure to be used - * while traversing in the FIFO Queue + * @brief CPU structure to be used while traversing in the FIFO Queue */ -typedef struct CPU +typedef struct Scheduler_strong_APA_CPU { /** * @brief Chain node for @@ -100,8 +109,7 @@ typedef struct CPU * @brief cpu associated with the node */ Per_CPU_Control cpu; - -}CPU; +}Scheduler_strong_APA_CPU; /** * @brief Entry points for the Strong APA Scheduler. @@ -132,113 +140,114 @@ typedef struct CPU _Scheduler_strong_APA_Set_affinity \ } +/** + * @brief Initializes the Strong_APA scheduler. + * + * Sets the chain containing all the nodes to empty + * and initializes the SMP scheduler. + * + * @param scheduler used to get reference to Strong APA scheduler context + * @retval void + * @see _Scheduler_strong_APA_Node_initialize() + */ void _Scheduler_strong_APA_Initialize( - const Scheduler_Control *scheduler - ); + const Scheduler_Control *scheduler +); - -void _Scheduler_strong_APA_Node_initialize( +/** + * @brief Called when a node yields the processor + * + * @param scheduler The scheduler control instance. + * @param thread Thread corresponding to @node + * @param node Node that yield the processor + */ +void _Scheduler_strong_APA_Yield( const Scheduler_Control *scheduler, - Scheduler_Node *node, - Thread_Control *the_thread, - Priority_Control priority -); - -void _Scheduler_strong_APA_Do_update( - Scheduler_Context *context, - Scheduler_Node *node, - Priority_Control new_priority -); - -bool _Scheduler_strong_APA_Has_ready( - Scheduler_Context *context - ); - -Scheduler_Node *_Scheduler_strong_APA_Get_highest_ready( - Scheduler_Context *context, - Scheduler_Node *filter -); - -Scheduler_Node *_Scheduler_strong_APA_Get_lowest_scheduled( - Scheduler_Context *context, - Scheduler_Node *filter_base -); - -void _Scheduler_strong_APA_Extract_from_scheduled( - Scheduler_Context *context, - Scheduler_Node *node_to_extract -); - -void _Scheduler_strong_APA_Extract_from_ready( - Scheduler_Context *context, - Scheduler_Node *node_to_extract -); - -void _Scheduler_strong_APA_Move_from_scheduled_to_ready( - Scheduler_Context *context, - Scheduler_Node *scheduled_to_ready -); - -void _Scheduler_strong_APA_Move_from_ready_to_scheduled( - Scheduler_Context *context, - Scheduler_Node *ready_to_scheduled -); - -void _Scheduler_strong_APA_Insert_ready( - Scheduler_Context *context, - Scheduler_Node *node_base, - Priority_Control insert_priority -); - -void _Scheduler_strong_APA_Allocate_processor( - Scheduler_Context *context, - Scheduler_Node *scheduled_base, - Scheduler_Node *victim_base, - Per_CPU_Control *victim_cpu + Thread_Control *thread, + Scheduler_Node *node ); +/** + * @brief Blocks a node + * + * Changes the state of the node and extracts it from the queue + * calls _Scheduler_SMP_Block(). + * + * @param context The scheduler control instance. + * @param thread Thread correspoding to the @node. + * @param node node which is to be blocked + */ void _Scheduler_strong_APA_Block( const Scheduler_Control *scheduler, Thread_Control *thread, Scheduler_Node *node ); -bool _Scheduler_strong_APA_Enqueue( - Scheduler_Context *context, - Scheduler_Node *node, - Priority_Control insert_priority -); - -bool _Scheduler_strong_APA_Enqueue_scheduled( - Scheduler_Context *context, - Scheduler_Node *node, - Priority_Control insert_priority -); - +/** + * @brief Unblocks a node + * + * Changes the state of the node and calls _Scheduler_SMP_Unblock(). + * + * @param scheduler The scheduler control instance. + * @param thread Thread correspoding to the @node. + * @param node node which is to be unblocked + * @see _Scheduler_strong_APA_Enqueue() + * @see _Scheduler_strong_APA_Do_update() + */ void _Scheduler_strong_APA_Unblock( const Scheduler_Control *scheduler, Thread_Control *thread, Scheduler_Node *node ); -bool _Scheduler_strong_APA_Ask_for_help( +/** + * @brief Updates the priority of the node + * + * @param scheduler The scheduler control instance. + * @param thread Thread correspoding to the @node. + * @param node Node whose priority has to be updated + */ +void _Scheduler_strong_APA_Update_priority( const Scheduler_Control *scheduler, - Thread_Control *the_thread, + Thread_Control *thread, Scheduler_Node *node ); -void _Scheduler_strong_APA_Update_priority( +/** + * @brief Calls the SMP Ask_for_help + * + * @param scheduler The scheduler control instance. + * @param thread Thread correspoding to the @node that asks for help. + * @param node node associated with @thread + */ +bool _Scheduler_strong_APA_Ask_for_help( const Scheduler_Control *scheduler, - Thread_Control *thread, + Thread_Control *the_thread, Scheduler_Node *node ); +/** + * @brief To Reconsider the help request + * + * @param scheduler The scheduler control instance. + * @param thread Thread correspoding to the @node. + * @param node Node corresponding to @thread which asks for + * reconsideration + */ void _Scheduler_strong_APA_Reconsider_help_request( const Scheduler_Control *scheduler, Thread_Control *the_thread, Scheduler_Node *node ); +/** + * @brief Withdraws a node + * + * @param scheduler The scheduler control instance. + * @param thread Thread correspoding to the @node. + * @param node Node that has to be withdrawn + * @param next_state the state that the node goes to + */ void _Scheduler_strong_APA_Withdraw_node( const Scheduler_Control *scheduler, Thread_Control *the_thread, @@ -246,61 +255,99 @@ void _Scheduler_strong_APA_Withdraw_node( Thread_Scheduler_state next_state ); -void _Scheduler_strong_APA_Register_idle( - Scheduler_Context *context, - Scheduler_Node *idle_base, - Per_CPU_Control *cpu +/** + * @brief Pins a node to a cpu + * + * @param scheduler The scheduler control instance. + * @param thread Thread corresponding to @node + * @param node_base node which gets pinned + * @param cpu processor that the node gets pinned to + */ +void _Scheduler_strong_APA_Pin( + const Scheduler_Control *scheduler, + Thread_Control *thread, + Scheduler_Node *node_base, + struct Per_CPU_Control *cpu +); + +/** + * @brief Unpins a node + * + * and sets it affinity back to normal. + * + * @param scheduler The scheduler control instance. + * @param thread Thread corresponding to @node + * @param node_base node which gets unpinned + * @param cpu processor that the node gets unpinned from : UNUSED + */ +void _Scheduler_strong_APA_Unpin( + const Scheduler_Control *scheduler, + Thread_Control *thread, + Scheduler_Node *node_base, + struct Per_CPU_Control *cpu ); +/** + * @brief Adds a processor to the scheduler instance + * + * and allocates an idle thread to the processor. + * + * @param scheduler The scheduler control instance. + * @param idle Idle thread to be allocated to the processor + */ void _Scheduler_strong_APA_Add_processor( const Scheduler_Control *scheduler, Thread_Control *idle ); +/** + * @brief Removes a processor from the scheduler instance + * + * @param scheduler The scheduler control instance. + * @param cpu processor that is removed + */ Thread_Control *_Scheduler_strong_APA_Remove_processor( const Scheduler_Control *scheduler, Per_CPU_Control *cpu ); -void _Scheduler_strong_APA_Yield( +/** + * @brief Initializes the node with the given priority. + * + * @param scheduler The scheduler control instance. + * @param[out] node The node to initialize. + * @param the_thread The thread of the node to initialize. + * @param priority The priority for @a node. + */ +void _Scheduler_strong_APA_Node_initialize( const Scheduler_Control *scheduler, - Thread_Control *thread, - Scheduler_Node *node -); - -void _Scheduler_strong_APA_Do_set_affinity( - Scheduler_Context *context, - Scheduler_Node *node_base, - void *arg + Scheduler_Node *node, + Thread_Control *the_thread, + Priority_Control priority ); +/** + * @brief Starts an idle thread on a CPU + * + * @param scheduler The scheduler control instance. + * @param idle Idle Thread + * @param cpu processor that gets the idle thread + */ void _Scheduler_strong_APA_Start_idle( const Scheduler_Control *scheduler, Thread_Control *idle, Per_CPU_Control *cpu ); -void _Scheduler_strong_APA_Pin( - const Scheduler_Control *scheduler, - Thread_Control *thread, - Scheduler_Node *node_base, - struct Per_CPU_Control *cpu -); - -void _Scheduler_strong_APA_Unpin( - const Scheduler_Control *scheduler, - Thread_Control *thread, - Scheduler_Node *node_base, - struct Per_CPU_Control *cpu -); - +/** + * @brief Sets the affinity of the @node_base to @affinity + */ bool _Scheduler_strong_APA_Set_affinity( const Scheduler_Control *scheduler, Thread_Control *thread, Scheduler_Node *node_base, const Processor_mask *affinity ); - /** @} */ #ifdef __cplusplus diff --git a/cpukit/score/src/schedulerstrongapa.c b/cpukit/score/src/schedulerstrongapa.c index 7c5077e9729..d6c1ab03fea 100644 --- a/cpukit/score/src/schedulerstrongapa.c +++ b/cpukit/score/src/schedulerstrongapa.c @@ -6,6 +6,24 @@ * @brief Strong APA Scheduler Implementation */ +/* + * Copyright (c) 2013, 2018 embedded brains GmbH, 2020 Richi Dubey. + * All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * + * + * Richi Dubey + * + * + * 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. + */ + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -32,59 +50,8 @@ _Scheduler_strong_APA_Node_downcast( Scheduler_Node *node ) { return (Scheduler_strong_APA_Node *) node; } -/** - * @brief Initializes the Strong_APA scheduler. - * - * Sets the chain containing all the nodes to empty - * and initializes the SMP scheduler. - * - * @param scheduler used to get - * reference to Strong APA scheduler context - * @retval void - * @see _Scheduler_strong_APA_Node_initialize() - * - */ -void _Scheduler_strong_APA_Initialize( const Scheduler_Control *scheduler ) -{ - Scheduler_strong_APA_Context *self = - _Scheduler_strong_APA_Get_context( scheduler ); - - _Scheduler_SMP_Initialize( &self->Base ); - _Chain_Initialize_empty( &self->allNodes ); -} - -/** - * @brief Initializes the node with the given priority. - * - * @param scheduler The scheduler control instance. - * @param[out] node The node to initialize. - * @param the_thread The thread of the node to initialize. - * @param priority The priority for @a node. - */ -void _Scheduler_strong_APA_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 ); -} -/** - * @brief Helper function for /a update entry function - * - * Calls _Scheduler_SMP_Node_update_priority() - * - * @param scheduler The scheduler context. - * @param[out] node The node to update the priority of. - * @param new_priority Node's new priority. - * @see _Scheduler_strong_APA_Do_update() - */ -void _Scheduler_strong_APA_Do_update( +static inline void _Scheduler_strong_APA_Do_update( Scheduler_Context *context, Scheduler_Node *node, Priority_Control new_priority @@ -97,18 +64,7 @@ void _Scheduler_strong_APA_Do_update( _Scheduler_SMP_Node_update_priority( smp_node, new_priority ); } -/** - * @brief Checks if scheduler has a ready node - * - * Iterates through all the nodes in /a allNodes to - * look for a ready node - * - * @param scheduler The scheduler context. - * @retval true if scheduler has a ready node available - * @retval false if scheduler has no ready nodes available - */ - -bool _Scheduler_strong_APA_Has_ready( Scheduler_Context *context ) +static inline bool _Scheduler_strong_APA_Has_ready( Scheduler_Context *context ) { Scheduler_strong_APA_Context *self = _Scheduler_strong_APA_Get_self( context ); @@ -136,12 +92,7 @@ bool _Scheduler_strong_APA_Has_ready( Scheduler_Context *context ) return ret; } -/** - * @brief Checks the next highest node ready on run - * on the CPU on which @filter node was running on - * - */ -Scheduler_Node *_Scheduler_strong_APA_Get_highest_ready( +static inline Scheduler_Node *_Scheduler_strong_APA_Get_highest_ready( Scheduler_Context *context, Scheduler_Node *filter ) //TODO @@ -242,18 +193,8 @@ Scheduler_Node *_Scheduler_strong_APA_Get_highest_ready( return ret; } -/** - * @brief Checks the lowest scheduled node - * running on a processor on which the - * @filter_base node could be running on - * - * @param context The scheduler context instance. - * @param filter_base The node which wants to get scheduled. - * - * @retval node The lowest scheduled node that can be - * replaced by @filter_base - */ -Scheduler_Node *_Scheduler_strong_APA_Get_lowest_scheduled( + +static inline Scheduler_Node *_Scheduler_strong_APA_Get_lowest_scheduled( Scheduler_Context *context, Scheduler_Node *filter_base ) @@ -361,15 +302,7 @@ Scheduler_Node *_Scheduler_strong_APA_Get_lowest_scheduled( return ret; } -/** - * @brief Extracts a node from the scheduled node's list - * - * Calls _Scheduler_SMP_Extract_from_scheduled() - * - * @param scheduler The scheduler context - * @param[in] node_to_extract The node to extract. - */ -void _Scheduler_strong_APA_Extract_from_scheduled( +static inline void _Scheduler_strong_APA_Extract_from_scheduled( Scheduler_Context *context, Scheduler_Node *node_to_extract ) @@ -384,15 +317,7 @@ void _Scheduler_strong_APA_Extract_from_scheduled( //Not removing it from allNodes since the node could go in the ready state. } -/** - * @brief Extracts a node from the ready queue - * - * Removes the node from /a allNodes chain. - * - * @param scheduler The scheduler context - * @param[in] node_to_extract The node to extract. - */ -void _Scheduler_strong_APA_Extract_from_ready( +static inline void _Scheduler_strong_APA_Extract_from_ready( Scheduler_Context *context, Scheduler_Node *node_to_extract ) @@ -410,18 +335,7 @@ void _Scheduler_strong_APA_Extract_from_ready( _Chain_Set_off_chain( &node->Node ); } -/** - * @brief Moves a node from scheduled to ready state - * - * Calls _Scheduler_SMP_Extract_from_scheduled() to remove it from - * scheduled nodes list - * - * @param scheduler The scheduler context - * @param[in] scheduled_to_ready The node to move. - * @see _Scheduler_strong_APA_Insert_ready() - * - */ -void _Scheduler_strong_APA_Move_from_scheduled_to_ready( +static inline void _Scheduler_strong_APA_Move_from_scheduled_to_ready( Scheduler_Context *context, Scheduler_Node *scheduled_to_ready ) @@ -438,16 +352,7 @@ void _Scheduler_strong_APA_Move_from_scheduled_to_ready( ); } -/** - * @brief Moves a node from ready to scheduled state. - * - * Calls the corresponding SMP function \a _Scheduler_SMP_Insert_scheduled() - * with append insert_priority - * - * @param context The scheduler context. - * @param ready_to_scheduled Node which moves from ready state. - */ -void _Scheduler_strong_APA_Move_from_ready_to_scheduled( +static inline void _Scheduler_strong_APA_Move_from_ready_to_scheduled( Scheduler_Context *context, Scheduler_Node *ready_to_scheduled ) @@ -465,17 +370,7 @@ void _Scheduler_strong_APA_Move_from_ready_to_scheduled( //Note: The node still stays in the allNodes chain } -/** - * @brief Inserts a node in the ready queue. - * - * Adds it into the /a allNodes chain. - * - * @param context The scheduler context. - * @param node_base Node which is inserted into the queue. - * @param insert_priority priority at which the node is inserted - */ - -void _Scheduler_strong_APA_Insert_ready( +static inline void _Scheduler_strong_APA_Insert_ready( Scheduler_Context *context, Scheduler_Node *node_base, Priority_Control insert_priority @@ -492,17 +387,7 @@ void _Scheduler_strong_APA_Insert_ready( _Chain_Append_unprotected( &self->allNodes, &node->Node ); } -/** - * @brief Allocates a processor for the node. - * - * Calls _Scheduler_SMP_Allocate_processor_exact() - * - * @param context The scheduler context. - * @param scheduled_base Node which is to be allocated the @victim_cpu. - * @param victim_base Node which was executing earlier on @victim_cpu - * @victim_cpu CPU on which the @scheduled_base would be allocated on - */ -void _Scheduler_strong_APA_Allocate_processor( +static inline void _Scheduler_strong_APA_Allocate_processor( Scheduler_Context *context, Scheduler_Node *scheduled_base, Scheduler_Node *victim_base, @@ -522,45 +407,7 @@ void _Scheduler_strong_APA_Allocate_processor( ); } -/** - * @brief Blocks a node - * - * Changes the state of the node and extracts it from the queue - * calls _Scheduler_SMP_Block(). - * - * @param context The scheduler control instance. - * @param thread Thread correspoding to the @node. - * @param node node which is to be blocked - */ -void _Scheduler_strong_APA_Block( - const Scheduler_Control *scheduler, - Thread_Control *thread, - Scheduler_Node *node -) -{ - Scheduler_Context *context = _Scheduler_Get_context( scheduler ); -//The extract from ready automatically removes the node from allNodes chain. - _Scheduler_SMP_Block( - context, - thread, - node, - _Scheduler_strong_APA_Extract_from_scheduled, - _Scheduler_strong_APA_Extract_from_ready, - _Scheduler_strong_APA_Get_highest_ready, - _Scheduler_strong_APA_Move_from_ready_to_scheduled, - _Scheduler_strong_APA_Allocate_processor - ); -} - -/** - * @brief Enqueues a node - * - * - * @param context The scheduler context. - * @param node node which is to be enqueued - * @param insert_priority priority at which the node should be enqueued. - */ -bool _Scheduler_strong_APA_Enqueue( +static inline bool _Scheduler_strong_APA_Enqueue( Scheduler_Context *context, Scheduler_Node *node, Priority_Control insert_priority @@ -579,15 +426,7 @@ bool _Scheduler_strong_APA_Enqueue( ); } -/** - * @brief Enqueues a node in the scheduled queue - * - * - * @param context The scheduler context. - * @param node node which is to be enqueued - * @param insert_priority priority at which the node should be enqueued. - */ -bool _Scheduler_strong_APA_Enqueue_scheduled( +static inline bool _Scheduler_strong_APA_Enqueue_scheduled( Scheduler_Context *context, Scheduler_Node *node, Priority_Control insert_priority @@ -607,18 +446,62 @@ bool _Scheduler_strong_APA_Enqueue_scheduled( ); } -/** - * @brief Unblocks a node - * - * Changes the state of the node and calls _Scheduler_SMP_Unblock(). - * - * @param scheduler The scheduler control instance. - * @param thread Thread correspoding to the @node. - * @param node node which is to be unblocked - * @see _Scheduler_strong_APA_Enqueue() - * @see _Scheduler_strong_APA_Do_update() - */ -void _Scheduler_strong_APA_Unblock( +static inline bool _Scheduler_strong_APA_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_Priority_less_equal, + _Scheduler_strong_APA_Insert_ready, + _Scheduler_SMP_Insert_scheduled, + _Scheduler_strong_APA_Move_from_scheduled_to_ready, + _Scheduler_strong_APA_Get_lowest_scheduled, + _Scheduler_strong_APA_Allocate_processor + ); +} + +static inline void _Scheduler_strong_APA_Register_idle( + Scheduler_Context *context, + Scheduler_Node *idle_base, + Per_CPU_Control *cpu +) +{ + (void) context; + (void) idle_base; + (void) cpu; + //We do not maintain a variable to access the scheduled + //node for a CPU. So this function does nothing. +} + +static inline void _Scheduler_strong_APA_Do_set_affinity( + Scheduler_Context *context, + Scheduler_Node *node_base, + void *arg +) +{ + Scheduler_strong_APA_Node *node; + const Processor_mask *affinity; + + node = _Scheduler_strong_APA_Node_downcast( node_base ); + affinity = arg; + node->affinity = *affinity; +} + +void _Scheduler_strong_APA_Initialize( const Scheduler_Control *scheduler ) +{ + Scheduler_strong_APA_Context *self = + _Scheduler_strong_APA_Get_context( scheduler ); + + _Scheduler_SMP_Initialize( &self->Base ); + _Chain_Initialize_empty( &self->allNodes ); +} + +void _Scheduler_strong_APA_Yield( const Scheduler_Control *scheduler, Thread_Control *thread, Scheduler_Node *node @@ -626,65 +509,53 @@ void _Scheduler_strong_APA_Unblock( { Scheduler_Context *context = _Scheduler_Get_context( scheduler ); - _Scheduler_SMP_Unblock( + _Scheduler_SMP_Yield( context, thread, node, - _Scheduler_strong_APA_Do_update, - _Scheduler_strong_APA_Enqueue + _Scheduler_strong_APA_Extract_from_ready, + _Scheduler_strong_APA_Enqueue, + _Scheduler_strong_APA_Enqueue_scheduled ); } -static inline bool _Scheduler_strong_APA_Do_ask_for_help( - Scheduler_Context *context, - Thread_Control *the_thread, - Scheduler_Node *node +void _Scheduler_strong_APA_Block( + const Scheduler_Control *scheduler, + Thread_Control *thread, + Scheduler_Node *node ) { - return _Scheduler_SMP_Ask_for_help( + Scheduler_Context *context = _Scheduler_Get_context( scheduler ); +//The extract from ready automatically removes the node from allNodes chain. + _Scheduler_SMP_Block( context, - the_thread, + thread, node, - _Scheduler_SMP_Priority_less_equal, - _Scheduler_strong_APA_Insert_ready, - _Scheduler_SMP_Insert_scheduled, - _Scheduler_strong_APA_Move_from_scheduled_to_ready, - _Scheduler_strong_APA_Get_lowest_scheduled, + _Scheduler_strong_APA_Extract_from_scheduled, + _Scheduler_strong_APA_Extract_from_ready, + _Scheduler_strong_APA_Get_highest_ready, + _Scheduler_strong_APA_Move_from_ready_to_scheduled, _Scheduler_strong_APA_Allocate_processor ); } -/** - * @brief Calls the smp Ask_for_help - * - * - * @param scheduler The scheduler control instance. - * @param thread Thread correspoding to the @node that asks for help. - * @param node node associated with @thread - */ -bool _Scheduler_strong_APA_Ask_for_help( +void _Scheduler_strong_APA_Unblock( const Scheduler_Control *scheduler, - Thread_Control *the_thread, + Thread_Control *thread, Scheduler_Node *node ) { Scheduler_Context *context = _Scheduler_Get_context( scheduler ); - return _Scheduler_strong_APA_Do_ask_for_help( + _Scheduler_SMP_Unblock( context, - the_thread, - node + thread, + node, + _Scheduler_strong_APA_Do_update, + _Scheduler_strong_APA_Enqueue ); } - -/** - * @brief Updates the priority of the node - * - * @param scheduler The scheduler control instance. - * @param thread Thread correspoding to the @node. - * @param node Node whose priority has to be updated - */ void _Scheduler_strong_APA_Update_priority( const Scheduler_Control *scheduler, Thread_Control *thread, @@ -704,14 +575,22 @@ void _Scheduler_strong_APA_Update_priority( _Scheduler_strong_APA_Do_ask_for_help ); } -/** - * @brief To Reconsider the help request - * - * @param scheduler The scheduler control instance. - * @param thread Thread correspoding to the @node. - * @param node Node corresponding to @thread which asks for - * reconsideration - */ + +bool _Scheduler_strong_APA_Ask_for_help( + const Scheduler_Control *scheduler, + Thread_Control *the_thread, + Scheduler_Node *node +) +{ + Scheduler_Context *context = _Scheduler_Get_context( scheduler ); + + return _Scheduler_strong_APA_Do_ask_for_help( + context, + the_thread, + node + ); +} + void _Scheduler_strong_APA_Reconsider_help_request( const Scheduler_Control *scheduler, Thread_Control *the_thread, @@ -728,14 +607,6 @@ void _Scheduler_strong_APA_Reconsider_help_request( ); } -/** - * @brief Withdraws a node - * - * @param scheduler The scheduler control instance. - * @param thread Thread correspoding to the @node. - * @param node Node that has to be withdrawn - * @param next_state the state that the node goes to - */ void _Scheduler_strong_APA_Withdraw_node( const Scheduler_Control *scheduler, Thread_Control *the_thread, @@ -757,34 +628,51 @@ void _Scheduler_strong_APA_Withdraw_node( ); } -/** - * @brief To register an idle thread on a cpu - * - * For compatibility with SMP functions, - * does nothing in our implementation - */ -void _Scheduler_strong_APA_Register_idle( - Scheduler_Context *context, - Scheduler_Node *idle_base, - Per_CPU_Control *cpu +void _Scheduler_strong_APA_Pin( + const Scheduler_Control *scheduler, + Thread_Control *thread, + Scheduler_Node *node_base, + struct Per_CPU_Control *cpu ) { - (void) context; - (void) idle_base; + Scheduler_strong_APA_Node *node; + uint32_t pin_cpu; + + (void) scheduler; + node = _Scheduler_strong_APA_Node_downcast( node_base ); + pin_cpu = (uint32_t) _Per_CPU_Get_index( cpu ); + + _Assert( + _Scheduler_SMP_Node_state( &node->Base.Base ) == SCHEDULER_SMP_NODE_BLOCKED + ); + + node = _Scheduler_strong_APA_Node_downcast( node_base ); + + _Processor_mask_Zero( &node->affinity ); + _Processor_mask_Set( &node->affinity, pin_cpu ); +} + +void _Scheduler_strong_APA_Unpin( + const Scheduler_Control *scheduler, + Thread_Control *thread, + Scheduler_Node *node_base, + struct Per_CPU_Control *cpu +) +{ + Scheduler_strong_APA_Node *node; + + (void) scheduler; (void) cpu; - //We do not maintain a variable to access the scheduled - //node for a CPU. So this function does nothing. + node = _Scheduler_strong_APA_Node_downcast( node_base ); + + _Assert( + _Scheduler_SMP_Node_state( &node->Base.Base ) == SCHEDULER_SMP_NODE_BLOCKED + ); + + _Processor_mask_Zero( &node->affinity ); + _Processor_mask_Assign( &node->affinity, &node->unpin_affinity ); } -/** - * @brief Adds a processor to the scheduler instance - * - * and allocates an idle thread to the processor. - * - * @param scheduler The scheduler control instance. - * @param idle Idle thread to be allocated to the processor - * - */ void _Scheduler_strong_APA_Add_processor( const Scheduler_Control *scheduler, Thread_Control *idle @@ -801,14 +689,6 @@ void _Scheduler_strong_APA_Add_processor( ); } - -/** - * @brief Removes a processor from the scheduler instance - * - * @param scheduler The scheduler control instance. - * @param cpu processor that is removed - * - */ Thread_Control *_Scheduler_strong_APA_Remove_processor( const Scheduler_Control *scheduler, Per_CPU_Control *cpu @@ -824,59 +704,19 @@ Thread_Control *_Scheduler_strong_APA_Remove_processor( ); } - -/** - * @brief Called when a node yields the processor - * - * @param scheduler The scheduler control instance. - * @param thread Thread corresponding to @node - * @param node Node that yield the processor - * - */ -void _Scheduler_strong_APA_Yield( +void _Scheduler_strong_APA_Node_initialize( const Scheduler_Control *scheduler, - Thread_Control *thread, - Scheduler_Node *node -) -{ - Scheduler_Context *context = _Scheduler_Get_context( scheduler ); - - _Scheduler_SMP_Yield( - context, - thread, - node, - _Scheduler_strong_APA_Extract_from_ready, - _Scheduler_strong_APA_Enqueue, - _Scheduler_strong_APA_Enqueue_scheduled - ); -} - -/** - * @brief Called by _Scheduler_strong_APA_Set_affinity() - * - */ -void _Scheduler_strong_APA_Do_set_affinity( - Scheduler_Context *context, - Scheduler_Node *node_base, - void *arg + Scheduler_Node *node, + Thread_Control *the_thread, + Priority_Control priority ) { - Scheduler_strong_APA_Node *node; - const Processor_mask *affinity; - - node = _Scheduler_strong_APA_Node_downcast( node_base ); - affinity = arg; - node->affinity = *affinity; + Scheduler_SMP_Node *smp_node; + + smp_node = _Scheduler_SMP_Node_downcast( node ); + _Scheduler_SMP_Node_initialize( scheduler, smp_node, the_thread, priority ); } -/** - * @brief Starts an idle thread on a CPU - * - * @param scheduler The scheduler control instance. - * @param idle Idle Thread - * @param cpu processor that gets the idle thread - * - */ void _Scheduler_strong_APA_Start_idle( const Scheduler_Control *scheduler, Thread_Control *idle, @@ -895,86 +735,6 @@ void _Scheduler_strong_APA_Start_idle( ); } -/** - * @brief Pins a node to a cpu - * - * @param scheduler The scheduler control instance. - * @param thread Thread corresponding to @node - * @param node_base node which gets pinned - * @param cpu processor that the node gets pinned to - * - */ -void _Scheduler_strong_APA_Pin( - const Scheduler_Control *scheduler, - Thread_Control *thread, - Scheduler_Node *node_base, - struct Per_CPU_Control *cpu -) -{ - Scheduler_strong_APA_Node *node; - uint32_t pin_cpu; - - (void) scheduler; - node = _Scheduler_strong_APA_Node_downcast( node_base ); - pin_cpu = (uint32_t) _Per_CPU_Get_index( cpu ); - - _Assert( - _Scheduler_SMP_Node_state( &node->Base.Base ) == SCHEDULER_SMP_NODE_BLOCKED - ); - - node = _Scheduler_strong_APA_Node_downcast( node_base ); - - _Processor_mask_Zero( &node->affinity ); - _Processor_mask_Set( &node->affinity, pin_cpu ); -} - -/** - * @brief Unpins a node - * - * and sets it affinity back to normal. - * - * @param scheduler The scheduler control instance. - * @param thread Thread corresponding to @node - * @param node_base node which gets unpinned - * @param cpu processor that the node gets unpinned from : UNUSED - * - */ -void _Scheduler_strong_APA_Unpin( - const Scheduler_Control *scheduler, - Thread_Control *thread, - Scheduler_Node *node_base, - struct Per_CPU_Control *cpu -) -{ - Scheduler_strong_APA_Node *node; - - (void) scheduler; - (void) cpu; - node = _Scheduler_strong_APA_Node_downcast( node_base ); - - _Assert( - _Scheduler_SMP_Node_state( &node->Base.Base ) == SCHEDULER_SMP_NODE_BLOCKED - ); - - _Processor_mask_Zero( &node->affinity ); - _Processor_mask_Assign( &node->affinity, &node->unpin_affinity ); -} - -/** - * @brief Checks if the processor set of the scheduler is the subset of the affinity set. - * - * Default implementation of the set affinity scheduler operation. - * - * @param scheduler This parameter is unused. - * @param thread This parameter is unused. - * @param node This parameter is unused. - * @param affinity The new processor affinity set for the thread. - * - * @see _Scheduler_strong_APA_Do_set_affinity() - * - * @retval true The processor set of the scheduler is a subset of the affinity set. - * @retval false The processor set of the scheduler is not a subset of the affinity set. - */ bool _Scheduler_strong_APA_Set_affinity( const Scheduler_Control *scheduler, Thread_Control *thread, @@ -997,10 +757,7 @@ bool _Scheduler_strong_APA_Set_affinity( if ( _Processor_mask_Is_equal( &node->affinity, affinity ) ) return true; //Nothing to do. Return true. - - _Processor_mask_Zero( &node->affinity ); - _Processor_mask_Zero( &node->unpin_affinity ); - + _Processor_mask_Assign( &node->affinity, &local_affinity ); _Processor_mask_Assign( &node->unpin_affinity, &local_affinity ); @@ -1019,3 +776,4 @@ bool _Scheduler_strong_APA_Set_affinity( return true; } + From 424c500086a6c8cc583d9b86edd2a0e560bdb451 Mon Sep 17 00:00:00 2001 From: richidubey Date: Wed, 5 Aug 2020 19:41:35 +0530 Subject: [PATCH 7/9] Started replacing the pseduo codes --- cpukit/include/rtems/scheduler.h | 2 +- .../include/rtems/score/schedulerstrongapa.h | 97 ++++---- cpukit/score/src/schedulerstrongapa.c | 227 ++++++++++-------- 3 files changed, 176 insertions(+), 150 deletions(-) diff --git a/cpukit/include/rtems/scheduler.h b/cpukit/include/rtems/scheduler.h index 955a83cfb48..b84b29fd209 100644 --- a/cpukit/include/rtems/scheduler.h +++ b/cpukit/include/rtems/scheduler.h @@ -257,7 +257,7 @@ #define RTEMS_SCHEDULER_STRONG_APA( name, prio_count ) \ static struct { \ Scheduler_strong_APA_Context Base; \ - Chain_Control Ready[ ( prio_count ) ]; \ + Scheduler_strong_APA_CPU CPU[ CONFIGURE_MAXIMUM_PROCESSORS ]; } SCHEDULER_STRONG_APA_CONTEXT_NAME( name ) #define RTEMS_SCHEDULER_TABLE_STRONG_APA( name, obj_name ) \ diff --git a/cpukit/include/rtems/score/schedulerstrongapa.h b/cpukit/include/rtems/score/schedulerstrongapa.h index cae588a1570..1947585a19f 100644 --- a/cpukit/include/rtems/score/schedulerstrongapa.h +++ b/cpukit/include/rtems/score/schedulerstrongapa.h @@ -20,7 +20,7 @@ * * 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. + * http://www.rtems.org/license/LICENSE. */ #ifndef _RTEMS_SCORE_SCHEDULERSTRONGAPA_H @@ -65,7 +65,24 @@ typedef struct { * @brief Chain of all the nodes present in * the system. Accounts for ready and scheduled nodes. */ - Chain_Control all_nodes; + Chain_Control All_nodes; + + /** + * @brief Queue for this context + */ + Scheduler_strong_APA_Queue *queue; + + /** + * @brief Pointer to structure with array of + * boolean visited values + */ + Scheduler_strong_APA_Visited *visited; + + /** + * @brief Pointer to structure with array of + * caller corresponding to a CPU + */ + Scheduler_strong_APA_Caller *caller; } Scheduler_strong_APA_Context; /** @@ -86,30 +103,42 @@ typedef struct { * @brief The associated affinity set of this node. */ Processor_mask Affinity; - - /** - * @brief The associated affinity set of this node to be used while unpinning the node. - */ - Processor_mask Unpin_affinity; } Scheduler_strong_APA_Node; /** * @brief CPU structure to be used while traversing in the FIFO Queue */ -typedef struct Scheduler_strong_APA_CPU +typedef struct { /** - * @brief Chain node for - * _Scheduler_strong_APA_Get_highest_ready::Queue - * and _Scheduler_strong_APA_Get_lowest_scheduled::Queue - */ - Chain_Node node; + * @brief Array of Cpu to be used for the queue operations + */ + Per_CPU_Control Cpu[ RTEMS_ZERO_LENGTH_ARRAY ]; +} Scheduler_strong_APA_Queue; + +/** + * @brief Caller corresponding to a Cpu in Scheduler_strong_APA_Queue + */ +typedef struct +{ + /** + * @brief Array of caller each corresponding to the + * Scheduler_strong_APA_Queue::Cpu at the same index + */ + Scheduler_strong_APA_Node *caller[ RTEMS_ZERO_LENGTH_ARRAY ]; +} Scheduler_strong_APA_Caller; +/** + * @brief to a Cpu in Scheduler_strong_APA_Queue + */ +typedef struct +{ /** - * @brief cpu associated with the node + * @brief Array of boolean each corresponding to the visited status of + * Scheduler_strong_APA_Queue::Cpu at the same index */ - Per_CPU_Control cpu; -}Scheduler_strong_APA_CPU; + bool *visited[ RTEMS_ZERO_LENGTH_ARRAY ]; +} Scheduler_strong_APA_Visited; /** * @brief Entry points for the Strong APA Scheduler. @@ -127,8 +156,8 @@ typedef struct Scheduler_strong_APA_CPU _Scheduler_strong_APA_Ask_for_help, \ _Scheduler_strong_APA_Reconsider_help_request, \ _Scheduler_strong_APA_Withdraw_node, \ - _Scheduler_strong_APA_Pin, \ - _Scheduler_strong_APA_Unpin, \ + _Scheduler_default_Pin_or_unpin, \ + _Scheduler_default_Pin_or_unpin, \ _Scheduler_strong_APA_Add_processor, \ _Scheduler_strong_APA_Remove_processor, \ _Scheduler_strong_APA_Node_initialize, \ @@ -255,38 +284,6 @@ void _Scheduler_strong_APA_Withdraw_node( Thread_Scheduler_state next_state ); -/** - * @brief Pins a node to a cpu - * - * @param scheduler The scheduler control instance. - * @param thread Thread corresponding to @node - * @param node_base node which gets pinned - * @param cpu processor that the node gets pinned to - */ -void _Scheduler_strong_APA_Pin( - const Scheduler_Control *scheduler, - Thread_Control *thread, - Scheduler_Node *node_base, - struct Per_CPU_Control *cpu -); - -/** - * @brief Unpins a node - * - * and sets it affinity back to normal. - * - * @param scheduler The scheduler control instance. - * @param thread Thread corresponding to @node - * @param node_base node which gets unpinned - * @param cpu processor that the node gets unpinned from : UNUSED - */ -void _Scheduler_strong_APA_Unpin( - const Scheduler_Control *scheduler, - Thread_Control *thread, - Scheduler_Node *node_base, - struct Per_CPU_Control *cpu -); - /** * @brief Adds a processor to the scheduler instance * diff --git a/cpukit/score/src/schedulerstrongapa.c b/cpukit/score/src/schedulerstrongapa.c index d6c1ab03fea..4bf43ea563d 100644 --- a/cpukit/score/src/schedulerstrongapa.c +++ b/cpukit/score/src/schedulerstrongapa.c @@ -21,7 +21,7 @@ * * 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. + * http://www.rtems.org/license/LICENSE. */ #ifdef HAVE_CONFIG_H @@ -68,25 +68,27 @@ static inline bool _Scheduler_strong_APA_Has_ready( Scheduler_Context *context ) { Scheduler_strong_APA_Context *self = _Scheduler_strong_APA_Get_self( context ); - bool ret; - const Chain_Node *tail; - Chain_Node *next; + bool ret; + const Chain_Node *tail; + Chain_Node *next; + Scheduler_strong_APA_Node *node; tail = _Chain_Immutable_tail( &self->allNodes ); next = _Chain_First( &self->allNodes ); - ret=false; + ret = false; while ( next != tail ) { - Scheduler_strong_APA_Node *node; - - node = (Scheduler_strong_APA_Node *) next; + node = (Scheduler_strong_APA_Node *) next; - if( _Scheduler_SMP_Node_state( &node->Base.Base ) - == SCHEDULER_SMP_NODE_READY ) { - ret=true; - break; - } + if ( + _Scheduler_SMP_Node_state( &node->Base.Base ) == SCHEDULER_SMP_NODE_READY + ) { + ret = true; + break; + } + + next = _Chain_Next( next ); } return ret; @@ -100,18 +102,17 @@ static inline Scheduler_Node *_Scheduler_strong_APA_Get_highest_ready( //Plan for this function: (Pseudo Code): Scheduler_strong_APA_Context *self=_Scheduler_strong_APA_Get_self( context ); - CPU *Qcpu; - Thread_Control *thread; - Per_CPU_Control *thread_cpu; - Per_CPU_Control *curr_CPU; - Per_CPU_Control *assigned_cpu; - Scheduler_Node *ret; - Priority_Control max_priority; - Priority_Control curr_priority; - Chain_Control Queue; - bool visited[10]; //Temporary Compilation Fix - - + CPU *Qcpu; + Thread_Control *thread; + Per_CPU_Control *thread_cpu; + Per_CPU_Control *curr_CPU; + Per_CPU_Control *assigned_cpu; + Scheduler_Node *ret; + Priority_Control max_priority; + Priority_Control curr_priority; + Scheduler_SMP_Node_state curr_state; + Chain_Control Queue; + bool visited[10]; //Temporary Compilation Fix thread = filter->user; thread_cpu = _Thread_Get_CPU( thread ); @@ -119,14 +120,13 @@ static inline Scheduler_Node *_Scheduler_strong_APA_Get_highest_ready( //Implement the BFS Algorithm for task departure //to get the highest ready task for a particular CPU - max_priority = _Scheduler_Node_get_priority( filter ); max_priority = SCHEDULER_PRIORITY_PURIFY( max_priority ); - ret=filter; + ret = filter; - const Chain_Node *tail; - Chain_Node *next; + const Chain_Node *tail; + Chain_Node *next; _Chain_Initialize_empty(&Queue); @@ -147,42 +147,41 @@ static inline Scheduler_Node *_Scheduler_strong_APA_Get_highest_ready( while ( next != tail ) { Scheduler_strong_APA_Node *node; node = (Scheduler_strong_APA_Node *) next; + curr_state = _Scheduler_SMP_Node_state( &node->Base.Base ); - if( _Processor_mask_Is_set( &node->affinity, _Per_CPU_Get_index( curr_CPU ) ) ) { - //Checks if the thread_CPU is in the affinity set of the node + if ( + _Processor_mask_Is_set(&node->affinity, _Per_CPU_Get_index( curr_CPU)) + ) { + //Checks if the thread_CPU is in the affinity set of the node - if(_Scheduler_SMP_Node_state( &node->Base.Base ) - == SCHEDULER_SMP_NODE_SCHEDULED) { - - assigned_cpu = _Thread_Get_CPU( node->Base.Base.user ); + if ( curr_state == SCHEDULER_SMP_NODE_SCHEDULED) { + assigned_cpu = _Thread_Get_CPU( node->Base.Base.user ); - if(visited[ _Per_CPU_Get_index( assigned_cpu ) ] == false) { - Qcpu = rtems_malloc( sizeof(CPU) ); - //rtems_malloc does not return a errnum in case of failure - Qcpu->cpu=*assigned_cpu; + if ( visited[ _Per_CPU_Get_index( assigned_cpu ) ] == false) { + Qcpu = rtems_malloc( sizeof(CPU) ); + //rtems_malloc does not return a errnum in case of failure + Qcpu->cpu=*assigned_cpu; - _Chain_Initialize_node( &Qcpu->node ); - _Chain_Append_unprotected( &Queue, &Qcpu->node ); - //Insert thread_CPU in the Queue - visited[ _Per_CPU_Get_index (assigned_cpu) ]=true; - } - } - else if(_Scheduler_SMP_Node_state( &node->Base.Base ) - == SCHEDULER_SMP_NODE_READY) { - curr_priority = _Scheduler_Node_get_priority( (Scheduler_Node *) next ); - curr_priority = SCHEDULER_PRIORITY_PURIFY( curr_priority ); + _Chain_Initialize_node( &Qcpu->node ); + _Chain_Append_unprotected( &Queue, &Qcpu->node ); + //Insert thread_CPU in the Queue + visited[ _Per_CPU_Get_index (assigned_cpu) ]=true; + } + } else if ( curr_state == SCHEDULER_SMP_NODE_READY) { + curr_priority = _Scheduler_Node_get_priority( (Scheduler_Node *) next ); + curr_priority = SCHEDULER_PRIORITY_PURIFY( curr_priority ); - if(curr_priorityBase.Base; - } - } - } + if ( curr_priorityBase.Base; + } + } + } next = _Chain_Next( next ); } } - if( ret != filter) + if ( ret != filter) { //Backtrack on the path from //thread_cpu to ret, shifting along every task. @@ -204,43 +203,55 @@ static inline Scheduler_Node *_Scheduler_strong_APA_Get_lowest_scheduled( uint32_t cpu_max; uint32_t cpu_index; CPU *Qcpu; + Priority_Control filter_priority; + + Per_CPU_Control *curr_CPU; + Thread_Control *curr_thread; + Scheduler_Node *curr_node; + Scheduler_Node *ret; + Chain_Control Queue; + Priority_Control max_priority; + Priority_Control curr_priority; + bool *visited; + - Per_CPU_Control *curr_CPU; - Thread_Control *curr_thread; - Scheduler_Node *curr_node; - Scheduler_Node *ret; - Chain_Control Queue; - Priority_Control max_priority; - Priority_Control curr_priority; - bool visited[10]; //Temporary Compilation Fix + Scheduler_strong_APA_Context *self; + + self = _Scheduler_strong_APA_Get_self( context ); + + visited = self->visited->visited; Scheduler_strong_APA_Node *Scurr_node; //Current Strong_APA_Node Scheduler_strong_APA_Node *filter_node; - ret=NULL; //To remove compiler warning. + ret = NULL; //To remove compiler warning. //ret would always point to the node with the lowest priority //node unless the affinity of filter_base is NULL. filter_node = _Scheduler_strong_APA_Node_downcast( filter_base ); - max_priority = 300;//Max (Lowest) priority encountered so far. + max_priority_num = 0;//Max (Lowest) priority encountered so far. + + _Assert( !_Processor_mask_Zero( &filter_node->affinity ) ); cpu_max = _SMP_Get_processor_maximum(); _Chain_Initialize_empty(&Queue); for ( cpu_index = 0 ; cpu_index < cpu_max ; ++cpu_index ) { - if( ( _Processor_mask_Is_set( &filter_node->affinity , cpu_index) - && visited[ cpu_index ] == false ) ) { - //Checks if the thread_CPU is in the affinity set of the node + visited[ cpu_index ] = false; + + //Checks if the thread_CPU is in the affinity set of the node + if ( _Processor_mask_Is_set( &filter_node->affinity, cpu_index)) { Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index ); - if( _Per_CPU_Is_processor_online( cpu ) ) { + + if ( _Per_CPU_Is_processor_online( cpu ) ) { Qcpu = rtems_malloc( sizeof(CPU) ); //No errornum returned in case of failure - Qcpu->cpu=*cpu; + Qcpu->cpu = *cpu; _Chain_Initialize_node( &Qcpu->node ); _Chain_Append_unprotected( &Queue, &Qcpu->node ); - //Insert cpu in the Queue - visited[ cpu_index ]=true; + //Insert cpu in the Queue + visited[ cpu_index ] = true; } } } @@ -250,45 +261,46 @@ static inline Scheduler_Node *_Scheduler_strong_APA_Get_lowest_scheduled( curr_CPU = &Qcpu->cpu; curr_thread = curr_CPU->executing; - curr_node = (Scheduler_Node *) _Chain_First( &curr_thread->Scheduler.Scheduler_nodes ); - - //How to check if the thread is not participating - //in helping on this processor? + curr_node = _Thread_Scheduler_get_home_node( curr_thread ); curr_priority = _Scheduler_Node_get_priority( curr_node ); curr_priority = SCHEDULER_PRIORITY_PURIFY( curr_priority ); - if(curr_priority < max_priority) { + if ( curr_priority > max_priority_num) { ret = curr_node; - max_priority = curr_priority; + max_priority_num = curr_priority; + + if( curr_priority > SCHEDULER_PRIORITY_PURIFY( _Scheduler_Node_get_priority( filter_base ) ) ) + { + cpu_to_preempt=curr_CPU; + } } - Scurr_node = _Scheduler_strong_APA_Node_downcast( curr_node ); - if( !curr_thread->is_idle ) { + Scurr_node = _Scheduler_strong_APA_Node_downcast( curr_node ); + if ( !curr_thread->is_idle ) { for ( cpu_index = 0 ; cpu_index < cpu_max ; ++cpu_index ) { - if( _Processor_mask_Is_set( &Scurr_node->affinity , cpu_index ) ) { + if ( _Processor_mask_Is_set( &Scurr_node->affinity, cpu_index ) ) { //Checks if the thread_CPU is in the affinity set of the node Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index ); - if( _Per_CPU_Is_processor_online( cpu ) && visited[ cpu_index ] == false ) { + if ( _Per_CPU_Is_processor_online( cpu ) && visited[ cpu_index ] == false ) { Qcpu = rtems_malloc( sizeof(CPU) ); - Qcpu->cpu=*cpu; + Qcpu->cpu = *cpu; _Chain_Initialize_node( &Qcpu->node ); _Chain_Append_unprotected( &Queue, &Qcpu->node ); //Insert the cpu in the affinty set of curr_thread in the Queue - visited[ cpu_index ]=true; + visited[ cpu_index ] = true; } } } } } - Priority_Control filter_priority; filter_priority = _Scheduler_Node_get_priority( filter_base ); filter_priority = SCHEDULER_PRIORITY_PURIFY( filter_priority ); - if( ret->Priority.value < filter_priority ) { + if ( ret->Priority.value < filter_priority ) { //Lowest priority task found has higher priority // than filter_base. //So, filter_base remains unassigned @@ -307,8 +319,8 @@ static inline void _Scheduler_strong_APA_Extract_from_scheduled( Scheduler_Node *node_to_extract ) { - Scheduler_strong_APA_Context *self; - Scheduler_strong_APA_Node *node; + Scheduler_strong_APA_Context *self; + Scheduler_strong_APA_Node *node; self = _Scheduler_strong_APA_Get_self( context ); node = _Scheduler_strong_APA_Node_downcast( node_to_extract ); @@ -322,8 +334,8 @@ static inline void _Scheduler_strong_APA_Extract_from_ready( Scheduler_Node *node_to_extract ) { - Scheduler_strong_APA_Context *self; - Scheduler_strong_APA_Node *node; + Scheduler_strong_APA_Context *self; + Scheduler_strong_APA_Node *node; self = _Scheduler_strong_APA_Get_self( context ); node = _Scheduler_strong_APA_Node_downcast( node_to_extract ); @@ -370,14 +382,31 @@ static inline void _Scheduler_strong_APA_Move_from_ready_to_scheduled( //Note: The node still stays in the allNodes chain } +static inline void _Scheduler_strong_APA_Set_scheduled( + _Scheduler_strong_APA_Context *self, + _Scheduler_strong_APA_Node *scheduled, + const Per_CPU_Control *cpu +) +{ + self->CPU[ _Per_CPU_Get_index( cpu ) ].scheduled = scheduled; +} + +static inline Scheduler_EDF_SMP_Node *_Scheduler_strong_APA_Get_scheduled( + const _Scheduler_strong_APA_Context *self, + uint8_t cpu +) +{ + return self->CPU[ cpu ].scheduled; +} + static inline void _Scheduler_strong_APA_Insert_ready( Scheduler_Context *context, Scheduler_Node *node_base, Priority_Control insert_priority ) { - Scheduler_strong_APA_Context *self; - Scheduler_strong_APA_Node *node; + Scheduler_strong_APA_Context *self; + Scheduler_strong_APA_Node *node; self = _Scheduler_strong_APA_Get_self( context ); node = _Scheduler_strong_APA_Node_downcast( node_base ); @@ -394,7 +423,7 @@ static inline void _Scheduler_strong_APA_Allocate_processor( Per_CPU_Control *victim_cpu ) { - Scheduler_strong_APA_Node *scheduled; + Scheduler_strong_APA_Node *scheduled; (void) victim_base; scheduled = _Scheduler_strong_APA_Node_downcast( scheduled_base ); @@ -635,8 +664,8 @@ void _Scheduler_strong_APA_Pin( struct Per_CPU_Control *cpu ) { - Scheduler_strong_APA_Node *node; - uint32_t pin_cpu; + Scheduler_strong_APA_Node *node; + uint32_t pin_cpu; (void) scheduler; node = _Scheduler_strong_APA_Node_downcast( node_base ); @@ -742,9 +771,9 @@ bool _Scheduler_strong_APA_Set_affinity( const Processor_mask *affinity ) { - Scheduler_Context *context; - Scheduler_strong_APA_Node *node; - Processor_mask local_affinity; + Scheduler_Context *context; + Scheduler_strong_APA_Node *node; + Processor_mask local_affinity; context = _Scheduler_Get_context( scheduler ); _Processor_mask_And( &local_affinity, &context->Processors, affinity ); From f2d6e4256ab07fe6e7479af8eeb0dcdb574964f4 Mon Sep 17 00:00:00 2001 From: richidubey Date: Thu, 6 Aug 2020 20:29:51 +0530 Subject: [PATCH 8/9] Added get_lowest_scheduled --- cpukit/score/src/schedulerstrongapa.c | 206 +++++++++++++++----------- 1 file changed, 120 insertions(+), 86 deletions(-) diff --git a/cpukit/score/src/schedulerstrongapa.c b/cpukit/score/src/schedulerstrongapa.c index 4bf43ea563d..9dd0ea610a7 100644 --- a/cpukit/score/src/schedulerstrongapa.c +++ b/cpukit/score/src/schedulerstrongapa.c @@ -111,9 +111,21 @@ static inline Scheduler_Node *_Scheduler_strong_APA_Get_highest_ready( Priority_Control max_priority; Priority_Control curr_priority; Scheduler_SMP_Node_state curr_state; - Chain_Control Queue; - bool visited[10]; //Temporary Compilation Fix + const Chain_Node *tail; + Chain_Node *next; + Per_CPU_Control *queue; //Array of Cpu that serves as a queue + bool *visited; //Array of bool values each corresponding to a cpu + + //Denotes front and rear of the queue + uint32_t front; + uint32_t rear; + front = 0; + rear = -1; + + visited = self->visited->visited; + queue = self->queue->Cpu; + thread = filter->user; thread_cpu = _Thread_Get_CPU( thread ); @@ -124,23 +136,15 @@ static inline Scheduler_Node *_Scheduler_strong_APA_Get_highest_ready( max_priority = SCHEDULER_PRIORITY_PURIFY( max_priority ); ret = filter; - - const Chain_Node *tail; - Chain_Node *next; - - _Chain_Initialize_empty(&Queue); - - Qcpu = rtems_malloc( sizeof(CPU) ); //Does not return any errornum on failure - Qcpu->cpu=*thread_cpu; - _Chain_Initialize_node( &Qcpu->node ); - _Chain_Append_unprotected( &Queue, &Qcpu->node ); //Insert thread_CPU in the Queue + rear = rear + 1; + queue[ rear ] = thread_cpu; visited[ _Per_CPU_Get_index( thread_cpu ) ]=true; - - while( !_Chain_Is_empty( &Queue) ) { - Qcpu = (CPU*) _Chain_Get_first_unprotected( &Queue ); - curr_CPU = &Qcpu->cpu; + while( front <= rear ) { + curr_CPU = queue[ front ]; + front = front + 1; + tail = _Chain_Immutable_tail( &self->allNodes ); next = _Chain_First( &self->allNodes ); @@ -149,37 +153,38 @@ static inline Scheduler_Node *_Scheduler_strong_APA_Get_highest_ready( node = (Scheduler_strong_APA_Node *) next; curr_state = _Scheduler_SMP_Node_state( &node->Base.Base ); - if ( + if ( _Processor_mask_Is_set(&node->affinity, _Per_CPU_Get_index( curr_CPU)) - ) { - //Checks if the thread_CPU is in the affinity set of the node - - if ( curr_state == SCHEDULER_SMP_NODE_SCHEDULED) { - assigned_cpu = _Thread_Get_CPU( node->Base.Base.user ); - - if ( visited[ _Per_CPU_Get_index( assigned_cpu ) ] == false) { - Qcpu = rtems_malloc( sizeof(CPU) ); - //rtems_malloc does not return a errnum in case of failure - Qcpu->cpu=*assigned_cpu; - - _Chain_Initialize_node( &Qcpu->node ); - _Chain_Append_unprotected( &Queue, &Qcpu->node ); - //Insert thread_CPU in the Queue - visited[ _Per_CPU_Get_index (assigned_cpu) ]=true; - } - } else if ( curr_state == SCHEDULER_SMP_NODE_READY) { - curr_priority = _Scheduler_Node_get_priority( (Scheduler_Node *) next ); - curr_priority = SCHEDULER_PRIORITY_PURIFY( curr_priority ); - - if ( curr_priorityBase.Base; - } - } - } + ) { + //Checks if the thread_CPU is in the affinity set of the node + + if ( curr_state == SCHEDULER_SMP_NODE_SCHEDULED) { + assigned_cpu = _Thread_Get_CPU( node->Base.Base.user ); + + if ( visited[ _Per_CPU_Get_index( assigned_cpu ) ] == false) { + Qcpu = rtems_malloc( sizeof(CPU) ); + //rtems_malloc does not return a errnum in case of failure + Qcpu->cpu=*assigned_cpu; + + _Chain_Initialize_node( &Qcpu->node ); + _Chain_Append_unprotected( &Queue, &Qcpu->node ); + //Insert thread_CPU in the Queue + visited[ _Per_CPU_Get_index (assigned_cpu) ]=true; + } + } + else if ( curr_state == SCHEDULER_SMP_NODE_READY) { + curr_priority = _Scheduler_Node_get_priority( (Scheduler_Node *) next ); + curr_priority = SCHEDULER_PRIORITY_PURIFY( curr_priority ); + + if ( curr_priorityBase.Base; + } + } + } next = _Chain_Next( next ); } - } + } if ( ret != filter) { @@ -202,27 +207,41 @@ static inline Scheduler_Node *_Scheduler_strong_APA_Get_lowest_scheduled( uint32_t cpu_max; uint32_t cpu_index; - CPU *Qcpu; Priority_Control filter_priority; Per_CPU_Control *curr_CPU; + Per_CPU_Control *next_cpu; + Per_CPU_Control *cpu_to_preempt; Thread_Control *curr_thread; Scheduler_Node *curr_node; Scheduler_Node *ret; - Chain_Control Queue; Priority_Control max_priority; Priority_Control curr_priority; - bool *visited; + + Scheduler_strong_APA_Node *curr_strong_node; //Current Strong_APA_Node + Scheduler_strong_APA_Node *filter_node; + Scheduler_strong_APA_Context *self; + Per_CPU_Control *queue; //Array of Cpu that serves as a queue + bool *visited; //Array of bool values each corresponding to a cpu. + //Node that has a CPU in its affinity set which gets used for backtracking. + Scheduler_strong_APA_Node *caller; //Caller node for a CPU. - Scheduler_strong_APA_Context *self; + //Denotes front and rear of the queue + uint32_t front; + uint32_t rear; + + front = 0; + rear = -1; - self = _Scheduler_strong_APA_Get_self( context ); - visited = self->visited->visited; + queue = self->queue->Cpu; + caller = Caller->caller; - Scheduler_strong_APA_Node *Scurr_node; //Current Strong_APA_Node - Scheduler_strong_APA_Node *filter_node; + filter_priority = _Scheduler_Node_get_priority( filter_base ); + filter_priority = SCHEDULER_PRIORITY_PURIFY( filter_priority ); + + self = _Scheduler_strong_APA_Get_self( context ); ret = NULL; //To remove compiler warning. //ret would always point to the node with the lowest priority @@ -232,10 +251,11 @@ static inline Scheduler_Node *_Scheduler_strong_APA_Get_lowest_scheduled( max_priority_num = 0;//Max (Lowest) priority encountered so far. + //This assert makes sure that there always exist an element in the + // Queue when we start the queue traversal. _Assert( !_Processor_mask_Zero( &filter_node->affinity ) ); cpu_max = _SMP_Get_processor_maximum(); - _Chain_Initialize_empty(&Queue); for ( cpu_index = 0 ; cpu_index < cpu_max ; ++cpu_index ) { visited[ cpu_index ] = false; @@ -245,71 +265,85 @@ static inline Scheduler_Node *_Scheduler_strong_APA_Get_lowest_scheduled( Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index ); if ( _Per_CPU_Is_processor_online( cpu ) ) { - Qcpu = rtems_malloc( sizeof(CPU) ); //No errornum returned in case of failure - Qcpu->cpu = *cpu; - - _Chain_Initialize_node( &Qcpu->node ); - _Chain_Append_unprotected( &Queue, &Qcpu->node ); - //Insert cpu in the Queue + rear = rear + 1; + queue[ rear ] = cpu; visited[ cpu_index ] = true; + caller[ cpu_index ] = filter_base; } } } - while( !_Chain_Is_empty( &Queue) ) { - Qcpu = (CPU*) _Chain_Get_first_unprotected( &Queue ); - curr_CPU = &Qcpu->cpu; + while( front <= rear ) { + curr_CPU = queue[ front ]; + front = front + 1; + curr_thread = curr_CPU->executing; - curr_node = _Thread_Scheduler_get_home_node( curr_thread ); curr_priority = _Scheduler_Node_get_priority( curr_node ); - curr_priority = SCHEDULER_PRIORITY_PURIFY( curr_priority ); + curr_priority = SCHEDULER_PRIORITY_PURIFY( curr_priority ); + + curr_strong_node = _Scheduler_strong_APA_Node_downcast( curr_node ); if ( curr_priority > max_priority_num) { ret = curr_node; max_priority_num = curr_priority; - if( curr_priority > SCHEDULER_PRIORITY_PURIFY( _Scheduler_Node_get_priority( filter_base ) ) ) + if( curr_priority > filter_priority) { - cpu_to_preempt=curr_CPU; + cpu_to_preempt = curr_CPU; } } - Scurr_node = _Scheduler_strong_APA_Node_downcast( curr_node ); if ( !curr_thread->is_idle ) { for ( cpu_index = 0 ; cpu_index < cpu_max ; ++cpu_index ) { if ( _Processor_mask_Is_set( &Scurr_node->affinity, cpu_index ) ) { //Checks if the thread_CPU is in the affinity set of the node Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index ); if ( _Per_CPU_Is_processor_online( cpu ) && visited[ cpu_index ] == false ) { - - Qcpu = rtems_malloc( sizeof(CPU) ); - Qcpu->cpu = *cpu; - - _Chain_Initialize_node( &Qcpu->node ); - _Chain_Append_unprotected( &Queue, &Qcpu->node ); - //Insert the cpu in the affinty set of curr_thread in the Queue + rear = rear + 1; + queue[ rear ] = cpu; visited[ cpu_index ] = true; + caller[ cpu_index ] = curr_node; } } } } - } + } - filter_priority = _Scheduler_Node_get_priority( filter_base ); - filter_priority = SCHEDULER_PRIORITY_PURIFY( filter_priority ); - - if ( ret->Priority.value < filter_priority ) { - //Lowest priority task found has higher priority - // than filter_base. - //So, filter_base remains unassigned - //No task shifting. - } - - else { + if( ret->Priority.value > filter_priority ) { //Backtrack on the path from //_Thread_Get_CPU(ret->user) to ret, shifting along every task + + curr_node = caller[ _Per_CPU_Get_index(cpu_to_preempt) ]; + curr_cpu = _Thread_Get_CPU( curr_node->user ); + + curr_node = caller [ _Per_CPU_Get_index( curr_cpu ) ]; + curr_cpu = _Thread_Get_CPU( curr_node->user ); + + do{ + next_cpu = _Thread_Get_CPU( curr_node->user ); + + _Scheduler_SMP_Preempt( + context, + curr_node, + _Thread_Scheduler_get_home_node( curr_cpu->executing ), + _Scheduler_strong_APA_Allocate_processor + ); + + curr_cpu = _Per_CPU_Get_index( next_cpu ); + curr_node = caller[ curr_cpu ]; + + }while( curr_node != filter_base ); + + _Scheduler_SMP_Preempt( + context, + curr_node, + _Thread_Scheduler_get_home_node( curr_cpu->executing ), + _Scheduler_strong_APA_Allocate_processor + ); + + filter_base = caller[ _Per_CPU_Get_index(cpu_to_preempt) ]; } return ret; } From 9cc11fb283114f032c34602552c59fe51c1b0a58 Mon Sep 17 00:00:00 2001 From: richidubey Date: Thu, 6 Aug 2020 20:32:51 +0530 Subject: [PATCH 9/9] Added configuration definitions --- cpukit/include/rtems/scheduler.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cpukit/include/rtems/scheduler.h b/cpukit/include/rtems/scheduler.h index b84b29fd209..3ec9b3aeabb 100644 --- a/cpukit/include/rtems/scheduler.h +++ b/cpukit/include/rtems/scheduler.h @@ -257,7 +257,9 @@ #define RTEMS_SCHEDULER_STRONG_APA( name, prio_count ) \ static struct { \ Scheduler_strong_APA_Context Base; \ - Scheduler_strong_APA_CPU CPU[ CONFIGURE_MAXIMUM_PROCESSORS ]; + Scheduler_strong_APA_Queue Cpu[ CONFIGURE_MAXIMUM_PROCESSORS ]; \ + Scheduler_strong_APA_Caller caller[ CONFIGURE_MAXIMUM_PROCESSORS ]; \ + Scheduler_strong_APA_Visited visited[ CONFIGURE_MAXIMUM_PROCESSORS ]; } SCHEDULER_STRONG_APA_CONTEXT_NAME( name ) #define RTEMS_SCHEDULER_TABLE_STRONG_APA( name, obj_name ) \