Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:26

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSScoreSchedulerSMPSimple
0007  *
0008  * @brief This source file contains the implementation of
0009  *   _Scheduler_simple_SMP_Add_processor(),
0010  *   _Scheduler_simple_SMP_Ask_for_help(), _Scheduler_simple_SMP_Block(),
0011  *   _Scheduler_simple_SMP_Initialize(),
0012  *   _Scheduler_simple_SMP_Node_initialize(),
0013  *   _Scheduler_simple_SMP_Reconsider_help_request(),
0014  *   _Scheduler_simple_SMP_Remove_processor(), _Scheduler_simple_SMP_Unblock(),
0015  *   _Scheduler_simple_SMP_Update_priority(),
0016  *   _Scheduler_simple_SMP_Withdraw_node(),
0017  *   _Scheduler_simple_SMP_Make_sticky(), _Scheduler_simple_SMP_Clean_sticky(),
0018  *   and _Scheduler_simple_SMP_Yield().
0019  */
0020 
0021 /*
0022  * Copyright (C) 2013, 2016 embedded brains GmbH & Co. KG
0023  *
0024  * Redistribution and use in source and binary forms, with or without
0025  * modification, are permitted provided that the following conditions
0026  * are met:
0027  * 1. Redistributions of source code must retain the above copyright
0028  *    notice, this list of conditions and the following disclaimer.
0029  * 2. Redistributions in binary form must reproduce the above copyright
0030  *    notice, this list of conditions and the following disclaimer in the
0031  *    documentation and/or other materials provided with the distribution.
0032  *
0033  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0034  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0035  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0036  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0037  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0038  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0039  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0040  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0041  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0042  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0043  * POSSIBILITY OF SUCH DAMAGE.
0044  */
0045 
0046 #ifdef HAVE_CONFIG_H
0047 #include "config.h"
0048 #endif
0049 
0050 #include <rtems/score/schedulersimplesmp.h>
0051 #include <rtems/score/schedulersmpimpl.h>
0052 
0053 static Scheduler_simple_SMP_Context *
0054 _Scheduler_simple_SMP_Get_context( const Scheduler_Control *scheduler )
0055 {
0056   return (Scheduler_simple_SMP_Context *) _Scheduler_Get_context( scheduler );
0057 }
0058 
0059 static Scheduler_simple_SMP_Context *
0060 _Scheduler_simple_SMP_Get_self( Scheduler_Context *context )
0061 {
0062   return (Scheduler_simple_SMP_Context *) context;
0063 }
0064 
0065 void _Scheduler_simple_SMP_Initialize( const Scheduler_Control *scheduler )
0066 {
0067   Scheduler_simple_SMP_Context *self =
0068     _Scheduler_simple_SMP_Get_context( scheduler );
0069 
0070   _Scheduler_SMP_Initialize( &self->Base );
0071   _Chain_Initialize_empty( &self->Ready );
0072 }
0073 
0074 void _Scheduler_simple_SMP_Node_initialize(
0075   const Scheduler_Control *scheduler,
0076   Scheduler_Node          *node,
0077   Thread_Control          *the_thread,
0078   Priority_Control         priority
0079 )
0080 {
0081   Scheduler_SMP_Node *smp_node;
0082 
0083   smp_node = _Scheduler_SMP_Node_downcast( node );
0084   _Scheduler_SMP_Node_initialize( scheduler, smp_node, the_thread, priority );
0085 }
0086 
0087 static void _Scheduler_simple_SMP_Do_update(
0088   Scheduler_Context *context,
0089   Scheduler_Node    *node,
0090   Priority_Control   new_priority
0091 )
0092 {
0093   Scheduler_SMP_Node *smp_node;
0094 
0095   (void) context;
0096 
0097   smp_node = _Scheduler_SMP_Node_downcast( node );
0098   _Scheduler_SMP_Node_update_priority( smp_node, new_priority );
0099 }
0100 
0101 static bool _Scheduler_simple_SMP_Has_ready( Scheduler_Context *context )
0102 {
0103   Scheduler_simple_SMP_Context *self =
0104     _Scheduler_simple_SMP_Get_self( context );
0105 
0106   return !_Chain_Is_empty( &self->Ready );
0107 }
0108 
0109 static Scheduler_Node *_Scheduler_simple_SMP_Get_highest_ready(
0110   Scheduler_Context *context,
0111   Scheduler_Node    *node
0112 )
0113 {
0114   Scheduler_simple_SMP_Context *self =
0115     _Scheduler_simple_SMP_Get_self( context );
0116   Scheduler_Node *first = (Scheduler_Node *) _Chain_First( &self->Ready );
0117 
0118   (void) node;
0119 
0120   _Assert( &first->Node.Chain != _Chain_Tail( &self->Ready ) );
0121 
0122   return first;
0123 }
0124 
0125 static void _Scheduler_simple_SMP_Move_from_scheduled_to_ready(
0126   Scheduler_Context *context,
0127   Scheduler_Node    *scheduled_to_ready
0128 )
0129 {
0130   Scheduler_simple_SMP_Context *self;
0131   Priority_Control              insert_priority;
0132 
0133   self = _Scheduler_simple_SMP_Get_self( context );
0134 
0135   _Chain_Extract_unprotected( &scheduled_to_ready->Node.Chain );
0136   insert_priority = _Scheduler_SMP_Node_priority( scheduled_to_ready );
0137   _Chain_Insert_ordered_unprotected(
0138     &self->Ready,
0139     &scheduled_to_ready->Node.Chain,
0140     &insert_priority,
0141     _Scheduler_SMP_Priority_less_equal
0142   );
0143 }
0144 
0145 static void _Scheduler_simple_SMP_Move_from_ready_to_scheduled(
0146   Scheduler_Context *context,
0147   Scheduler_Node    *ready_to_scheduled
0148 )
0149 {
0150   Scheduler_simple_SMP_Context *self;
0151   Priority_Control              insert_priority;
0152 
0153   self = _Scheduler_simple_SMP_Get_self( context );
0154 
0155   _Chain_Extract_unprotected( &ready_to_scheduled->Node.Chain );
0156   insert_priority = _Scheduler_SMP_Node_priority( ready_to_scheduled );
0157   insert_priority = SCHEDULER_PRIORITY_APPEND( insert_priority );
0158   _Chain_Insert_ordered_unprotected(
0159     &self->Base.Scheduled,
0160     &ready_to_scheduled->Node.Chain,
0161     &insert_priority,
0162     _Scheduler_SMP_Priority_less_equal
0163   );
0164 }
0165 
0166 static void _Scheduler_simple_SMP_Insert_ready(
0167   Scheduler_Context *context,
0168   Scheduler_Node    *node_to_insert,
0169   Priority_Control   insert_priority
0170 )
0171 {
0172   Scheduler_simple_SMP_Context *self;
0173 
0174   self = _Scheduler_simple_SMP_Get_self( context );
0175 
0176   _Chain_Insert_ordered_unprotected(
0177     &self->Ready,
0178     &node_to_insert->Node.Chain,
0179     &insert_priority,
0180     _Scheduler_SMP_Priority_less_equal
0181   );
0182 }
0183 
0184 static void _Scheduler_simple_SMP_Extract_from_ready(
0185   Scheduler_Context *context,
0186   Scheduler_Node    *node_to_extract
0187 )
0188 {
0189   (void) context;
0190 
0191   _Chain_Extract_unprotected( &node_to_extract->Node.Chain );
0192 }
0193 
0194 static inline Scheduler_Node *_Scheduler_simple_SMP_Get_idle( void *arg )
0195 {
0196   Scheduler_simple_SMP_Context *self =
0197     _Scheduler_simple_SMP_Get_self( arg );
0198   Scheduler_Node *lowest_ready = (Scheduler_Node *) _Chain_Last( &self->Ready );
0199 
0200   _Assert( &lowest_ready->Node.Chain != _Chain_Head( &self->Ready ) );
0201   _Chain_Extract_unprotected( &lowest_ready->Node.Chain );
0202 
0203   return lowest_ready;
0204 }
0205 
0206 static inline void _Scheduler_simple_SMP_Release_idle(
0207   Scheduler_Node *node,
0208   void           *arg
0209 )
0210 {
0211   Scheduler_simple_SMP_Context *self;
0212 
0213   self = _Scheduler_simple_SMP_Get_self( arg );
0214 
0215   _Chain_Append_unprotected( &self->Ready, &node->Node.Chain );
0216 }
0217 
0218 void _Scheduler_simple_SMP_Block(
0219   const Scheduler_Control *scheduler,
0220   Thread_Control          *thread,
0221   Scheduler_Node          *node
0222 )
0223 {
0224   Scheduler_Context *context = _Scheduler_Get_context( scheduler );
0225 
0226   _Scheduler_SMP_Block(
0227     context,
0228     thread,
0229     node,
0230     _Scheduler_SMP_Extract_from_scheduled,
0231     _Scheduler_simple_SMP_Extract_from_ready,
0232     _Scheduler_simple_SMP_Get_highest_ready,
0233     _Scheduler_simple_SMP_Move_from_ready_to_scheduled,
0234     _Scheduler_SMP_Allocate_processor_lazy,
0235     _Scheduler_simple_SMP_Get_idle
0236   );
0237 }
0238 
0239 static bool _Scheduler_simple_SMP_Enqueue(
0240   Scheduler_Context *context,
0241   Scheduler_Node    *node,
0242   Priority_Control   insert_priority
0243 )
0244 {
0245   return _Scheduler_SMP_Enqueue(
0246     context,
0247     node,
0248     insert_priority,
0249     _Scheduler_SMP_Priority_less_equal,
0250     _Scheduler_simple_SMP_Insert_ready,
0251     _Scheduler_SMP_Insert_scheduled,
0252     _Scheduler_simple_SMP_Move_from_scheduled_to_ready,
0253     _Scheduler_simple_SMP_Move_from_ready_to_scheduled,
0254     _Scheduler_SMP_Get_lowest_scheduled,
0255     _Scheduler_SMP_Allocate_processor_lazy,
0256     _Scheduler_simple_SMP_Get_idle,
0257     _Scheduler_simple_SMP_Release_idle
0258   );
0259 }
0260 
0261 static void _Scheduler_simple_SMP_Enqueue_scheduled(
0262   Scheduler_Context *context,
0263   Scheduler_Node    *node,
0264   Priority_Control   insert_priority
0265 )
0266 {
0267   _Scheduler_SMP_Enqueue_scheduled(
0268     context,
0269     node,
0270     insert_priority,
0271     _Scheduler_SMP_Priority_less_equal,
0272     _Scheduler_simple_SMP_Extract_from_ready,
0273     _Scheduler_simple_SMP_Get_highest_ready,
0274     _Scheduler_simple_SMP_Insert_ready,
0275     _Scheduler_SMP_Insert_scheduled,
0276     _Scheduler_simple_SMP_Move_from_ready_to_scheduled,
0277     _Scheduler_SMP_Allocate_processor_lazy,
0278     _Scheduler_simple_SMP_Get_idle,
0279     _Scheduler_simple_SMP_Release_idle
0280   );
0281 }
0282 
0283 void _Scheduler_simple_SMP_Unblock(
0284   const Scheduler_Control *scheduler,
0285   Thread_Control          *thread,
0286   Scheduler_Node          *node
0287 )
0288 {
0289   Scheduler_Context *context = _Scheduler_Get_context( scheduler );
0290 
0291   _Scheduler_SMP_Unblock(
0292     context,
0293     thread,
0294     node,
0295     _Scheduler_simple_SMP_Do_update,
0296     _Scheduler_simple_SMP_Enqueue,
0297     _Scheduler_simple_SMP_Release_idle
0298   );
0299 }
0300 
0301 static bool _Scheduler_simple_SMP_Do_ask_for_help(
0302   Scheduler_Context *context,
0303   Thread_Control    *the_thread,
0304   Scheduler_Node    *node
0305 )
0306 {
0307   return _Scheduler_SMP_Ask_for_help(
0308     context,
0309     the_thread,
0310     node,
0311     _Scheduler_SMP_Priority_less_equal,
0312     _Scheduler_simple_SMP_Insert_ready,
0313     _Scheduler_SMP_Insert_scheduled,
0314     _Scheduler_simple_SMP_Move_from_scheduled_to_ready,
0315     _Scheduler_SMP_Get_lowest_scheduled,
0316     _Scheduler_SMP_Allocate_processor_lazy,
0317     _Scheduler_simple_SMP_Release_idle
0318   );
0319 }
0320 
0321 void _Scheduler_simple_SMP_Update_priority(
0322   const Scheduler_Control *scheduler,
0323   Thread_Control          *thread,
0324   Scheduler_Node          *node
0325 )
0326 {
0327   Scheduler_Context *context = _Scheduler_Get_context( scheduler );
0328 
0329   _Scheduler_SMP_Update_priority(
0330     context,
0331     thread,
0332     node,
0333     _Scheduler_SMP_Extract_from_scheduled,
0334     _Scheduler_simple_SMP_Extract_from_ready,
0335     _Scheduler_simple_SMP_Do_update,
0336     _Scheduler_simple_SMP_Enqueue,
0337     _Scheduler_simple_SMP_Enqueue_scheduled,
0338     _Scheduler_simple_SMP_Do_ask_for_help
0339   );
0340 }
0341 
0342 bool _Scheduler_simple_SMP_Ask_for_help(
0343   const Scheduler_Control *scheduler,
0344   Thread_Control          *the_thread,
0345   Scheduler_Node          *node
0346 )
0347 {
0348   Scheduler_Context *context = _Scheduler_Get_context( scheduler );
0349 
0350   return _Scheduler_simple_SMP_Do_ask_for_help( context, the_thread, node );
0351 }
0352 
0353 void _Scheduler_simple_SMP_Reconsider_help_request(
0354   const Scheduler_Control *scheduler,
0355   Thread_Control          *the_thread,
0356   Scheduler_Node          *node
0357 )
0358 {
0359   Scheduler_Context *context = _Scheduler_Get_context( scheduler );
0360 
0361   _Scheduler_SMP_Reconsider_help_request(
0362     context,
0363     the_thread,
0364     node,
0365     _Scheduler_simple_SMP_Extract_from_ready
0366   );
0367 }
0368 
0369 void _Scheduler_simple_SMP_Withdraw_node(
0370   const Scheduler_Control *scheduler,
0371   Thread_Control          *the_thread,
0372   Scheduler_Node          *node,
0373   Thread_Scheduler_state   next_state
0374 )
0375 {
0376   Scheduler_Context *context = _Scheduler_Get_context( scheduler );
0377 
0378   _Scheduler_SMP_Withdraw_node(
0379     context,
0380     the_thread,
0381     node,
0382     next_state,
0383     _Scheduler_SMP_Extract_from_scheduled,
0384     _Scheduler_simple_SMP_Extract_from_ready,
0385     _Scheduler_simple_SMP_Get_highest_ready,
0386     _Scheduler_simple_SMP_Move_from_ready_to_scheduled,
0387     _Scheduler_SMP_Allocate_processor_lazy,
0388     _Scheduler_simple_SMP_Get_idle
0389   );
0390 }
0391 
0392 void _Scheduler_simple_SMP_Make_sticky(
0393   const Scheduler_Control *scheduler,
0394   Thread_Control          *the_thread,
0395   Scheduler_Node          *node
0396 )
0397 {
0398   _Scheduler_SMP_Make_sticky(
0399     scheduler,
0400     the_thread,
0401     node,
0402     _Scheduler_simple_SMP_Do_update,
0403     _Scheduler_simple_SMP_Enqueue
0404   );
0405 }
0406 
0407 void _Scheduler_simple_SMP_Clean_sticky(
0408   const Scheduler_Control *scheduler,
0409   Thread_Control          *the_thread,
0410   Scheduler_Node          *node
0411 )
0412 {
0413   _Scheduler_SMP_Clean_sticky(
0414     scheduler,
0415     the_thread,
0416     node,
0417     _Scheduler_SMP_Extract_from_scheduled,
0418     _Scheduler_simple_SMP_Extract_from_ready,
0419     _Scheduler_simple_SMP_Get_highest_ready,
0420     _Scheduler_simple_SMP_Move_from_ready_to_scheduled,
0421     _Scheduler_SMP_Allocate_processor_lazy,
0422     _Scheduler_simple_SMP_Get_idle,
0423     _Scheduler_simple_SMP_Release_idle
0424   );
0425 }
0426 
0427 void _Scheduler_simple_SMP_Add_processor(
0428   const Scheduler_Control *scheduler,
0429   Thread_Control          *idle
0430 )
0431 {
0432   Scheduler_Context *context = _Scheduler_Get_context( scheduler );
0433 
0434   _Scheduler_SMP_Add_processor(
0435     context,
0436     idle,
0437     _Scheduler_simple_SMP_Has_ready,
0438     _Scheduler_simple_SMP_Enqueue_scheduled,
0439     _Scheduler_SMP_Do_nothing_register_idle
0440   );
0441 }
0442 
0443 Thread_Control *_Scheduler_simple_SMP_Remove_processor(
0444   const Scheduler_Control *scheduler,
0445   Per_CPU_Control         *cpu
0446 )
0447 {
0448   Scheduler_Context *context = _Scheduler_Get_context( scheduler );
0449 
0450   return _Scheduler_SMP_Remove_processor(
0451     context,
0452     cpu,
0453     _Scheduler_SMP_Extract_from_scheduled,
0454     _Scheduler_simple_SMP_Extract_from_ready,
0455     _Scheduler_simple_SMP_Enqueue,
0456     _Scheduler_simple_SMP_Get_idle,
0457     _Scheduler_simple_SMP_Release_idle
0458   );
0459 }
0460 
0461 void _Scheduler_simple_SMP_Yield(
0462   const Scheduler_Control *scheduler,
0463   Thread_Control          *thread,
0464   Scheduler_Node          *node
0465 )
0466 {
0467   Scheduler_Context *context = _Scheduler_Get_context( scheduler );
0468 
0469   _Scheduler_SMP_Yield(
0470     context,
0471     thread,
0472     node,
0473     _Scheduler_SMP_Extract_from_scheduled,
0474     _Scheduler_simple_SMP_Extract_from_ready,
0475     _Scheduler_simple_SMP_Enqueue,
0476     _Scheduler_simple_SMP_Enqueue_scheduled
0477   );
0478 }