summaryrefslogtreecommitdiffstats
path: root/cpukit/score/include/rtems/score/schedulersmpimpl.h
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/score/include/rtems/score/schedulersmpimpl.h')
-rw-r--r--cpukit/score/include/rtems/score/schedulersmpimpl.h1482
1 files changed, 0 insertions, 1482 deletions
diff --git a/cpukit/score/include/rtems/score/schedulersmpimpl.h b/cpukit/score/include/rtems/score/schedulersmpimpl.h
deleted file mode 100644
index e152eb0878..0000000000
--- a/cpukit/score/include/rtems/score/schedulersmpimpl.h
+++ /dev/null
@@ -1,1482 +0,0 @@
-/**
- * @file
- *
- * @brief SMP Scheduler Implementation
- *
- * @ingroup ScoreSchedulerSMP
- */
-
-/*
- * Copyright (c) 2013, 2017 embedded brains GmbH. All rights reserved.
- *
- * embedded brains GmbH
- * Dornierstr. 4
- * 82178 Puchheim
- * Germany
- * <rtems@embedded-brains.de>
- *
- * 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_SCHEDULERSMPIMPL_H
-#define _RTEMS_SCORE_SCHEDULERSMPIMPL_H
-
-#include <rtems/score/schedulersmp.h>
-#include <rtems/score/assert.h>
-#include <rtems/score/chainimpl.h>
-#include <rtems/score/schedulersimpleimpl.h>
-#include <rtems/bspIo.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-/**
- * @addtogroup ScoreSchedulerSMP
- *
- * The scheduler nodes can be in four states
- * - @ref SCHEDULER_SMP_NODE_BLOCKED,
- * - @ref SCHEDULER_SMP_NODE_SCHEDULED, and
- * - @ref SCHEDULER_SMP_NODE_READY.
- *
- * State transitions are triggered via basic operations
- * - _Scheduler_SMP_Enqueue(),
- * - _Scheduler_SMP_Enqueue_scheduled(), and
- * - _Scheduler_SMP_Block().
- *
- * @dot
- * digraph {
- * node [style="filled"];
- *
- * bs [label="BLOCKED"];
- * ss [label="SCHEDULED", fillcolor="green"];
- * rs [label="READY", fillcolor="red"];
- *
- * edge [label="enqueue"];
- * edge [fontcolor="darkgreen", color="darkgreen"];
- *
- * bs -> ss;
- *
- * edge [fontcolor="red", color="red"];
- *
- * bs -> rs;
- *
- * edge [label="enqueue other"];
- *
- * ss -> rs;
- *
- * edge [label="block"];
- * edge [fontcolor="black", color="black"];
- *
- * ss -> bs;
- * rs -> bs;
- *
- * edge [label="block other"];
- * edge [fontcolor="darkgreen", color="darkgreen"];
- *
- * rs -> ss;
- * }
- * @enddot
- *
- * During system initialization each processor of the scheduler instance starts
- * with an idle thread assigned to it. Lets have a look at an example with two
- * idle threads I and J with priority 5. We also have blocked threads A, B and
- * C with priorities 1, 2 and 3 respectively. The scheduler nodes are ordered
- * with respect to the thread priority from left to right in the below
- * diagrams. The highest priority node (lowest priority number) is the
- * leftmost node. Since the processor assignment is independent of the thread
- * priority the processor indices may move from one state to the other.
- *
- * @dot
- * digraph {
- * node [style="filled"];
- * edge [dir="none"];
- * subgraph {
- * rank = same;
- *
- * i [label="I (5)", fillcolor="green"];
- * j [label="J (5)", fillcolor="green"];
- * a [label="A (1)"];
- * b [label="B (2)"];
- * c [label="C (3)"];
- * i -> j;
- * }
- *
- * subgraph {
- * rank = same;
- *
- * p0 [label="PROCESSOR 0", shape="box"];
- * p1 [label="PROCESSOR 1", shape="box"];
- * }
- *
- * i -> p0;
- * j -> p1;
- * }
- * @enddot
- *
- * Lets start A. For this an enqueue operation is performed.
- *
- * @dot
- * digraph {
- * node [style="filled"];
- * edge [dir="none"];
- *
- * subgraph {
- * rank = same;
- *
- * i [label="I (5)", fillcolor="green"];
- * j [label="J (5)", fillcolor="red"];
- * a [label="A (1)", fillcolor="green"];
- * b [label="B (2)"];
- * c [label="C (3)"];
- * a -> i;
- * }
- *
- * subgraph {
- * rank = same;
- *
- * p0 [label="PROCESSOR 0", shape="box"];
- * p1 [label="PROCESSOR 1", shape="box"];
- * }
- *
- * i -> p0;
- * a -> p1;
- * }
- * @enddot
- *
- * Lets start C.
- *
- * @dot
- * digraph {
- * node [style="filled"];
- * edge [dir="none"];
- *
- * subgraph {
- * rank = same;
- *
- * a [label="A (1)", fillcolor="green"];
- * c [label="C (3)", fillcolor="green"];
- * i [label="I (5)", fillcolor="red"];
- * j [label="J (5)", fillcolor="red"];
- * b [label="B (2)"];
- * a -> c;
- * i -> j;
- * }
- *
- * subgraph {
- * rank = same;
- *
- * p0 [label="PROCESSOR 0", shape="box"];
- * p1 [label="PROCESSOR 1", shape="box"];
- * }
- *
- * c -> p0;
- * a -> p1;
- * }
- * @enddot
- *
- * Lets start B.
- *
- * @dot
- * digraph {
- * node [style="filled"];
- * edge [dir="none"];
- *
- * subgraph {
- * rank = same;
- *
- * a [label="A (1)", fillcolor="green"];
- * b [label="B (2)", fillcolor="green"];
- * c [label="C (3)", fillcolor="red"];
- * i [label="I (5)", fillcolor="red"];
- * j [label="J (5)", fillcolor="red"];
- * a -> b;
- * c -> i -> j;
- * }
- *
- * subgraph {
- * rank = same;
- *
- * p0 [label="PROCESSOR 0", shape="box"];
- * p1 [label="PROCESSOR 1", shape="box"];
- * }
- *
- * b -> p0;
- * a -> p1;
- * }
- * @enddot
- *
- * Lets change the priority of thread A to 4.
- *
- * @dot
- * digraph {
- * node [style="filled"];
- * edge [dir="none"];
- *
- * subgraph {
- * rank = same;
- *
- * b [label="B (2)", fillcolor="green"];
- * c [label="C (3)", fillcolor="green"];
- * a [label="A (4)", fillcolor="red"];
- * i [label="I (5)", fillcolor="red"];
- * j [label="J (5)", fillcolor="red"];
- * b -> c;
- * a -> i -> j;
- * }
- *
- * subgraph {
- * rank = same;
- *
- * p0 [label="PROCESSOR 0", shape="box"];
- * p1 [label="PROCESSOR 1", shape="box"];
- * }
- *
- * b -> p0;
- * c -> p1;
- * }
- * @enddot
- *
- * Now perform a blocking operation with thread B. Please note that thread A
- * migrated now from processor 0 to processor 1 and thread C still executes on
- * processor 1.
- *
- * @dot
- * digraph {
- * node [style="filled"];
- * edge [dir="none"];
- *
- * subgraph {
- * rank = same;
- *
- * c [label="C (3)", fillcolor="green"];
- * a [label="A (4)", fillcolor="green"];
- * i [label="I (5)", fillcolor="red"];
- * j [label="J (5)", fillcolor="red"];
- * b [label="B (2)"];
- * c -> a;
- * i -> j;
- * }
- *
- * subgraph {
- * rank = same;
- *
- * p0 [label="PROCESSOR 0", shape="box"];
- * p1 [label="PROCESSOR 1", shape="box"];
- * }
- *
- * a -> p0;
- * c -> p1;
- * }
- * @enddot
- *
- * @{
- */
-
-typedef bool ( *Scheduler_SMP_Has_ready )(
- Scheduler_Context *context
-);
-
-typedef Scheduler_Node *( *Scheduler_SMP_Get_highest_ready )(
- Scheduler_Context *context,
- Scheduler_Node *node
-);
-
-typedef Scheduler_Node *( *Scheduler_SMP_Get_lowest_scheduled )(
- Scheduler_Context *context,
- Scheduler_Node *filter
-);
-
-typedef void ( *Scheduler_SMP_Extract )(
- Scheduler_Context *context,
- Scheduler_Node *node_to_extract
-);
-
-typedef void ( *Scheduler_SMP_Insert )(
- Scheduler_Context *context,
- Scheduler_Node *node_to_insert,
- Priority_Control insert_priority
-);
-
-typedef void ( *Scheduler_SMP_Move )(
- Scheduler_Context *context,
- Scheduler_Node *node_to_move
-);
-
-typedef bool ( *Scheduler_SMP_Ask_for_help )(
- Scheduler_Context *context,
- Thread_Control *thread,
- Scheduler_Node *node
-);
-
-typedef void ( *Scheduler_SMP_Update )(
- Scheduler_Context *context,
- Scheduler_Node *node_to_update,
- Priority_Control new_priority
-);
-
-typedef void ( *Scheduler_SMP_Set_affinity )(
- Scheduler_Context *context,
- Scheduler_Node *node,
- void *arg
-);
-
-typedef bool ( *Scheduler_SMP_Enqueue )(
- Scheduler_Context *context,
- Scheduler_Node *node_to_enqueue,
- Priority_Control priority
-);
-
-typedef void ( *Scheduler_SMP_Allocate_processor )(
- Scheduler_Context *context,
- Scheduler_Node *scheduled,
- Scheduler_Node *victim,
- Per_CPU_Control *victim_cpu
-);
-
-typedef void ( *Scheduler_SMP_Register_idle )(
- Scheduler_Context *context,
- Scheduler_Node *idle,
- Per_CPU_Control *cpu
-);
-
-static inline void _Scheduler_SMP_Do_nothing_register_idle(
- Scheduler_Context *context,
- Scheduler_Node *idle,
- Per_CPU_Control *cpu
-)
-{
- (void) context;
- (void) idle;
- (void) cpu;
-}
-
-static inline bool _Scheduler_SMP_Priority_less_equal(
- const void *to_insert,
- const Chain_Node *next
-)
-{
- const Priority_Control *priority_to_insert;
- const Scheduler_SMP_Node *node_next;
-
- priority_to_insert = (const Priority_Control *) to_insert;
- node_next = (const Scheduler_SMP_Node *) next;
-
- return *priority_to_insert <= node_next->priority;
-}
-
-static inline Scheduler_SMP_Context *_Scheduler_SMP_Get_self(
- Scheduler_Context *context
-)
-{
- return (Scheduler_SMP_Context *) context;
-}
-
-static inline void _Scheduler_SMP_Initialize(
- Scheduler_SMP_Context *self
-)
-{
- _Chain_Initialize_empty( &self->Scheduled );
- _Chain_Initialize_empty( &self->Idle_threads );
-}
-
-static inline Scheduler_SMP_Node *_Scheduler_SMP_Thread_get_node(
- Thread_Control *thread
-)
-{
- return (Scheduler_SMP_Node *) _Thread_Scheduler_get_home_node( thread );
-}
-
-static inline Scheduler_SMP_Node *_Scheduler_SMP_Thread_get_own_node(
- Thread_Control *thread
-)
-{
- return (Scheduler_SMP_Node *) _Thread_Scheduler_get_home_node( thread );
-}
-
-static inline Scheduler_SMP_Node *_Scheduler_SMP_Node_downcast(
- Scheduler_Node *node
-)
-{
- return (Scheduler_SMP_Node *) node;
-}
-
-static inline Scheduler_SMP_Node_state _Scheduler_SMP_Node_state(
- const Scheduler_Node *node
-)
-{
- return ( (const Scheduler_SMP_Node *) node )->state;
-}
-
-static inline Priority_Control _Scheduler_SMP_Node_priority(
- const Scheduler_Node *node
-)
-{
- return ( (const Scheduler_SMP_Node *) node )->priority;
-}
-
-static inline void _Scheduler_SMP_Node_initialize(
- const Scheduler_Control *scheduler,
- Scheduler_SMP_Node *node,
- Thread_Control *thread,
- Priority_Control priority
-)
-{
- _Scheduler_Node_do_initialize( scheduler, &node->Base, thread, priority );
- node->state = SCHEDULER_SMP_NODE_BLOCKED;
- node->priority = priority;
-}
-
-static inline void _Scheduler_SMP_Node_update_priority(
- Scheduler_SMP_Node *node,
- Priority_Control new_priority
-)
-{
- node->priority = new_priority;
-}
-
-static inline void _Scheduler_SMP_Node_change_state(
- Scheduler_Node *node,
- Scheduler_SMP_Node_state new_state
-)
-{
- Scheduler_SMP_Node *the_node;
-
- the_node = _Scheduler_SMP_Node_downcast( node );
- the_node->state = new_state;
-}
-
-static inline bool _Scheduler_SMP_Is_processor_owned_by_us(
- const Scheduler_Context *context,
- const Per_CPU_Control *cpu
-)
-{
- return cpu->Scheduler.context == context;
-}
-
-static inline Thread_Control *_Scheduler_SMP_Get_idle_thread(
- Scheduler_Context *context
-)
-{
- Scheduler_SMP_Context *self = _Scheduler_SMP_Get_self( context );
- Thread_Control *idle = (Thread_Control *)
- _Chain_Get_first_unprotected( &self->Idle_threads );
-
- _Assert( &idle->Object.Node != _Chain_Tail( &self->Idle_threads ) );
-
- return idle;
-}
-
-static inline void _Scheduler_SMP_Release_idle_thread(
- Scheduler_Context *context,
- Thread_Control *idle
-)
-{
- Scheduler_SMP_Context *self = _Scheduler_SMP_Get_self( context );
-
- _Chain_Prepend_unprotected( &self->Idle_threads, &idle->Object.Node );
-}
-
-static inline void _Scheduler_SMP_Exctract_idle_thread(
- Thread_Control *idle
-)
-{
- _Chain_Extract_unprotected( &idle->Object.Node );
-}
-
-static inline void _Scheduler_SMP_Allocate_processor_lazy(
- Scheduler_Context *context,
- Scheduler_Node *scheduled,
- Scheduler_Node *victim,
- Per_CPU_Control *victim_cpu
-)
-{
- Thread_Control *scheduled_thread = _Scheduler_Node_get_user( scheduled );
- Thread_Control *victim_thread = _Scheduler_Node_get_user( victim );
- Per_CPU_Control *scheduled_cpu = _Thread_Get_CPU( scheduled_thread );
- Per_CPU_Control *cpu_self = _Per_CPU_Get();
- Thread_Control *heir;
-
- _Assert( _ISR_Get_level() != 0 );
-
- if ( _Thread_Is_executing_on_a_processor( scheduled_thread ) ) {
- if ( _Scheduler_SMP_Is_processor_owned_by_us( context, scheduled_cpu ) ) {
- heir = scheduled_cpu->heir;
- _Thread_Dispatch_update_heir(
- cpu_self,
- scheduled_cpu,
- scheduled_thread
- );
- } else {
- /* We have to force a migration to our processor set */
- heir = scheduled_thread;
- }
- } else {
- heir = scheduled_thread;
- }
-
- if ( heir != victim_thread ) {
- _Thread_Set_CPU( heir, victim_cpu );
- _Thread_Dispatch_update_heir( cpu_self, victim_cpu, heir );
- }
-}
-
-/*
- * This method is slightly different from
- * _Scheduler_SMP_Allocate_processor_lazy() in that it does what it is asked to
- * do. _Scheduler_SMP_Allocate_processor_lazy() attempts to prevent migrations
- * but does not take into account affinity.
- */
-static inline void _Scheduler_SMP_Allocate_processor_exact(
- Scheduler_Context *context,
- Scheduler_Node *scheduled,
- Scheduler_Node *victim,
- Per_CPU_Control *victim_cpu
-)
-{
- Thread_Control *scheduled_thread = _Scheduler_Node_get_user( scheduled );
- Per_CPU_Control *cpu_self = _Per_CPU_Get();
-
- (void) context;
- (void) victim;
-
- _Thread_Set_CPU( scheduled_thread, victim_cpu );
- _Thread_Dispatch_update_heir( cpu_self, victim_cpu, scheduled_thread );
-}
-
-static inline void _Scheduler_SMP_Allocate_processor(
- Scheduler_Context *context,
- Scheduler_Node *scheduled,
- Scheduler_Node *victim,
- Per_CPU_Control *victim_cpu,
- Scheduler_SMP_Allocate_processor allocate_processor
-)
-{
- _Scheduler_SMP_Node_change_state( scheduled, SCHEDULER_SMP_NODE_SCHEDULED );
- ( *allocate_processor )( context, scheduled, victim, victim_cpu );
-}
-
-static inline Thread_Control *_Scheduler_SMP_Preempt(
- Scheduler_Context *context,
- Scheduler_Node *scheduled,
- Scheduler_Node *victim,
- Scheduler_SMP_Allocate_processor allocate_processor
-)
-{
- Thread_Control *victim_thread;
- ISR_lock_Context lock_context;
- Per_CPU_Control *victim_cpu;
-
- victim_thread = _Scheduler_Node_get_user( victim );
- _Scheduler_SMP_Node_change_state( victim, SCHEDULER_SMP_NODE_READY );
-
- _Thread_Scheduler_acquire_critical( victim_thread, &lock_context );
-
- victim_cpu = _Thread_Get_CPU( victim_thread );
-
- if ( victim_thread->Scheduler.state == THREAD_SCHEDULER_SCHEDULED ) {
- _Scheduler_Thread_change_state( victim_thread, THREAD_SCHEDULER_READY );
-
- if ( victim_thread->Scheduler.helping_nodes > 0 ) {
- _Per_CPU_Acquire( victim_cpu );
- _Chain_Append_unprotected(
- &victim_cpu->Threads_in_need_for_help,
- &victim_thread->Scheduler.Help_node
- );
- _Per_CPU_Release( victim_cpu );
- }
- }
-
- _Thread_Scheduler_release_critical( victim_thread, &lock_context );
-
- _Scheduler_SMP_Allocate_processor(
- context,
- scheduled,
- victim,
- victim_cpu,
- allocate_processor
- );
-
- return victim_thread;
-}
-
-static inline Scheduler_Node *_Scheduler_SMP_Get_lowest_scheduled(
- Scheduler_Context *context,
- Scheduler_Node *filter
-)
-{
- Scheduler_SMP_Context *self = _Scheduler_SMP_Get_self( context );
- Chain_Control *scheduled = &self->Scheduled;
- Scheduler_Node *lowest_scheduled =
- (Scheduler_Node *) _Chain_Last( scheduled );
-
- (void) filter;
-
- _Assert( &lowest_scheduled->Node.Chain != _Chain_Tail( scheduled ) );
- _Assert(
- _Chain_Next( &lowest_scheduled->Node.Chain ) == _Chain_Tail( scheduled )
- );
-
- return lowest_scheduled;
-}
-
-static inline void _Scheduler_SMP_Enqueue_to_scheduled(
- Scheduler_Context *context,
- Scheduler_Node *node,
- Priority_Control priority,
- Scheduler_Node *lowest_scheduled,
- Scheduler_SMP_Insert insert_scheduled,
- Scheduler_SMP_Move move_from_scheduled_to_ready,
- Scheduler_SMP_Allocate_processor allocate_processor
-)
-{
- Scheduler_Try_to_schedule_action action;
-
- action = _Scheduler_Try_to_schedule_node(
- context,
- node,
- _Scheduler_Node_get_idle( lowest_scheduled ),
- _Scheduler_SMP_Get_idle_thread
- );
-
- if ( action == SCHEDULER_TRY_TO_SCHEDULE_DO_SCHEDULE ) {
- _Scheduler_SMP_Preempt(
- context,
- node,
- lowest_scheduled,
- allocate_processor
- );
-
- ( *insert_scheduled )( context, node, priority );
- ( *move_from_scheduled_to_ready )( context, lowest_scheduled );
-
- _Scheduler_Release_idle_thread(
- context,
- lowest_scheduled,
- _Scheduler_SMP_Release_idle_thread
- );
- } else if ( action == SCHEDULER_TRY_TO_SCHEDULE_DO_IDLE_EXCHANGE ) {
- _Scheduler_SMP_Node_change_state(
- lowest_scheduled,
- SCHEDULER_SMP_NODE_READY
- );
- _Scheduler_SMP_Node_change_state( node, SCHEDULER_SMP_NODE_SCHEDULED );
-
- ( *insert_scheduled )( context, node, priority );
- ( *move_from_scheduled_to_ready )( context, lowest_scheduled );
-
- _Scheduler_Exchange_idle_thread(
- node,
- lowest_scheduled,
- _Scheduler_Node_get_idle( lowest_scheduled )
- );
- } else {
- _Assert( action == SCHEDULER_TRY_TO_SCHEDULE_DO_BLOCK );
- _Scheduler_SMP_Node_change_state( node, SCHEDULER_SMP_NODE_BLOCKED );
- }
-}
-
-/**
- * @brief Enqueues a node according to the specified order function.
- *
- * The node must not be in the scheduled state.
- *
- * @param[in] context The scheduler instance context.
- * @param[in] node The node to enqueue.
- * @param[in] priority The node insert priority.
- * @param[in] order The order function.
- * @param[in] insert_ready Function to insert a node into the set of ready
- * nodes.
- * @param[in] insert_scheduled Function to insert a node into the set of
- * scheduled nodes.
- * @param[in] move_from_scheduled_to_ready Function to move a node from the set
- * of scheduled nodes to the set of ready nodes.
- * @param[in] get_lowest_scheduled Function to select the node from the
- * scheduled nodes to replace. It may not be possible to find one, in this
- * case a pointer must be returned so that the order functions returns false
- * if this pointer is passed as the second argument to the order function.
- * @param[in] allocate_processor Function to allocate a processor to a node
- * based on the rules of the scheduler.
- */
-static inline bool _Scheduler_SMP_Enqueue(
- Scheduler_Context *context,
- Scheduler_Node *node,
- Priority_Control insert_priority,
- Chain_Node_order order,
- Scheduler_SMP_Insert insert_ready,
- Scheduler_SMP_Insert insert_scheduled,
- Scheduler_SMP_Move move_from_scheduled_to_ready,
- Scheduler_SMP_Get_lowest_scheduled get_lowest_scheduled,
- Scheduler_SMP_Allocate_processor allocate_processor
-)
-{
- bool needs_help;
- Scheduler_Node *lowest_scheduled;
-
- lowest_scheduled = ( *get_lowest_scheduled )( context, node );
-
- if ( ( *order )( &insert_priority, &lowest_scheduled->Node.Chain ) ) {
- _Scheduler_SMP_Enqueue_to_scheduled(
- context,
- node,
- insert_priority,
- lowest_scheduled,
- insert_scheduled,
- move_from_scheduled_to_ready,
- allocate_processor
- );
- needs_help = false;
- } else {
- ( *insert_ready )( context, node, insert_priority );
- needs_help = true;
- }
-
- return needs_help;
-}
-
-/**
- * @brief Enqueues a scheduled node according to the specified order
- * function.
- *
- * @param[in] context The scheduler instance context.
- * @param[in] node The node to enqueue.
- * @param[in] order The order function.
- * @param[in] extract_from_ready Function to extract a node from the set of
- * ready nodes.
- * @param[in] get_highest_ready Function to get the highest ready node.
- * @param[in] insert_ready Function to insert a node into the set of ready
- * nodes.
- * @param[in] insert_scheduled Function to insert a node into the set of
- * scheduled nodes.
- * @param[in] move_from_ready_to_scheduled Function to move a node from the set
- * of ready nodes to the set of scheduled nodes.
- * @param[in] allocate_processor Function to allocate a processor to a node
- * based on the rules of the scheduler.
- */
-static inline bool _Scheduler_SMP_Enqueue_scheduled(
- Scheduler_Context *context,
- Scheduler_Node *const node,
- Priority_Control insert_priority,
- Chain_Node_order order,
- Scheduler_SMP_Extract extract_from_ready,
- Scheduler_SMP_Get_highest_ready get_highest_ready,
- Scheduler_SMP_Insert insert_ready,
- Scheduler_SMP_Insert insert_scheduled,
- Scheduler_SMP_Move move_from_ready_to_scheduled,
- Scheduler_SMP_Allocate_processor allocate_processor
-)
-{
- while ( true ) {
- Scheduler_Node *highest_ready;
- Scheduler_Try_to_schedule_action action;
-
- highest_ready = ( *get_highest_ready )( context, node );
-
- /*
- * The node has been extracted from the scheduled chain. We have to place
- * it now on the scheduled or ready set.
- */
- if (
- node->sticky_level > 0
- && ( *order )( &insert_priority, &highest_ready->Node.Chain )
- ) {
- ( *insert_scheduled )( context, node, insert_priority );
-
- if ( _Scheduler_Node_get_idle( node ) != NULL ) {
- Thread_Control *owner;
- ISR_lock_Context lock_context;
-
- owner = _Scheduler_Node_get_owner( node );
- _Thread_Scheduler_acquire_critical( owner, &lock_context );
-
- if ( owner->Scheduler.state == THREAD_SCHEDULER_READY ) {
- _Thread_Scheduler_cancel_need_for_help(
- owner,
- _Thread_Get_CPU( owner )
- );
- _Scheduler_Discard_idle_thread(
- context,
- owner,
- node,
- _Scheduler_SMP_Release_idle_thread
- );
- _Scheduler_Thread_change_state( owner, THREAD_SCHEDULER_SCHEDULED );
- }
-
- _Thread_Scheduler_release_critical( owner, &lock_context );
- }
-
- return false;
- }
-
- action = _Scheduler_Try_to_schedule_node(
- context,
- highest_ready,
- _Scheduler_Node_get_idle( node ),
- _Scheduler_SMP_Get_idle_thread
- );
-
- if ( action == SCHEDULER_TRY_TO_SCHEDULE_DO_SCHEDULE ) {
- Thread_Control *idle;
-
- _Scheduler_SMP_Preempt(
- context,
- highest_ready,
- node,
- allocate_processor
- );
-
- ( *insert_ready )( context, node, insert_priority );
- ( *move_from_ready_to_scheduled )( context, highest_ready );
-
- idle = _Scheduler_Release_idle_thread(
- context,
- node,
- _Scheduler_SMP_Release_idle_thread
- );
- return ( idle == NULL );
- } else if ( action == SCHEDULER_TRY_TO_SCHEDULE_DO_IDLE_EXCHANGE ) {
- _Scheduler_SMP_Node_change_state( node, SCHEDULER_SMP_NODE_READY );
- _Scheduler_SMP_Node_change_state(
- highest_ready,
- SCHEDULER_SMP_NODE_SCHEDULED
- );
-
- ( *insert_ready )( context, node, insert_priority );
- ( *move_from_ready_to_scheduled )( context, highest_ready );
-
- _Scheduler_Exchange_idle_thread(
- highest_ready,
- node,
- _Scheduler_Node_get_idle( node )
- );
- return false;
- } else {
- _Assert( action == SCHEDULER_TRY_TO_SCHEDULE_DO_BLOCK );
-
- _Scheduler_SMP_Node_change_state(
- highest_ready,
- SCHEDULER_SMP_NODE_BLOCKED
- );
-
- ( *extract_from_ready )( context, highest_ready );
- }
- }
-}
-
-static inline void _Scheduler_SMP_Extract_from_scheduled(
- Scheduler_Node *node
-)
-{
- _Chain_Extract_unprotected( &node->Node.Chain );
-}
-
-static inline void _Scheduler_SMP_Schedule_highest_ready(
- Scheduler_Context *context,
- Scheduler_Node *victim,
- Per_CPU_Control *victim_cpu,
- Scheduler_SMP_Extract extract_from_ready,
- Scheduler_SMP_Get_highest_ready get_highest_ready,
- Scheduler_SMP_Move move_from_ready_to_scheduled,
- Scheduler_SMP_Allocate_processor allocate_processor
-)
-{
- Scheduler_Try_to_schedule_action action;
-
- do {
- Scheduler_Node *highest_ready = ( *get_highest_ready )( context, victim );
-
- action = _Scheduler_Try_to_schedule_node(
- context,
- highest_ready,
- NULL,
- _Scheduler_SMP_Get_idle_thread
- );
-
- if ( action == SCHEDULER_TRY_TO_SCHEDULE_DO_SCHEDULE ) {
- _Scheduler_SMP_Allocate_processor(
- context,
- highest_ready,
- victim,
- victim_cpu,
- allocate_processor
- );
-
- ( *move_from_ready_to_scheduled )( context, highest_ready );
- } else {
- _Assert( action == SCHEDULER_TRY_TO_SCHEDULE_DO_BLOCK );
-
- _Scheduler_SMP_Node_change_state(
- highest_ready,
- SCHEDULER_SMP_NODE_BLOCKED
- );
-
- ( *extract_from_ready )( context, highest_ready );
- }
- } while ( action == SCHEDULER_TRY_TO_SCHEDULE_DO_BLOCK );
-}
-
-static inline void _Scheduler_SMP_Preempt_and_schedule_highest_ready(
- Scheduler_Context *context,
- Scheduler_Node *victim,
- Per_CPU_Control *victim_cpu,
- Scheduler_SMP_Extract extract_from_ready,
- Scheduler_SMP_Get_highest_ready get_highest_ready,
- Scheduler_SMP_Move move_from_ready_to_scheduled,
- Scheduler_SMP_Allocate_processor allocate_processor
-)
-{
- Scheduler_Try_to_schedule_action action;
-
- do {
- Scheduler_Node *highest_ready = ( *get_highest_ready )( context, victim );
-
- action = _Scheduler_Try_to_schedule_node(
- context,
- highest_ready,
- NULL,
- _Scheduler_SMP_Get_idle_thread
- );
-
- if ( action == SCHEDULER_TRY_TO_SCHEDULE_DO_SCHEDULE ) {
- _Scheduler_SMP_Preempt(
- context,
- highest_ready,
- victim,
- allocate_processor
- );
-
- ( *move_from_ready_to_scheduled )( context, highest_ready );
- } else {
- _Assert( action == SCHEDULER_TRY_TO_SCHEDULE_DO_BLOCK );
-
- _Scheduler_SMP_Node_change_state(
- highest_ready,
- SCHEDULER_SMP_NODE_BLOCKED
- );
-
- ( *extract_from_ready )( context, highest_ready );
- }
- } while ( action == SCHEDULER_TRY_TO_SCHEDULE_DO_BLOCK );
-}
-
-/**
- * @brief Blocks a thread.
- *
- * @param[in] context The scheduler instance context.
- * @param[in] thread The thread of the scheduling operation.
- * @param[in] node The scheduler node of the thread to block.
- * @param[in] extract_from_ready Function to extract a node from the set of
- * ready nodes.
- * @param[in] get_highest_ready Function to get the highest ready node.
- * @param[in] move_from_ready_to_scheduled Function to move a node from the set
- * of ready nodes to the set of scheduled nodes.
- */
-static inline void _Scheduler_SMP_Block(
- Scheduler_Context *context,
- Thread_Control *thread,
- Scheduler_Node *node,
- Scheduler_SMP_Extract extract_from_ready,
- Scheduler_SMP_Get_highest_ready get_highest_ready,
- Scheduler_SMP_Move move_from_ready_to_scheduled,
- Scheduler_SMP_Allocate_processor allocate_processor
-)
-{
- Scheduler_SMP_Node_state node_state;
- Per_CPU_Control *thread_cpu;
-
- node_state = _Scheduler_SMP_Node_state( node );
-
- thread_cpu = _Scheduler_Block_node(
- context,
- thread,
- node,
- node_state == SCHEDULER_SMP_NODE_SCHEDULED,
- _Scheduler_SMP_Get_idle_thread
- );
-
- if ( thread_cpu != NULL ) {
- _Scheduler_SMP_Node_change_state( node, SCHEDULER_SMP_NODE_BLOCKED );
-
- if ( node_state == SCHEDULER_SMP_NODE_SCHEDULED ) {
- _Scheduler_SMP_Extract_from_scheduled( node );
- _Scheduler_SMP_Schedule_highest_ready(
- context,
- node,
- thread_cpu,
- extract_from_ready,
- get_highest_ready,
- move_from_ready_to_scheduled,
- allocate_processor
- );
- } else if ( node_state == SCHEDULER_SMP_NODE_READY ) {
- ( *extract_from_ready )( context, node );
- }
- }
-}
-
-static inline void _Scheduler_SMP_Unblock(
- Scheduler_Context *context,
- Thread_Control *thread,
- Scheduler_Node *node,
- Scheduler_SMP_Update update,
- Scheduler_SMP_Enqueue enqueue
-)
-{
- Scheduler_SMP_Node_state node_state;
- bool unblock;
-
- node_state = _Scheduler_SMP_Node_state( node );
- unblock = _Scheduler_Unblock_node(
- context,
- thread,
- node,
- node_state == SCHEDULER_SMP_NODE_SCHEDULED,
- _Scheduler_SMP_Release_idle_thread
- );
-
- if ( unblock ) {
- Priority_Control priority;
- bool needs_help;
-
- priority = _Scheduler_Node_get_priority( node );
- priority = SCHEDULER_PRIORITY_PURIFY( priority );
-
- if ( priority != _Scheduler_SMP_Node_priority( node ) ) {
- ( *update )( context, node, priority );
- }
-
- if ( node_state == SCHEDULER_SMP_NODE_BLOCKED ) {
- Priority_Control insert_priority;
-
- _Scheduler_SMP_Node_change_state( node, SCHEDULER_SMP_NODE_READY );
- insert_priority = SCHEDULER_PRIORITY_APPEND( priority );
- needs_help = ( *enqueue )( context, node, insert_priority );
- } else {
- _Assert( node_state == SCHEDULER_SMP_NODE_READY );
- _Assert( node->sticky_level > 0 );
- _Assert( node->idle == NULL );
- needs_help = true;
- }
-
- if ( needs_help ) {
- _Scheduler_Ask_for_help( thread );
- }
- }
-}
-
-static inline void _Scheduler_SMP_Update_priority(
- Scheduler_Context *context,
- Thread_Control *thread,
- Scheduler_Node *node,
- Scheduler_SMP_Extract extract_from_ready,
- Scheduler_SMP_Update update,
- Scheduler_SMP_Enqueue enqueue,
- Scheduler_SMP_Enqueue enqueue_scheduled,
- Scheduler_SMP_Ask_for_help ask_for_help
-)
-{
- Priority_Control priority;
- Priority_Control insert_priority;
- Scheduler_SMP_Node_state node_state;
-
- insert_priority = _Scheduler_Node_get_priority( node );
- priority = SCHEDULER_PRIORITY_PURIFY( insert_priority );
-
- if ( priority == _Scheduler_SMP_Node_priority( node ) ) {
- if ( _Thread_Is_ready( thread ) ) {
- ( *ask_for_help )( context, thread, node );
- }
-
- return;
- }
-
- node_state = _Scheduler_SMP_Node_state( node );
-
- if ( node_state == SCHEDULER_SMP_NODE_SCHEDULED ) {
- _Scheduler_SMP_Extract_from_scheduled( node );
- ( *update )( context, node, priority );
- ( *enqueue_scheduled )( context, node, insert_priority );
- } else if ( node_state == SCHEDULER_SMP_NODE_READY ) {
- ( *extract_from_ready )( context, node );
- ( *update )( context, node, priority );
- ( *enqueue )( context, node, insert_priority );
- } else {
- ( *update )( context, node, priority );
-
- if ( _Thread_Is_ready( thread ) ) {
- ( *ask_for_help )( context, thread, node );
- }
- }
-}
-
-static inline void _Scheduler_SMP_Yield(
- Scheduler_Context *context,
- Thread_Control *thread,
- Scheduler_Node *node,
- Scheduler_SMP_Extract extract_from_ready,
- Scheduler_SMP_Enqueue enqueue,
- Scheduler_SMP_Enqueue enqueue_scheduled
-)
-{
- bool needs_help;
- Scheduler_SMP_Node_state node_state;
- Priority_Control insert_priority;
-
- node_state = _Scheduler_SMP_Node_state( node );
- insert_priority = _Scheduler_SMP_Node_priority( node );
- insert_priority = SCHEDULER_PRIORITY_APPEND( insert_priority );
-
- if ( node_state == SCHEDULER_SMP_NODE_SCHEDULED ) {
- _Scheduler_SMP_Extract_from_scheduled( node );
- ( *enqueue_scheduled )( context, node, insert_priority );
- needs_help = false;
- } else if ( node_state == SCHEDULER_SMP_NODE_READY ) {
- ( *extract_from_ready )( context, node );
-
- needs_help = ( *enqueue )( context, node, insert_priority );
- } else {
- needs_help = true;
- }
-
- if ( needs_help ) {
- _Scheduler_Ask_for_help( thread );
- }
-}
-
-static inline void _Scheduler_SMP_Insert_scheduled(
- Scheduler_Context *context,
- Scheduler_Node *node_to_insert,
- Priority_Control priority_to_insert
-)
-{
- Scheduler_SMP_Context *self;
-
- self = _Scheduler_SMP_Get_self( context );
-
- _Chain_Insert_ordered_unprotected(
- &self->Scheduled,
- &node_to_insert->Node.Chain,
- &priority_to_insert,
- _Scheduler_SMP_Priority_less_equal
- );
-}
-
-static inline bool _Scheduler_SMP_Ask_for_help(
- Scheduler_Context *context,
- Thread_Control *thread,
- Scheduler_Node *node,
- Chain_Node_order order,
- Scheduler_SMP_Insert insert_ready,
- Scheduler_SMP_Insert insert_scheduled,
- Scheduler_SMP_Move move_from_scheduled_to_ready,
- Scheduler_SMP_Get_lowest_scheduled get_lowest_scheduled,
- Scheduler_SMP_Allocate_processor allocate_processor
-)
-{
- Scheduler_Node *lowest_scheduled;
- ISR_lock_Context lock_context;
- bool success;
-
- lowest_scheduled = ( *get_lowest_scheduled )( context, node );
-
- _Thread_Scheduler_acquire_critical( thread, &lock_context );
-
- if ( thread->Scheduler.state == THREAD_SCHEDULER_READY ) {
- Scheduler_SMP_Node_state node_state;
-
- node_state = _Scheduler_SMP_Node_state( node );
-
- if ( node_state == SCHEDULER_SMP_NODE_BLOCKED ) {
- Priority_Control insert_priority;
-
- insert_priority = _Scheduler_SMP_Node_priority( node );
-
- if ( ( *order )( &insert_priority, &lowest_scheduled->Node.Chain ) ) {
- _Thread_Scheduler_cancel_need_for_help(
- thread,
- _Thread_Get_CPU( thread )
- );
- _Scheduler_Thread_change_state( thread, THREAD_SCHEDULER_SCHEDULED );
- _Thread_Scheduler_release_critical( thread, &lock_context );
-
- _Scheduler_SMP_Preempt(
- context,
- node,
- lowest_scheduled,
- allocate_processor
- );
-
- ( *insert_scheduled )( context, node, insert_priority );
- ( *move_from_scheduled_to_ready )( context, lowest_scheduled );
-
- _Scheduler_Release_idle_thread(
- context,
- lowest_scheduled,
- _Scheduler_SMP_Release_idle_thread
- );
- success = true;
- } else {
- _Thread_Scheduler_release_critical( thread, &lock_context );
- _Scheduler_SMP_Node_change_state( node, SCHEDULER_SMP_NODE_READY );
- ( *insert_ready )( context, node, insert_priority );
- success = false;
- }
- } else if ( node_state == SCHEDULER_SMP_NODE_SCHEDULED ) {
- _Thread_Scheduler_cancel_need_for_help(
- thread,
- _Thread_Get_CPU( thread )
- );
- _Scheduler_Discard_idle_thread(
- context,
- thread,
- node,
- _Scheduler_SMP_Release_idle_thread
- );
- _Scheduler_Thread_change_state( thread, THREAD_SCHEDULER_SCHEDULED );
- _Thread_Scheduler_release_critical( thread, &lock_context );
- success = true;
- } else {
- _Thread_Scheduler_release_critical( thread, &lock_context );
- success = false;
- }
- } else {
- _Thread_Scheduler_release_critical( thread, &lock_context );
- success = false;
- }
-
- return success;
-}
-
-static inline void _Scheduler_SMP_Reconsider_help_request(
- Scheduler_Context *context,
- Thread_Control *thread,
- Scheduler_Node *node,
- Scheduler_SMP_Extract extract_from_ready
-)
-{
- ISR_lock_Context lock_context;
-
- _Thread_Scheduler_acquire_critical( thread, &lock_context );
-
- if (
- thread->Scheduler.state == THREAD_SCHEDULER_SCHEDULED
- && _Scheduler_SMP_Node_state( node ) == SCHEDULER_SMP_NODE_READY
- && node->sticky_level == 1
- ) {
- _Scheduler_SMP_Node_change_state( node, SCHEDULER_SMP_NODE_BLOCKED );
- ( *extract_from_ready )( context, node );
- }
-
- _Thread_Scheduler_release_critical( thread, &lock_context );
-}
-
-static inline void _Scheduler_SMP_Withdraw_node(
- Scheduler_Context *context,
- Thread_Control *thread,
- Scheduler_Node *node,
- Thread_Scheduler_state next_state,
- Scheduler_SMP_Extract extract_from_ready,
- Scheduler_SMP_Get_highest_ready get_highest_ready,
- Scheduler_SMP_Move move_from_ready_to_scheduled,
- Scheduler_SMP_Allocate_processor allocate_processor
-)
-{
- ISR_lock_Context lock_context;
- Scheduler_SMP_Node_state node_state;
-
- _Thread_Scheduler_acquire_critical( thread, &lock_context );
-
- node_state = _Scheduler_SMP_Node_state( node );
- _Scheduler_SMP_Node_change_state( node, SCHEDULER_SMP_NODE_BLOCKED );
-
- if ( node_state == SCHEDULER_SMP_NODE_SCHEDULED ) {
- Per_CPU_Control *thread_cpu;
-
- thread_cpu = _Thread_Get_CPU( thread );
- _Scheduler_Thread_change_state( thread, next_state );
- _Thread_Scheduler_release_critical( thread, &lock_context );
-
- _Scheduler_SMP_Extract_from_scheduled( node );
- _Scheduler_SMP_Schedule_highest_ready(
- context,
- node,
- thread_cpu,
- extract_from_ready,
- get_highest_ready,
- move_from_ready_to_scheduled,
- allocate_processor
- );
- } else if ( node_state == SCHEDULER_SMP_NODE_READY ) {
- _Thread_Scheduler_release_critical( thread, &lock_context );
- ( *extract_from_ready )( context, node );
- } else {
- _Assert( node_state == SCHEDULER_SMP_NODE_BLOCKED );
- _Thread_Scheduler_release_critical( thread, &lock_context );
- }
-}
-
-static inline void _Scheduler_SMP_Do_start_idle(
- Scheduler_Context *context,
- Thread_Control *idle,
- Per_CPU_Control *cpu,
- Scheduler_SMP_Register_idle register_idle
-)
-{
- Scheduler_SMP_Context *self;
- Scheduler_SMP_Node *node;
-
- self = _Scheduler_SMP_Get_self( context );
- node = _Scheduler_SMP_Thread_get_node( idle );
-
- _Scheduler_Thread_change_state( idle, THREAD_SCHEDULER_SCHEDULED );
- node->state = SCHEDULER_SMP_NODE_SCHEDULED;
-
- _Thread_Set_CPU( idle, cpu );
- ( *register_idle )( context, &node->Base, cpu );
- _Chain_Append_unprotected( &self->Scheduled, &node->Base.Node.Chain );
- _Scheduler_SMP_Release_idle_thread( &self->Base, idle );
-}
-
-static inline void _Scheduler_SMP_Add_processor(
- Scheduler_Context *context,
- Thread_Control *idle,
- Scheduler_SMP_Has_ready has_ready,
- Scheduler_SMP_Enqueue enqueue_scheduled,
- Scheduler_SMP_Register_idle register_idle
-)
-{
- Scheduler_SMP_Context *self;
- Scheduler_Node *node;
-
- self = _Scheduler_SMP_Get_self( context );
- idle->Scheduler.state = THREAD_SCHEDULER_SCHEDULED;
- _Scheduler_SMP_Release_idle_thread( &self->Base, idle );
- node = _Thread_Scheduler_get_home_node( idle );
- _Scheduler_SMP_Node_change_state( node, SCHEDULER_SMP_NODE_SCHEDULED );
- ( *register_idle )( context, node, _Thread_Get_CPU( idle ) );
-
- if ( ( *has_ready )( &self->Base ) ) {
- Priority_Control insert_priority;
-
- insert_priority = _Scheduler_SMP_Node_priority( node );
- insert_priority = SCHEDULER_PRIORITY_APPEND( insert_priority );
- ( *enqueue_scheduled )( &self->Base, node, insert_priority );
- } else {
- _Chain_Append_unprotected( &self->Scheduled, &node->Node.Chain );
- }
-}
-
-static inline Thread_Control *_Scheduler_SMP_Remove_processor(
- Scheduler_Context *context,
- Per_CPU_Control *cpu,
- Scheduler_SMP_Extract extract_from_ready,
- Scheduler_SMP_Enqueue enqueue
-)
-{
- Scheduler_SMP_Context *self;
- Chain_Node *chain_node;
- Scheduler_Node *victim_node;
- Thread_Control *victim_user;
- Thread_Control *victim_owner;
- Thread_Control *idle;
-
- self = _Scheduler_SMP_Get_self( context );
- chain_node = _Chain_First( &self->Scheduled );
-
- do {
- _Assert( chain_node != _Chain_Immutable_tail( &self->Scheduled ) );
- victim_node = (Scheduler_Node *) chain_node;
- victim_user = _Scheduler_Node_get_user( victim_node );
- chain_node = _Chain_Next( chain_node );
- } while ( _Thread_Get_CPU( victim_user ) != cpu );
-
- _Scheduler_SMP_Extract_from_scheduled( victim_node );
- victim_owner = _Scheduler_Node_get_owner( victim_node );
-
- if ( !victim_owner->is_idle ) {
- Scheduler_Node *idle_node;
-
- _Scheduler_Release_idle_thread(
- &self->Base,
- victim_node,
- _Scheduler_SMP_Release_idle_thread
- );
- idle = _Scheduler_SMP_Get_idle_thread( &self->Base );
- idle_node = _Thread_Scheduler_get_home_node( idle );
- ( *extract_from_ready )( &self->Base, idle_node );
- _Scheduler_SMP_Preempt(
- &self->Base,
- idle_node,
- victim_node,
- _Scheduler_SMP_Allocate_processor_exact
- );
-
- if ( !_Chain_Is_empty( &self->Scheduled ) ) {
- Priority_Control insert_priority;
-
- insert_priority = _Scheduler_SMP_Node_priority( victim_node );
- insert_priority = SCHEDULER_PRIORITY_APPEND( insert_priority );
- ( *enqueue )( context, victim_node, insert_priority );
- }
- } else {
- _Assert( victim_owner == victim_user );
- _Assert( _Scheduler_Node_get_idle( victim_node ) == NULL );
- idle = victim_owner;
- _Scheduler_SMP_Exctract_idle_thread( idle );
- }
-
- return idle;
-}
-
-static inline void _Scheduler_SMP_Set_affinity(
- Scheduler_Context *context,
- Thread_Control *thread,
- Scheduler_Node *node,
- void *arg,
- Scheduler_SMP_Set_affinity set_affinity,
- Scheduler_SMP_Extract extract_from_ready,
- Scheduler_SMP_Get_highest_ready get_highest_ready,
- Scheduler_SMP_Move move_from_ready_to_scheduled,
- Scheduler_SMP_Enqueue enqueue,
- Scheduler_SMP_Allocate_processor allocate_processor
-)
-{
- Scheduler_SMP_Node_state node_state;
- Priority_Control insert_priority;
-
- node_state = _Scheduler_SMP_Node_state( node );
- insert_priority = _Scheduler_SMP_Node_priority( node );
- insert_priority = SCHEDULER_PRIORITY_APPEND( insert_priority );
-
- if ( node_state == SCHEDULER_SMP_NODE_SCHEDULED ) {
- _Scheduler_SMP_Extract_from_scheduled( node );
- _Scheduler_SMP_Preempt_and_schedule_highest_ready(
- context,
- node,
- _Thread_Get_CPU( thread ),
- extract_from_ready,
- get_highest_ready,
- move_from_ready_to_scheduled,
- allocate_processor
- );
- ( *set_affinity )( context, node, arg );
- ( *enqueue )( context, node, insert_priority );
- } else if ( node_state == SCHEDULER_SMP_NODE_READY ) {
- ( *extract_from_ready )( context, node );
- ( *set_affinity )( context, node, arg );
- ( *enqueue )( context, node, insert_priority );
- } else {
- ( *set_affinity )( context, node, arg );
- }
-}
-
-/** @} */
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* _RTEMS_SCORE_SCHEDULERSMPIMPL_H */