[PATCH v4] Pre-Release Strong-APA
Gedare Bloom
gedare at rtems.org
Wed Aug 26 20:48:18 UTC 2020
The subject line comes through fine, but your mail reader is picking
up some in-reply-to field probably. I think you can change this with
some threading options in either git-format-patch or git-send-email.
On Wed, Aug 26, 2020 at 2:39 PM Richi Dubey <richidubey at gmail.com> wrote:
>
> I used this command:
>
> richi at YouAreAmazing:~/quick-start/src/rtems$ git send-email --to=devel at rtems.org v4-0001-Pre-Release-Strong-APA.patch
> v4-0001-Pre-Release-Strong-APA.patch
> (mbox) Adding cc: Richi Dubey <richidubey at gmail.com> from line 'From: Richi Dubey <richidubey at gmail.com>'
>
> From: Richi Dubey <richidubey at gmail.com>
> To: devel at rtems.org
> Cc: Richi Dubey <richidubey at gmail.com>
> Subject: [PATCH v4] Pre-Release Strong-APA
> Date: Thu, 27 Aug 2020 02:03:33 +0530
> Message-Id: <20200826203333.8491-1-richidubey at gmail.com>
> X-Mailer: git-send-email 2.17.1
>
> Send this email? ([y]es|[n]o|[q]uit|[a]ll): y
> OK. Log says:
> Server: smtp.gmail.com
> MAIL FROM:<richidubey at gmail.com>
> RCPT TO:<devel at rtems.org>
> RCPT TO:<richidubey at gmail.com>
> From: Richi Dubey <richidubey at gmail.com>
> To: devel at rtems.org
> Cc: Richi Dubey <richidubey at gmail.com>
> Subject: [PATCH v4] Pre-Release Strong-APA
> Date: Thu, 27 Aug 2020 02:03:33 +0530
> Message-Id: <20200826203333.8491-1-richidubey at gmail.com>
> X-Mailer: git-send-email 2.17.1
>
> Result: 250
>
> On Thu, Aug 27, 2020 at 2:07 AM Richi Dubey <richidubey at gmail.com> wrote:
>>
>> I've been trying to send the v4 but the patch keeps coming in v3 mail thread :(.
>>
>> What am I missing?
>>
>> On Thu, Aug 27, 2020 at 2:03 AM Richi Dubey <richidubey at gmail.com> wrote:
>>>
>>> ---
>>> cpukit/include/rtems/scheduler.h | 6 +-
>>> .../include/rtems/score/schedulerstrongapa.h | 152 ++-
>>> cpukit/score/src/schedulerstrongapa.c | 901 ++++++++++++++----
>>> 3 files changed, 828 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
>>> - * <rtems at 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..429bbacece 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
>>> - * <rtems at 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,754 @@
>>> #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;
>>> + 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 < sizeof(Context->CPU)
>>> + _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.
>>> + if (
>>> + _Processor_mask_Is_set(&node->Affinity, _Per_CPU_Get_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 of 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 affinty 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 ); //Removed from Ready
>>> + _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;
>>> +
>>> + 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
>>> + );
>>>
>>> - (void) node;
>>> + curr_node = next_node;
>>> + curr_strong_node = _Scheduler_strong_APA_Node_downcast( curr_node );
>>>
>>> - return (Scheduler_Node *) _Scheduler_priority_Ready_queue_first(
>>> - &self->Bit_map,
>>> - &self->Ready[ 0 ]
>>> - );
>>> + 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_Register_idle(
>>> Scheduler_Context *context,
>>> - Scheduler_Node *node,
>>> - Priority_Control insert_priority
>>> + Scheduler_Node *idle_base,
>>> + Per_CPU_Control *cpu
>>> )
>>> {
>>> - return _Scheduler_SMP_Enqueue_scheduled(
>>> + (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;
>>> +
>>> + 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 +793,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 +811,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 +851,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 +886,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 at rtems.org
> http://lists.rtems.org/mailman/listinfo/devel
More information about the devel
mailing list