Hi, Thanks for your reviews so far. This patch implements the reviews suggested in the following links:
https://lists.rtems.org/pipermail/devel/2020-August/061578.html https://github.com/richidubey/rtems/pull/7/files and my comments on resolving the issues are here: https://lists.rtems.org/pipermail/devel/2020-August/061614.html Please let me know how to improve this patch. Thanks, Richi. On Thu, Aug 27, 2020 at 7:10 PM Richi Dubey <richidu...@gmail.com> wrote: > From 18982f8084f8d603ea0492e809d759d3c09ea263 Mon Sep 17 00:00:00 2001 > From: Richi Dubey <richidu...@gmail.com> > Date: Thu, 27 Aug 2020 19:07:46 +0530 > Subject: [PATCH v5] Pre-Release Strong-APA > > --- > cpukit/include/rtems/scheduler.h | 6 +- > .../include/rtems/score/schedulerstrongapa.h | 152 ++- > cpukit/score/src/schedulerstrongapa.c | 893 ++++++++++++++---- > 3 files changed, 820 insertions(+), 231 deletions(-) > > diff --git a/cpukit/include/rtems/scheduler.h > b/cpukit/include/rtems/scheduler.h > index 955a83cfb4..6a05c2798a 100644 > --- a/cpukit/include/rtems/scheduler.h > +++ b/cpukit/include/rtems/scheduler.h > @@ -257,16 +257,14 @@ > #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 ) \ > { \ > &SCHEDULER_STRONG_APA_CONTEXT_NAME( name ).Base.Base.Base, \ > SCHEDULER_STRONG_APA_ENTRY_POINTS, \ > - RTEMS_ARRAY_SIZE( \ > - SCHEDULER_STRONG_APA_CONTEXT_NAME( name ).Ready \ > - ) - 1, \ > + SCHEDULER_STRONG_APA_MAXIMUM_PRIORITY, \ > ( obj_name ) \ > SCHEDULER_CONTROL_IS_NON_PREEMPT_MODE_SUPPORTED( false ) \ > } > diff --git a/cpukit/include/rtems/score/schedulerstrongapa.h > b/cpukit/include/rtems/score/schedulerstrongapa.h > index 0ac28cb439..cfd79e932a 100644 > --- a/cpukit/include/rtems/score/schedulerstrongapa.h > +++ b/cpukit/include/rtems/score/schedulerstrongapa.h > @@ -6,31 +6,47 @@ > * @brief Strong APA Scheduler API > */ > > -/* > - * Copyright (c) 2013, 2018 embedded brains GmbH. All rights reserved. > +/* SPDX-License-Identifier: BSD-2-Clause > * > - * embedded brains GmbH > - * Dornierstr. 4 > - * 82178 Puchheim > - * Germany > - * <rt...@embedded-brains.de> > + * Copyright (C) 2020 Richi Dubey > + * Copyright (c) 2013, 2018 embedded brains GmbH > * > - * The license and distribution terms for this file may be > - * found in the file LICENSE in this distribution or at > - * http://www.rtems.org/license/LICENSE. > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * 1. Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * 2. Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in the > + * documentation and/or other materials provided with the distribution. > + * > + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS > "AS IS" > + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, > THE > + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR > PURPOSE > + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS > BE > + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR > + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF > + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR > BUSINESS > + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN > + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) > + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF > THE > + * POSSIBILITY OF SUCH DAMAGE. > */ > > #ifndef _RTEMS_SCORE_SCHEDULERSTRONGAPA_H > #define _RTEMS_SCORE_SCHEDULERSTRONGAPA_H > > #include <rtems/score/scheduler.h> > -#include <rtems/score/schedulerpriority.h> > #include <rtems/score/schedulersmp.h> > +#include <rtems/score/percpu.h> > > #ifdef __cplusplus > extern "C" { > #endif /* __cplusplus */ > > +#define STRONG_SCHEDULER_NODE_OF_CHAIN( node ) \ > + RTEMS_CONTAINER_OF( node, Scheduler_strong_APA_Node, Ready_node ) > + > /** > * @defgroup RTEMSScoreSchedulerStrongAPA Strong APA Scheduler > * > @@ -38,42 +54,96 @@ 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 > + * Cerqueira et al. in Linux's Processor Affinity API, Refined: > + * Shifting Real-Time Tasks Towards Higher Schedulability. > * > + * The scheduled and ready nodes are accessed via the > + * Scheduler_strong_APA_Context::Ready which helps in backtracking when a > + * node which is executing on a CPU gets blocked. New node is allocated to > + * the cpu by checking all the executing nodes in the affinity set of the > + * node and the subsequent nodes executing on the processors in its > + * affinity set. > * @{ > */ > > /** > - * @brief Scheduler context specialization for Strong APA > - * schedulers. > + * @brief Scheduler node specialization for Strong APA schedulers. > */ > typedef struct { > - Scheduler_SMP_Context Base; > - Priority_bit_map_Control Bit_map; > - Chain_Control Ready[ RTEMS_ZERO_LENGTH_ARRAY ]; > -} Scheduler_strong_APA_Context; > + /** > + * @brief SMP scheduler node. > + */ > + Scheduler_SMP_Node Base; > + > + /** > + * @brief Chain node for Scheduler_strong_APA_Context::Ready. > + */ > + Chain_Node Ready_node; > + > + /** > + * @brief CPU that this node would preempt in the backtracking part of > + * _Scheduler_strong_APA_Get_highest_ready and > + * _Scheduler_strong_APA_Do_Enqueue. > + */ > + Per_CPU_Control *cpu_to_preempt; > + > + /** > + * @brief The associated affinity set of this node. > + */ > + Processor_mask Affinity; > +} Scheduler_strong_APA_Node; > + > > /** > - * @brief Scheduler node specialization for Strong APA > - * schedulers. > + * @brief CPU related variables and a CPU_Control to implement BFS. > + */ > +typedef struct > +{ > + /** > + * @brief CPU in a queue. > + */ > + Per_CPU_Control *cpu; > + > + /** > + * @brief The node that would preempt this CPU. > + */ > + Scheduler_Node *preempting_node; > + > + /** > + * @brief Whether or not this cpu has been added to the queue > + * (visited in BFS). > + */ > + bool visited; > + > + /** > + * @brief The node currently executing on this cpu. > + */ > + Scheduler_Node *executing; > +} Scheduler_strong_APA_CPU; > + > + /** > + * @brief Scheduler context and node definition for Strong APA scheduler. > */ > typedef struct { > + /** > + * @brief @see Scheduler_SMP_Context. > + */ > + Scheduler_SMP_Context Base; > + > /** > - * @brief SMP scheduler node. > + * @brief Chain of all the ready and scheduled nodes present in > + * the Strong APA scheduler. > */ > - Scheduler_SMP_Node Base; > + Chain_Control Ready; > > /** > - * @brief The associated ready queue of this node. > + * @brief Struct with important variables for each cpu. > */ > - Scheduler_priority_Ready_queue Ready_queue; > -} Scheduler_strong_APA_Node; > + Scheduler_strong_APA_CPU CPU[ RTEMS_ZERO_LENGTH_ARRAY ]; > +} Scheduler_strong_APA_Context; > + > +#define SCHEDULER_STRONG_APA_MAXIMUM_PRIORITY 255 > > /** > * @brief Entry points for the Strong APA Scheduler. > @@ -100,8 +170,8 @@ typedef struct { > _Scheduler_default_Release_job, \ > _Scheduler_default_Cancel_job, \ > _Scheduler_default_Tick, \ > - _Scheduler_SMP_Start_idle \ > - SCHEDULER_OPERATION_DEFAULT_GET_SET_AFFINITY \ > + _Scheduler_SMP_Start_idle, \ > + _Scheduler_strong_APA_Set_affinity \ > } > > /** > @@ -168,7 +238,7 @@ void _Scheduler_strong_APA_Update_priority( > /** > * @brief Asks for help. > * > - * @param scheduler The scheduler control instance. > + * @param scheduler The scheduler control instance. > * @param the_thread The thread that asks for help. > * @param node The node of @a the_thread. > * > @@ -246,6 +316,20 @@ void _Scheduler_strong_APA_Yield( > Scheduler_Node *node > ); > > +/** > + * @brief Sets the affinity . > + * > + * @param scheduler The scheduler control instance. > + * @param the_thread The thread to yield. > + * @param[in, out] node The node of @a the_thread. > + */ > +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 924cd86412..4d4e38bf0d 100644 > --- a/cpukit/score/src/schedulerstrongapa.c > +++ b/cpukit/score/src/schedulerstrongapa.c > @@ -6,18 +6,31 @@ > * @brief Strong APA Scheduler Implementation > */ > > -/* > - * Copyright (c) 2013, 2016 embedded brains GmbH. All rights reserved. > +/* SPDX-License-Identifier: BSD-2-Clause > + * > + * Copyright (C) 2020 Richi Dubey > + * Copyright (c) 2013, 2018 embedded brains GmbH > * > - * embedded brains GmbH > - * Dornierstr. 4 > - * 82178 Puchheim > - * Germany > - * <rt...@embedded-brains.de> > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * 1. Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * 2. Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in the > + * documentation and/or other materials provided with the distribution. > * > - * 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. > + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS > "AS IS" > + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, > THE > + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR > PURPOSE > + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS > BE > + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR > + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF > + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR > BUSINESS > + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN > + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) > + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF > THE > + * POSSIBILITY OF SUCH DAMAGE. > */ > > #ifdef HAVE_CONFIG_H > @@ -25,301 +38,746 @@ > #endif > > #include <rtems/score/schedulerstrongapa.h> > -#include <rtems/score/schedulerpriorityimpl.h> > #include <rtems/score/schedulersmpimpl.h> > +#include <rtems/score/assert.h> > > -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( > +static inline void _Scheduler_strong_APA_Do_update( > Scheduler_Context *context, > - Scheduler_Node *scheduled_to_ready > + Scheduler_Node *node, > + Priority_Control new_priority > ) > { > - 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_SMP_Node *smp_node; > + (void) context; > + > + smp_node = _Scheduler_SMP_Node_downcast( node ); > + _Scheduler_SMP_Node_update_priority( smp_node, new_priority ); > } > > -static void _Scheduler_strong_APA_Move_from_ready_to_scheduled( > +/* > + * Returns true if the Strong APA scheduler has ready nodes > + * available for scheduling. > + */ > +static inline bool > + _Scheduler_strong_APA_Has_ready( Scheduler_Context *context ) > +{ > + Scheduler_strong_APA_Context *self; > + const Chain_Node *tail; > + Chain_Node *next; > + Scheduler_strong_APA_Node *node; > + > + self = _Scheduler_strong_APA_Get_self( context ); > + tail = _Chain_Immutable_tail( &self->Ready ); > + next = _Chain_First( &self->Ready ); > + > + while ( next != tail ) { > + node = (Scheduler_strong_APA_Node *) STRONG_SCHEDULER_NODE_OF_CHAIN( > next ); > + > + if ( > + _Scheduler_SMP_Node_state( &node->Base.Base ) == > + SCHEDULER_SMP_NODE_READY > + ) { > + return true; > + } > + > + next = _Chain_Next( next ); > + } > + > + return false; > +} > + > +static inline void _Scheduler_strong_APA_Allocate_processor( > Scheduler_Context *context, > - Scheduler_Node *ready_to_scheduled > + Scheduler_Node *scheduled_base, > + Scheduler_Node *victim_base, > + Per_CPU_Control *victim_cpu > ) > { > + Scheduler_strong_APA_Node *scheduled; > Scheduler_strong_APA_Context *self; > - Scheduler_strong_APA_Node *node; > - Priority_Control insert_priority; > > + (void) victim_base; > + > + scheduled = _Scheduler_strong_APA_Node_downcast( scheduled_base ); > 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 > + self->CPU[ _Per_CPU_Get_index( victim_cpu ) ].executing = > scheduled_base; > + > + _Scheduler_SMP_Allocate_processor_exact( > + context, > + &( scheduled->Base.Base ), > + NULL, > + victim_cpu > ); > - insert_priority = _Scheduler_SMP_Node_priority( &node->Base.Base ); > +} > + > +/* > + * Finds and returns the highest ready node present by accessing the > + * _Strong_APA_Context->CPU with front and rear values. > + */ > +static inline Scheduler_Node * _Scheduler_strong_APA_Find_highest_ready( > + Scheduler_strong_APA_Context *self, > + uint32_t front, > + uint32_t rear > +) > +{ > + Scheduler_Node *highest_ready; > + Scheduler_strong_APA_CPU *CPU; > + const Chain_Node *tail; > + Chain_Node *next; > + uint32_t index_assigned_cpu; > + uint32_t index_curr_cpu; > + Scheduler_strong_APA_Node *node; > + Priority_Control min_priority_num; > + Priority_Control curr_priority; > + Per_CPU_Control *assigned_cpu; > + Scheduler_SMP_Node_state curr_state; > + Per_CPU_Control *curr_CPU; > + bool first_task; > + > + CPU = self->CPU; > + /* > + * When the first task accessed has nothing to compare its priority > against > + * So, it is the task with the highest priority witnessed so far. > + */ > + first_task = true; > + > + _Assert( rear < CONFIGURE_MAXIMUM_PROCESSOR ); > + > + while( front <= rear ) { > + curr_CPU = CPU[ front ].cpu; > + front = front + 1; > + > + tail = _Chain_Immutable_tail( &self->Ready ); > + next = _Chain_First( &self->Ready ); > + > + while ( next != tail ) { > + node = (Scheduler_strong_APA_Node*) STRONG_SCHEDULER_NODE_OF_CHAIN( > next ); > + /* Check if the curr_CPU is in the affinity set of the node. */ > + index_curr_cpu = _Per_CPU_Get_index( curr_CPU ); > + if ( > + _Processor_mask_Is_set( &node->Affinity, index_curr_cpu ) > + ) { > + curr_state = _Scheduler_SMP_Node_state( &node->Base.Base ); > + > + if ( curr_state == SCHEDULER_SMP_NODE_SCHEDULED ) { > + assigned_cpu = _Thread_Get_CPU( node->Base.Base.user ); > + index_assigned_cpu = _Per_CPU_Get_index( assigned_cpu ); > + > + if ( CPU[ index_assigned_cpu ].visited == false ) { > + rear = rear + 1; > + CPU[ rear ].cpu = assigned_cpu; > + CPU[ index_assigned_cpu ].visited = true; > + /* > + * The curr CPU of the queue invoked this node to add its CPU > + * that it is executing on to the queue. So this node might > get > + * preempted because of the invoker curr_CPU and this curr_CPU > + * is the CPU that node should preempt in case this node > + * gets preempted. > + */ > + node->cpu_to_preempt = curr_CPU; > + } > + } > + else if ( curr_state == SCHEDULER_SMP_NODE_READY ) { > + curr_priority = _Scheduler_Node_get_priority( &node->Base.Base > ); > + curr_priority = SCHEDULER_PRIORITY_PURIFY( curr_priority ); > + > + if ( first_task == true || curr_priority < min_priority_num ) { > + min_priority_num = curr_priority; > + highest_ready = &node->Base.Base; > + first_task = false; > + /* > + * In case curr_CPU is filter_CPU, we need to store the > + * cpu_to_preempt value so that we go back to SMP_* > + * function, rather than preempting the node ourselves. > + */ > + node->cpu_to_preempt = curr_CPU; > + } > + } > + } > + next = _Chain_Next( next ); > + } > + } > + > + return highest_ready; > +} > + > +static inline void _Scheduler_strong_APA_Move_from_ready_to_scheduled( > + Scheduler_Context *context, > + Scheduler_Node *ready_to_scheduled > +) > +{ > + Priority_Control insert_priority; > + > + insert_priority = _Scheduler_SMP_Node_priority( ready_to_scheduled ); > 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_Insert_scheduled( > + context, > + ready_to_scheduled, > + insert_priority > ); > } > > -static void _Scheduler_strong_APA_Insert_ready( > +/* > + * Implement the BFS Algorithm for task departure to get the highest > ready task > + * for a particular CPU, returns the highest ready Scheduler_Node > + * Scheduler_Node filter here pointst to the victim node that is blocked > + * resulting which this function is called. > + */ > +static inline Scheduler_Node *_Scheduler_strong_APA_Get_highest_ready( > Scheduler_Context *context, > - Scheduler_Node *node_base, > - Priority_Control insert_priority > + Scheduler_Node *filter > ) > { > Scheduler_strong_APA_Context *self; > + Per_CPU_Control *filter_cpu; > Scheduler_strong_APA_Node *node; > + Scheduler_Node *highest_ready; > + Scheduler_Node *curr_node; > + Scheduler_Node *next_node; > + Scheduler_strong_APA_CPU *CPU; > + uint32_t front; > + uint32_t rear; > + uint32_t cpu_max; > + uint32_t cpu_index; > > self = _Scheduler_strong_APA_Get_self( context ); > - node = _Scheduler_strong_APA_Node_downcast( node_base ); > + /* Denotes front and rear of the queue */ > + front = 0; > + rear = -1; > > - 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 > - ); > + filter_cpu = _Thread_Get_CPU( filter->user ); > + CPU = self->CPU; > + cpu_max = _SMP_Get_processor_maximum(); > + > + for ( cpu_index = 0 ; cpu_index < cpu_max ; ++cpu_index ) { > + CPU[ cpu_index ].visited = false; > } > + > + rear = rear + 1; > + CPU[ rear ].cpu = filter_cpu; > + CPU[ _Per_CPU_Get_index( filter_cpu ) ].visited = true; > + > + highest_ready = _Scheduler_strong_APA_Find_highest_ready( > + self, > + front, > + rear > + ); > + > + if ( highest_ready != filter ) { > + /* > + * Backtrack on the path from > + * filter_cpu to highest_ready, shifting along every task. > + */ > + > + node = _Scheduler_strong_APA_Node_downcast( highest_ready ); > + /* > + * Highest ready is not just directly reachable from the victim cpu > + * So there is need for task shifting . > + */ > + while ( node->cpu_to_preempt != filter_cpu ) { > + curr_node = &node->Base.Base; > + next_node = CPU[ _Per_CPU_Get_index( node->cpu_to_preempt ) > ].executing; > + > + _Scheduler_SMP_Preempt( > + context, > + curr_node, > + next_node, > + _Scheduler_strong_APA_Allocate_processor > + ); > + > + if( curr_node == highest_ready ) { > + _Scheduler_strong_APA_Move_from_ready_to_scheduled( context, > curr_node ); > + } > + > + node = _Scheduler_strong_APA_Node_downcast( next_node ); > + } > + /* > + * To save the last node so that the caller SMP_* function > + * can do the allocation > + */ > + curr_node = &node->Base.Base; > + highest_ready = curr_node; > + } > + > + return highest_ready; > } > > -static void _Scheduler_strong_APA_Extract_from_ready( > +/* > + * Checks the lowest scheduled directly reachable task > + */ > +static inline Scheduler_Node *_Scheduler_strong_APA_Get_lowest_scheduled( > Scheduler_Context *context, > - Scheduler_Node *the_thread > + Scheduler_Node *filter_base > ) > { > - 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 > - ); > + uint32_t cpu_max; > + uint32_t cpu_index; > + Scheduler_Node *curr_node; > + Scheduler_Node *lowest_scheduled; > + Priority_Control max_priority_num; > + Priority_Control curr_priority; > + Scheduler_strong_APA_Node *filter_strong_node; > + Scheduler_strong_APA_Context *self; > + > + self = _Scheduler_strong_APA_Get_self( context ); > + lowest_scheduled = NULL; /* To remove compiler warning */ > + max_priority_num = 0; /* Max (Lowest) priority encountered so far */ > + filter_strong_node = _Scheduler_strong_APA_Node_downcast( filter_base ); > + > + /* lowest_scheduled is NULL if affinity of a node is 0 */ > + _Assert( !_Processor_mask_Zero( &filter_strong_node->Affinity ) ); > + cpu_max = _SMP_Get_processor_maximum(); > + > + for ( cpu_index = 0 ; cpu_index < cpu_max ; ++cpu_index ) { > + /* Checks if the CPU is in the affinity set of filter_strong_node */ > + if ( _Processor_mask_Is_set( &filter_strong_node->Affinity, cpu_index > ) ) { > + Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index ); > + > + if ( _Per_CPU_Is_processor_online( cpu ) ) { > + curr_node = self->CPU[ _Per_CPU_Get_index( cpu ) ].executing; > + curr_priority = _Scheduler_Node_get_priority( curr_node ); > + curr_priority = SCHEDULER_PRIORITY_PURIFY( curr_priority ); > + > + if ( curr_priority > max_priority_num ) { > + lowest_scheduled = curr_node; > + max_priority_num = curr_priority; > + } > + } > + } > + } > + > + _Assert( lowest_scheduled != NULL ); > + return lowest_scheduled; > } > > -static void _Scheduler_strong_APA_Do_update( > +static inline 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 Ready since the node could go in the READY > state */ > } > > -static Scheduler_strong_APA_Context * > -_Scheduler_strong_APA_Get_context( const Scheduler_Control *scheduler ) > +static inline 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->Ready ) ); > + _Assert( !_Chain_Is_node_off_chain( &node->Ready_node ) ); > + > + _Chain_Extract_unprotected( &node->Ready_node ); > + _Chain_Set_off_chain( &node->Ready_node ); > } > > -void _Scheduler_strong_APA_Initialize( const Scheduler_Control *scheduler > ) > +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_Get_context( scheduler ); > + Scheduler_strong_APA_Context *self; > + Scheduler_strong_APA_Node *node; > > - _Scheduler_SMP_Initialize( &self->Base ); > - _Priority_bit_map_Initialize( &self->Bit_map ); > - _Scheduler_priority_Ready_queue_initialize( > - &self->Ready[ 0 ], > - scheduler->maximum_priority > - ); > + self = _Scheduler_strong_APA_Get_self( context ); > + node = _Scheduler_strong_APA_Node_downcast( node_base ); > + > + if( _Chain_Is_node_off_chain( &node->Ready_node ) ) { > + _Chain_Append_unprotected( &self->Ready, &node->Ready_node ); > + } > } > > -void _Scheduler_strong_APA_Node_initialize( > - const Scheduler_Control *scheduler, > - Scheduler_Node *node, > - Thread_Control *the_thread, > - Priority_Control priority > +static inline void _Scheduler_strong_APA_Move_from_scheduled_to_ready( > + Scheduler_Context *context, > + Scheduler_Node *scheduled_to_ready > ) > { > - Scheduler_Context *context; > - Scheduler_strong_APA_Context *self; > - Scheduler_strong_APA_Node *the_node; > + Priority_Control insert_priority; > > - the_node = _Scheduler_strong_APA_Node_downcast( node ); > - _Scheduler_SMP_Node_initialize( > - scheduler, > - &the_node->Base, > - the_thread, > - priority > - ); > + _Scheduler_SMP_Extract_from_scheduled( context, scheduled_to_ready ); > + insert_priority = _Scheduler_SMP_Node_priority( scheduled_to_ready ); > > - 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_Insert_ready( > + context, > + scheduled_to_ready, > + insert_priority > ); > } > > -static bool _Scheduler_strong_APA_Has_ready( Scheduler_Context *context ) > +static inline Scheduler_Node* _Scheduler_strong_APA_Get_lowest_reachable( > + Scheduler_strong_APA_Context *self, > + uint32_t front, > + uint32_t rear, > + Per_CPU_Control **cpu_to_preempt > +) > { > - Scheduler_strong_APA_Context *self = > - _Scheduler_strong_APA_Get_self( context ); > + Scheduler_Node *lowest_reachable; > + Priority_Control max_priority_num; > + uint32_t cpu_max; > + uint32_t cpu_index; > + Thread_Control *curr_thread; > + Per_CPU_Control *curr_CPU; > + Priority_Control curr_priority; > + Scheduler_Node *curr_node; > + Scheduler_strong_APA_Node *curr_strong_node; /* Current > Strong_APA_Node */ > + Scheduler_strong_APA_CPU *CPU; > + > + max_priority_num = 0; /* Max (Lowest) priority encountered so far */ > + CPU = self->CPU; > + cpu_max = _SMP_Get_processor_maximum(); > + > + while( front <= rear ) { > + curr_CPU = CPU[ front ].cpu; > + front = front + 1; > + > + curr_node = CPU[ _Per_CPU_Get_index( curr_CPU ) ].executing; > + curr_thread = curr_node->user; > + > + curr_priority = _Scheduler_Node_get_priority( curr_node ); > + curr_priority = SCHEDULER_PRIORITY_PURIFY( curr_priority ); > + > + curr_strong_node = _Scheduler_strong_APA_Node_downcast( curr_node ); > + > + if ( curr_priority > max_priority_num ) { > + lowest_reachable = curr_node; > + max_priority_num = curr_priority; > + *cpu_to_preempt = curr_CPU; > + } > + > + if ( !curr_thread->is_idle ) { > + for ( cpu_index = 0 ; cpu_index < cpu_max ; ++cpu_index ) { > + if ( _Processor_mask_Is_set( &curr_strong_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 ) && > + CPU[ cpu_index ].visited == false ) > + { > + rear = rear + 1; > + CPU[ rear ].cpu = cpu; > + CPU[ cpu_index ].visited = true; > + CPU[ cpu_index ].preempting_node = curr_node; > + } > + } > + } > + } > + } > > - return !_Priority_bit_map_Is_empty( &self->Bit_map ); > + return lowest_reachable; > } > > -static Scheduler_Node *_Scheduler_strong_APA_Get_highest_ready( > +static inline bool _Scheduler_strong_APA_Do_enqueue( > Scheduler_Context *context, > - Scheduler_Node *node > + Scheduler_Node *lowest_reachable, > + Scheduler_Node *node, > + Priority_Control insert_priority, > + Per_CPU_Control *cpu_to_preempt > ) > { > - Scheduler_strong_APA_Context *self = > - _Scheduler_strong_APA_Get_self( context ); > + bool needs_help; > + Priority_Control node_priority; > + Priority_Control lowest_priority; > + Scheduler_strong_APA_CPU *CPU; > + Scheduler_Node *curr_node; > + Scheduler_strong_APA_Node *curr_strong_node; /* Current > Strong_APA_Node */ > + Per_CPU_Control *curr_CPU; > + Scheduler_strong_APA_Context *self; > + Scheduler_Node *next_node; > > - (void) node; > + self = _Scheduler_strong_APA_Get_self( context ); > + CPU = self->CPU; > + > + node_priority = _Scheduler_Node_get_priority( node ); > + node_priority = SCHEDULER_PRIORITY_PURIFY( node_priority ); > + > + lowest_priority = _Scheduler_Node_get_priority( lowest_reachable ); > + lowest_priority = SCHEDULER_PRIORITY_PURIFY( lowest_priority ); > + > + if( lowest_priority > node_priority ) { > + /* > + * Backtrack on the path from > + * _Thread_Get_CPU(lowest_reachable->user) to lowest_reachable, > shifting > + * along every task > + */ > + > + curr_node = CPU[ _Per_CPU_Get_index( cpu_to_preempt ) > ].preempting_node; > + curr_strong_node = _Scheduler_strong_APA_Node_downcast( curr_node ); > + curr_strong_node->cpu_to_preempt = cpu_to_preempt; > + > + /* Save which cpu to preempt in cpu_to_preempt value of the node */ > + while ( curr_node != node ) { > + curr_CPU = _Thread_Get_CPU( curr_node->user ); > + curr_node = CPU[ _Per_CPU_Get_index( curr_CPU ) ].preempting_node; > + curr_strong_node = _Scheduler_strong_APA_Node_downcast( curr_node ); > + curr_strong_node->cpu_to_preempt = curr_CPU; > + } > + > + curr_CPU = curr_strong_node->cpu_to_preempt; > + next_node = CPU[ _Per_CPU_Get_index( curr_CPU ) ].executing; > + > + node_priority = _Scheduler_Node_get_priority( curr_node ); > + node_priority = SCHEDULER_PRIORITY_PURIFY( node_priority ); > + > + _Scheduler_SMP_Enqueue_to_scheduled( > + context, > + curr_node, > + node_priority, > + next_node, > + _Scheduler_SMP_Insert_scheduled, > + _Scheduler_strong_APA_Move_from_scheduled_to_ready, > + _Scheduler_strong_APA_Allocate_processor > + ); > > - return (Scheduler_Node *) _Scheduler_priority_Ready_queue_first( > - &self->Bit_map, > - &self->Ready[ 0 ] > - ); > + curr_node = next_node; > + curr_strong_node = _Scheduler_strong_APA_Node_downcast( curr_node ); > + > + while ( curr_node != lowest_reachable ) { > + curr_CPU = curr_strong_node->cpu_to_preempt; > + next_node = CPU[ _Per_CPU_Get_index( curr_CPU ) ].executing; > + /* curr_node preempts the next_node; */ > + _Scheduler_SMP_Preempt( > + context, > + curr_node, > + next_node, > + _Scheduler_strong_APA_Allocate_processor > + ); > + > + curr_node = next_node; > + curr_strong_node = _Scheduler_strong_APA_Node_downcast( curr_node ); > + } > + > + _Scheduler_strong_APA_Move_from_scheduled_to_ready( context, > lowest_reachable ); > + > + needs_help = false; > + } else { > + needs_help = true; > + } > + > + /* Add it to Ready chain since it is now either scheduled or just > ready. */ > + _Scheduler_strong_APA_Insert_ready( context,node, insert_priority ); > + > + return needs_help; > } > > -void _Scheduler_strong_APA_Block( > - const Scheduler_Control *scheduler, > - Thread_Control *the_thread, > - Scheduler_Node *node > +/* > + * BFS Algorithm for task arrival > + * Enqueue node either in the scheduled chain or in the ready chain. > + * node is the newly arrived node and is currently not scheduled. > + */ > +static inline bool _Scheduler_strong_APA_Enqueue( > + Scheduler_Context *context, > + Scheduler_Node *node, > + Priority_Control insert_priority > ) > { > - Scheduler_Context *context = _Scheduler_Get_context( scheduler ); > + Scheduler_strong_APA_Context *self; > + Scheduler_strong_APA_CPU *CPU; > + uint32_t cpu_max; > + uint32_t cpu_index; > + Per_CPU_Control *cpu_to_preempt; > + Scheduler_Node *lowest_reachable; > + Scheduler_strong_APA_Node *strong_node; > > - _Scheduler_SMP_Block( > + /* Denotes front and rear of the queue */ > + uint32_t front; > + uint32_t rear; > + > + front = 0; > + rear = -1; > + > + self = _Scheduler_strong_APA_Get_self( context ); > + strong_node = _Scheduler_strong_APA_Node_downcast( node ); > + cpu_max = _SMP_Get_processor_maximum(); > + CPU = self->CPU; > + > + for ( cpu_index = 0 ; cpu_index < cpu_max ; ++cpu_index ) { > + CPU[ cpu_index ].visited = false; > + > + /* Checks if the thread_CPU is in the affinity set of the node */ > + if ( _Processor_mask_Is_set( &strong_node->Affinity, cpu_index ) ) { > + Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index ); > + > + if ( _Per_CPU_Is_processor_online( cpu ) ) { > + rear = rear + 1; > + CPU[ rear ].cpu = cpu; > + CPU[ cpu_index ].visited = true; > + CPU[ cpu_index ].preempting_node = node; > + } > + } > + } > + > + /* > + * This assert makes sure that there always exist an element in the > + * Queue when we start the queue traversal. > + */ > + _Assert( !_Processor_mask_Zero( &strong_node->Affinity ) ); > + > + lowest_reachable = _Scheduler_strong_APA_Get_lowest_reachable( > + self, > + front, > + rear, > + &cpu_to_preempt > + ); > + > + return _Scheduler_strong_APA_Do_enqueue( > + context, > + lowest_reachable, > + node, > + insert_priority, > + cpu_to_preempt > + ); > +} > + > +static inline bool _Scheduler_strong_APA_Enqueue_scheduled( > + Scheduler_Context *context, > + Scheduler_Node *node, > + Priority_Control insert_priority > +) > +{ > + return _Scheduler_SMP_Enqueue_scheduled( > context, > - the_thread, > node, > - _Scheduler_SMP_Extract_from_scheduled, > + insert_priority, > + _Scheduler_SMP_Priority_less_equal, > _Scheduler_strong_APA_Extract_from_ready, > _Scheduler_strong_APA_Get_highest_ready, > + _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 > ); > } > > -static bool _Scheduler_strong_APA_Enqueue( > +static inline bool _Scheduler_strong_APA_Do_ask_for_help( > Scheduler_Context *context, > - Scheduler_Node *node, > - Priority_Control insert_priority > + Thread_Control *the_thread, > + Scheduler_Node *node > ) > { > - return _Scheduler_SMP_Enqueue( > + return _Scheduler_SMP_Ask_for_help( > context, > + the_thread, > node, > - insert_priority, > _Scheduler_SMP_Priority_less_equal, > _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( > +static inline void _Scheduler_strong_APA_Do_set_affinity( > Scheduler_Context *context, > - Scheduler_Node *node, > - Priority_Control insert_priority > + Scheduler_Node *node_base, > + void *arg > ) > { > - return _Scheduler_SMP_Enqueue_scheduled( > + Scheduler_strong_APA_Node *node; > + > + node = _Scheduler_strong_APA_Node_downcast( node_base ); > + node->Affinity = *( (const Processor_mask *) arg ); > +} > + > +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->Ready ); > +} > + > +void _Scheduler_strong_APA_Yield( > + const Scheduler_Control *scheduler, > + Thread_Control *thread, > + Scheduler_Node *node > +) > +{ > + Scheduler_Context *context = _Scheduler_Get_context( scheduler ); > + > + _Scheduler_SMP_Yield( > context, > + thread, > node, > - insert_priority, > - _Scheduler_SMP_Priority_less_equal, > _Scheduler_strong_APA_Extract_from_ready, > - _Scheduler_strong_APA_Get_highest_ready, > - _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_Enqueue, > + _Scheduler_strong_APA_Enqueue_scheduled > ); > } > > -void _Scheduler_strong_APA_Unblock( > +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 ); > - > - _Scheduler_SMP_Unblock( > + /* The extract from ready automatically removes the node from Ready > chain */ > + _Scheduler_SMP_Block( > context, > - the_thread, > + thread, > node, > - _Scheduler_strong_APA_Do_update, > - _Scheduler_strong_APA_Enqueue > + _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 > ); > } > > -static bool _Scheduler_strong_APA_Do_ask_for_help( > - Scheduler_Context *context, > - Thread_Control *the_thread, > - Scheduler_Node *node > +void _Scheduler_strong_APA_Unblock( > + const Scheduler_Control *scheduler, > + Thread_Control *thread, > + Scheduler_Node *node > ) > { > - return _Scheduler_SMP_Ask_for_help( > + Scheduler_Context *context = _Scheduler_Get_context( scheduler ); > + > + _Scheduler_SMP_Unblock( > 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_SMP_Get_lowest_scheduled, > - _Scheduler_SMP_Allocate_processor_lazy > + _Scheduler_strong_APA_Do_update, > + _Scheduler_strong_APA_Enqueue > ); > } > > void _Scheduler_strong_APA_Update_priority( > const Scheduler_Control *scheduler, > - Thread_Control *the_thread, > + Thread_Control *thread, > Scheduler_Node *node > ) > { > @@ -327,7 +785,7 @@ 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, > @@ -345,7 +803,11 @@ bool _Scheduler_strong_APA_Ask_for_help( > { > Scheduler_Context *context = _Scheduler_Get_context( scheduler ); > > - return _Scheduler_strong_APA_Do_ask_for_help( context, the_thread, node > ); > + return _Scheduler_strong_APA_Do_ask_for_help( > + context, > + the_thread, > + node > + ); > } > > void _Scheduler_strong_APA_Reconsider_help_request( > @@ -381,7 +843,7 @@ 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 > ); > } > > @@ -416,20 +878,65 @@ Thread_Control > *_Scheduler_strong_APA_Remove_processor( > ); > } > > -void _Scheduler_strong_APA_Yield( > +void _Scheduler_strong_APA_Node_initialize( > const Scheduler_Control *scheduler, > + Scheduler_Node *node, > Thread_Control *the_thread, > - Scheduler_Node *node > + Priority_Control priority > ) > { > - Scheduler_Context *context = _Scheduler_Get_context( scheduler ); > + Scheduler_SMP_Node *smp_node; > + Scheduler_strong_APA_Node *strong_node; > > - _Scheduler_SMP_Yield( > - context, > - the_thread, > - node, > - _Scheduler_strong_APA_Extract_from_ready, > - _Scheduler_strong_APA_Enqueue, > - _Scheduler_strong_APA_Enqueue_scheduled > + smp_node = _Scheduler_SMP_Node_downcast( node ); > + strong_node = _Scheduler_strong_APA_Node_downcast( node ); > + > + _Scheduler_SMP_Node_initialize( scheduler, smp_node, the_thread, > priority ); > + > + _Processor_mask_Assign( > + &strong_node->Affinity, > + _SMP_Get_online_processors() > ); > } > + > +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_Assign( &node->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; > +} > + > -- > 2.17.1 >
_______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel