RTEMS 6.1-rc1
schedulersmpimpl.h
Go to the documentation of this file.
1/* SPDX-License-Identifier: BSD-2-Clause */
2
12/*
13 * Copyright (C) 2013, 2021 embedded brains GmbH & Co. KG
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the distribution.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#ifndef _RTEMS_SCORE_SCHEDULERSMPIMPL_H
38#define _RTEMS_SCORE_SCHEDULERSMPIMPL_H
39
41#include <rtems/score/assert.h>
44#include <rtems/bspIo.h>
45
46#ifdef __cplusplus
47extern "C" {
48#endif /* __cplusplus */
49
292typedef bool ( *Scheduler_SMP_Has_ready )(
294);
295
296typedef Scheduler_Node *( *Scheduler_SMP_Get_highest_ready )(
298 Scheduler_Node *filter
299);
300
301typedef Scheduler_Node *( *Scheduler_SMP_Get_lowest_ready )(
303);
304
305typedef Scheduler_Node *( *Scheduler_SMP_Get_lowest_scheduled )(
307 Scheduler_Node *filter
308);
309
310typedef void ( *Scheduler_SMP_Extract )(
312 Scheduler_Node *node_to_extract
313);
314
315typedef void ( *Scheduler_SMP_Insert )(
317 Scheduler_Node *node_to_insert,
318 Priority_Control insert_priority
319);
320
321typedef void ( *Scheduler_SMP_Move )(
323 Scheduler_Node *node_to_move
324);
325
326typedef bool ( *Scheduler_SMP_Ask_for_help )(
328 Thread_Control *thread,
329 Scheduler_Node *node
330);
331
332typedef void ( *Scheduler_SMP_Update )(
334 Scheduler_Node *node_to_update,
335 Priority_Control new_priority
336);
337
338typedef void ( *Scheduler_SMP_Set_affinity )(
340 Scheduler_Node *node,
341 void *arg
342);
343
344typedef bool ( *Scheduler_SMP_Enqueue )(
346 Scheduler_Node *node_to_enqueue,
347 Priority_Control priority
348);
349
350typedef void ( *Scheduler_SMP_Enqueue_scheduled )(
352 Scheduler_Node *node_to_enqueue,
353 Priority_Control priority
354);
355
356typedef void ( *Scheduler_SMP_Allocate_processor )(
358 Scheduler_Node *scheduled,
359 Per_CPU_Control *cpu
360);
361
362typedef void ( *Scheduler_SMP_Register_idle )(
364 Scheduler_Node *idle,
365 Per_CPU_Control *cpu
366);
367
375static inline void _Scheduler_SMP_Do_nothing_register_idle(
377 Scheduler_Node *idle,
378 Per_CPU_Control *cpu
379)
380{
381 (void) context;
382 (void) idle;
383 (void) cpu;
384}
385
398static inline bool _Scheduler_SMP_Priority_less_equal(
399 const void *key,
400 const Chain_Node *to_insert,
401 const Chain_Node *next
402)
403{
404 const Priority_Control *priority_to_insert;
405 const Scheduler_SMP_Node *node_next;
406
407 (void) to_insert;
408 priority_to_insert = (const Priority_Control *) key;
409 node_next = (const Scheduler_SMP_Node *) next;
410
411 return *priority_to_insert <= node_next->priority;
412}
413
421static inline Scheduler_SMP_Context *_Scheduler_SMP_Get_self(
423)
424{
426}
427
433static inline void _Scheduler_SMP_Initialize(
435)
436{
437 _Chain_Initialize_empty( &self->Scheduled );
438}
439
447static inline Scheduler_SMP_Node *_Scheduler_SMP_Thread_get_node(
448 Thread_Control *thread
449)
450{
451 return (Scheduler_SMP_Node *) _Thread_Scheduler_get_home_node( thread );
452}
453
461static inline Scheduler_SMP_Node *_Scheduler_SMP_Thread_get_own_node(
462 Thread_Control *thread
463)
464{
465 return (Scheduler_SMP_Node *) _Thread_Scheduler_get_home_node( thread );
466}
467
475static inline Scheduler_SMP_Node *_Scheduler_SMP_Node_downcast(
476 Scheduler_Node *node
477)
478{
479 return (Scheduler_SMP_Node *) node;
480}
481
489static inline Scheduler_SMP_Node_state _Scheduler_SMP_Node_state(
490 const Scheduler_Node *node
491)
492{
493 return ( (const Scheduler_SMP_Node *) node )->state;
494}
495
503static inline Priority_Control _Scheduler_SMP_Node_priority(
504 const Scheduler_Node *node
505)
506{
507 return ( (const Scheduler_SMP_Node *) node )->priority;
508}
509
518static inline void _Scheduler_SMP_Node_initialize(
519 const Scheduler_Control *scheduler,
520 Scheduler_SMP_Node *node,
521 Thread_Control *thread,
522 Priority_Control priority
523)
524{
525 _Scheduler_Node_do_initialize( scheduler, &node->Base, thread, priority );
526 node->state = SCHEDULER_SMP_NODE_BLOCKED;
527 node->priority = priority;
528}
529
536static inline void _Scheduler_SMP_Node_update_priority(
537 Scheduler_SMP_Node *node,
538 Priority_Control new_priority
539)
540{
541 node->priority = new_priority;
542}
543
550static inline void _Scheduler_SMP_Node_change_state(
551 Scheduler_Node *node,
553)
554{
555 Scheduler_SMP_Node *the_node;
556
557 the_node = _Scheduler_SMP_Node_downcast( node );
558 the_node->state = new_state;
559}
560
570static inline bool _Scheduler_SMP_Is_processor_owned_by_us(
572 const Per_CPU_Control *cpu
573)
574{
575 return cpu->Scheduler.context == context;
576}
577
589 Thread_Control *thread,
590 Per_CPU_Control *cpu
591);
592
600static inline void _Scheduler_SMP_Cancel_ask_for_help( Thread_Control *thread )
601{
602 Per_CPU_Control *cpu;
603
604 _Assert( _ISR_lock_Is_owner( &thread->Scheduler.Lock ) );
605 cpu = thread->Scheduler.ask_for_help_cpu;
606
607 if ( RTEMS_PREDICT_FALSE( cpu != NULL ) ) {
609 }
610}
611
626static inline void _Scheduler_SMP_Request_ask_for_help( Thread_Control *thread )
627{
628 ISR_lock_Context lock_context;
629 Per_CPU_Control *cpu_self;
630
631 cpu_self = _Per_CPU_Get();
632
633 _Assert( thread->Scheduler.ask_for_help_cpu == NULL );
634 thread->Scheduler.ask_for_help_cpu = cpu_self;
635 cpu_self->dispatch_necessary = true;
636
637 _Per_CPU_Acquire( cpu_self, &lock_context );
638 _Chain_Append_unprotected(
639 &cpu_self->Threads_in_need_for_help,
640 &thread->Scheduler.Help_node
641 );
642 _Per_CPU_Release( cpu_self, &lock_context );
643}
644
649typedef enum {
650 SCHEDULER_SMP_DO_SCHEDULE,
651 SCHEDULER_SMP_DO_NOT_SCHEDULE
653
680static inline Scheduler_SMP_Action _Scheduler_SMP_Try_to_schedule(
681 Scheduler_Node *node,
682 Scheduler_Get_idle_node get_idle_node,
683 void *arg
684)
685{
686 ISR_lock_Context lock_context;
687 Thread_Control *owner;
688 Thread_Scheduler_state owner_state;
689 int owner_sticky_level;
690
691 owner = _Scheduler_Node_get_owner( node );
692 _Assert( _Scheduler_Node_get_idle( node ) == NULL );
693
694 _Thread_Scheduler_acquire_critical( owner, &lock_context );
695 owner_state = owner->Scheduler.state;
696 owner_sticky_level = node->sticky_level;
697
698 if ( RTEMS_PREDICT_TRUE( owner_state == THREAD_SCHEDULER_READY ) ) {
699 _Scheduler_SMP_Cancel_ask_for_help( owner );
700 _Scheduler_Thread_change_state( owner, THREAD_SCHEDULER_SCHEDULED );
701 _Thread_Scheduler_release_critical( owner, &lock_context );
702 return SCHEDULER_SMP_DO_SCHEDULE;
703 }
704
705 _Thread_Scheduler_release_critical( owner, &lock_context );
706
707 if (
708 ( owner_state == THREAD_SCHEDULER_SCHEDULED && owner_sticky_level <= 1 ) ||
709 owner_sticky_level == 0
710 ) {
711 _Scheduler_SMP_Node_change_state( node, SCHEDULER_SMP_NODE_BLOCKED );
712
713 return SCHEDULER_SMP_DO_NOT_SCHEDULE;
714 }
715
716 (void) _Scheduler_Use_idle_thread( node, get_idle_node, arg );
717
718 return SCHEDULER_SMP_DO_SCHEDULE;
719}
720
732static inline void _Scheduler_SMP_Allocate_processor_lazy(
734 Scheduler_Node *scheduled,
735 Per_CPU_Control *cpu
736)
737{
738 Thread_Control *scheduled_thread = _Scheduler_Node_get_user( scheduled );
739 Per_CPU_Control *scheduled_cpu = _Thread_Get_CPU( scheduled_thread );
740 Per_CPU_Control *cpu_self = _Per_CPU_Get();
741
742 _Assert( _ISR_Get_level() != 0 );
743
744 if ( cpu == scheduled_cpu ) {
745 _Thread_Set_CPU( scheduled_thread, cpu );
746 _Thread_Dispatch_update_heir( cpu_self, cpu, scheduled_thread );
747
748 return;
749 }
750
751 if (
752 _Thread_Is_executing_on_a_processor( scheduled_thread ) &&
753 _Scheduler_SMP_Is_processor_owned_by_us( context, scheduled_cpu )
754 ) {
755 Thread_Control *heir = scheduled_cpu->heir;
756 _Thread_Dispatch_update_heir( cpu_self, scheduled_cpu, scheduled_thread );
757 _Thread_Set_CPU( heir, cpu );
758 _Thread_Dispatch_update_heir( cpu_self, cpu, heir );
759
760 return;
761 }
762
763 _Thread_Set_CPU( scheduled_thread, cpu );
764 _Thread_Dispatch_update_heir( cpu_self, cpu, scheduled_thread );
765}
766
781static inline void _Scheduler_SMP_Allocate_processor_exact(
783 Scheduler_Node *scheduled,
784 Per_CPU_Control *cpu
785)
786{
787 Thread_Control *scheduled_thread = _Scheduler_Node_get_user( scheduled );
788 Per_CPU_Control *cpu_self = _Per_CPU_Get();
789
790 (void) context;
791
792 _Thread_Set_CPU( scheduled_thread, cpu );
793 _Thread_Dispatch_update_heir( cpu_self, cpu, scheduled_thread );
794}
795
808static inline void _Scheduler_SMP_Allocate_processor(
810 Scheduler_Node *scheduled,
811 Per_CPU_Control *cpu,
812 Scheduler_SMP_Allocate_processor allocate_processor
813)
814{
815 _Scheduler_SMP_Node_change_state( scheduled, SCHEDULER_SMP_NODE_SCHEDULED );
816 ( *allocate_processor )( context, scheduled, cpu );
817}
818
834static inline void _Scheduler_SMP_Preempt(
836 Scheduler_Node *scheduled,
837 Scheduler_Node *victim,
838 Thread_Control *victim_idle,
839 Scheduler_SMP_Allocate_processor allocate_processor
840)
841{
842 Thread_Control *victim_owner;
843 ISR_lock_Context lock_context;
844 Per_CPU_Control *cpu;
845
846 _Scheduler_SMP_Node_change_state( victim, SCHEDULER_SMP_NODE_READY );
847
848 victim_owner = _Scheduler_Node_get_owner( victim );
849 _Thread_Scheduler_acquire_critical( victim_owner, &lock_context );
850
851 if ( RTEMS_PREDICT_TRUE( victim_idle == NULL ) ) {
852 if ( victim_owner->Scheduler.state == THREAD_SCHEDULER_SCHEDULED ) {
853 _Scheduler_Thread_change_state( victim_owner, THREAD_SCHEDULER_READY );
854
855 if ( victim_owner->Scheduler.helping_nodes > 0 ) {
856 _Scheduler_SMP_Request_ask_for_help( victim_owner );
857 }
858 }
859
860 cpu = _Thread_Get_CPU( victim_owner );
861 } else {
862 cpu = _Thread_Get_CPU( victim_idle );
863 }
864
865 _Thread_Scheduler_release_critical( victim_owner, &lock_context );
866
867 _Scheduler_SMP_Allocate_processor(
868 context,
869 scheduled,
870 cpu,
871 allocate_processor
872 );
873}
874
883static inline Scheduler_Node *_Scheduler_SMP_Get_lowest_scheduled(
885 Scheduler_Node *filter
886)
887{
889 Scheduler_Node *lowest_scheduled;
890
891 (void) filter;
892
893 self = _Scheduler_SMP_Get_self( context );
894
895 _Assert( !_Chain_Is_empty( &self->Scheduled ) );
896 lowest_scheduled = (Scheduler_Node *) _Chain_Last( &self->Scheduled );
897
898 _Assert(
899 _Chain_Next( &lowest_scheduled->Node.Chain ) ==
900 _Chain_Tail( &self->Scheduled )
901 );
902
903 return lowest_scheduled;
904}
905
922static inline void _Scheduler_SMP_Enqueue_to_scheduled(
924 Scheduler_Node *node,
925 Priority_Control priority,
926 Scheduler_Node *lowest_scheduled,
927 Scheduler_SMP_Insert insert_scheduled,
928 Scheduler_SMP_Move move_from_scheduled_to_ready,
929 Scheduler_SMP_Move move_from_ready_to_scheduled,
930 Scheduler_SMP_Allocate_processor allocate_processor,
931 Scheduler_Get_idle_node get_idle_node,
932 Scheduler_Release_idle_node release_idle_node
933)
934{
935 Thread_Control *lowest_scheduled_idle;
937
938 lowest_scheduled_idle = _Scheduler_Release_idle_thread_if_necessary(
939 lowest_scheduled,
940 release_idle_node,
941 context
942 );
943
944 ( *move_from_scheduled_to_ready )( context, lowest_scheduled );
945
946 action = _Scheduler_SMP_Try_to_schedule( node, get_idle_node, context );
947
948 if ( RTEMS_PREDICT_TRUE( action == SCHEDULER_SMP_DO_SCHEDULE ) ) {
949 _Scheduler_SMP_Preempt(
950 context,
951 node,
952 lowest_scheduled,
953 lowest_scheduled_idle,
954 allocate_processor
955 );
956
957 ( *insert_scheduled )( context, node, priority );
958 } else {
959 _Assert( action == SCHEDULER_SMP_DO_NOT_SCHEDULE );
960
961 if ( lowest_scheduled_idle != NULL ) {
962 (void) _Scheduler_Use_idle_thread( lowest_scheduled, get_idle_node, context );
963 }
964
965 ( *move_from_ready_to_scheduled )( context, lowest_scheduled );
966 }
967}
968
991static inline bool _Scheduler_SMP_Enqueue(
993 Scheduler_Node *node,
994 Priority_Control insert_priority,
995 Chain_Node_order order,
996 Scheduler_SMP_Insert insert_ready,
997 Scheduler_SMP_Insert insert_scheduled,
998 Scheduler_SMP_Move move_from_scheduled_to_ready,
999 Scheduler_SMP_Move move_from_ready_to_scheduled,
1000 Scheduler_SMP_Get_lowest_scheduled get_lowest_scheduled,
1001 Scheduler_SMP_Allocate_processor allocate_processor,
1002 Scheduler_Get_idle_node get_idle_node,
1003 Scheduler_Release_idle_node release_idle_node
1004)
1005{
1006 bool needs_help;
1007 Scheduler_Node *lowest_scheduled;
1008
1009 lowest_scheduled = ( *get_lowest_scheduled )( context, node );
1010
1011 if (
1012 ( *order )(
1013 &insert_priority,
1014 &node->Node.Chain,
1015 &lowest_scheduled->Node.Chain
1016 )
1017 ) {
1018 _Scheduler_SMP_Enqueue_to_scheduled(
1019 context,
1020 node,
1021 insert_priority,
1022 lowest_scheduled,
1023 insert_scheduled,
1024 move_from_scheduled_to_ready,
1025 move_from_ready_to_scheduled,
1026 allocate_processor,
1027 get_idle_node,
1028 release_idle_node
1029 );
1030 needs_help = false;
1031 } else {
1032 _Scheduler_SMP_Node_change_state( node, SCHEDULER_SMP_NODE_READY );
1033 ( *insert_ready )( context, node, insert_priority );
1034 needs_help = true;
1035 }
1036
1037 return needs_help;
1038}
1039
1059static inline void _Scheduler_SMP_Enqueue_scheduled(
1061 Scheduler_Node *const node,
1062 Priority_Control insert_priority,
1063 Chain_Node_order order,
1064 Scheduler_SMP_Extract extract_from_ready,
1065 Scheduler_SMP_Get_highest_ready get_highest_ready,
1066 Scheduler_SMP_Insert insert_ready,
1067 Scheduler_SMP_Insert insert_scheduled,
1068 Scheduler_SMP_Move move_from_ready_to_scheduled,
1069 Scheduler_SMP_Allocate_processor allocate_processor,
1070 Scheduler_Get_idle_node get_idle_node,
1071 Scheduler_Release_idle_node release_idle_node
1072)
1073{
1074 Thread_Control *node_idle;
1075
1076 node_idle = _Scheduler_Release_idle_thread_if_necessary(
1077 node,
1078 release_idle_node,
1079 context
1080 );
1081
1082 while ( true ) {
1083 Scheduler_Node *highest_ready;
1084 Scheduler_SMP_Action action;
1085
1086 highest_ready = ( *get_highest_ready )( context, node );
1087
1088 /*
1089 * The node has been extracted from the scheduled chain. We have to place
1090 * it now on the scheduled or ready set.
1091 */
1092 if (
1093 node->sticky_level > 0 && ( *order )(
1094 &insert_priority,
1095 &node->Node.Chain,
1096 &highest_ready->Node.Chain
1097 )
1098 ) {
1099 if ( node_idle != NULL ) {
1100 Thread_Control *owner;
1101 ISR_lock_Context lock_context;
1102
1103 owner = _Scheduler_Node_get_owner( node );
1104 _Thread_Scheduler_acquire_critical( owner, &lock_context );
1105
1106 if ( owner->Scheduler.state == THREAD_SCHEDULER_READY ) {
1107 Per_CPU_Control *cpu;
1108
1109 _Scheduler_SMP_Cancel_ask_for_help( owner );
1110 _Scheduler_Thread_change_state( owner, THREAD_SCHEDULER_SCHEDULED );
1111 cpu = _Thread_Get_CPU( node_idle );
1112 _Thread_Set_CPU( owner, cpu );
1113 _Thread_Scheduler_release_critical( owner, &lock_context );
1114 _Thread_Dispatch_update_heir( _Per_CPU_Get(), cpu, owner );
1115 } else {
1116 Thread_Control *new_idle;
1117
1118 _Thread_Scheduler_release_critical( owner, &lock_context );
1119 new_idle = _Scheduler_Use_idle_thread( node, get_idle_node, context );
1120 _Assert_Unused_variable_equals( new_idle, node_idle );
1121 }
1122 }
1123
1124 ( *insert_scheduled )( context, node, insert_priority );
1125
1126 return;
1127 }
1128
1129 action = _Scheduler_SMP_Try_to_schedule(
1130 highest_ready,
1131 get_idle_node,
1132 context
1133 );
1134
1135 if ( RTEMS_PREDICT_TRUE( action == SCHEDULER_SMP_DO_SCHEDULE ) ) {
1136 _Scheduler_SMP_Preempt(
1137 context,
1138 highest_ready,
1139 node,
1140 node_idle,
1141 allocate_processor
1142 );
1143
1144 ( *move_from_ready_to_scheduled )( context, highest_ready );
1145 ( *insert_ready )( context, node, insert_priority );
1146 return;
1147 }
1148
1149 _Assert( action == SCHEDULER_SMP_DO_NOT_SCHEDULE );
1150 ( *extract_from_ready )( context, highest_ready );
1151 }
1152}
1153
1160static inline void _Scheduler_SMP_Extract_from_scheduled(
1162 Scheduler_Node *node
1163)
1164{
1165 (void) context;
1166 _Chain_Extract_unprotected( &node->Node.Chain );
1167}
1168
1185static inline void _Scheduler_SMP_Schedule_highest_ready(
1187 Scheduler_Node *victim,
1188 Per_CPU_Control *cpu,
1189 Scheduler_SMP_Extract extract_from_scheduled,
1190 Scheduler_SMP_Extract extract_from_ready,
1191 Scheduler_SMP_Get_highest_ready get_highest_ready,
1192 Scheduler_SMP_Move move_from_ready_to_scheduled,
1193 Scheduler_SMP_Allocate_processor allocate_processor,
1194 Scheduler_Get_idle_node get_idle_node
1195)
1196{
1197 Scheduler_SMP_Action action;
1198
1199 _Scheduler_SMP_Node_change_state( victim, SCHEDULER_SMP_NODE_BLOCKED );
1200 ( *extract_from_scheduled )( context, victim );
1201
1202 while ( true ) {
1203 Scheduler_Node *highest_ready = ( *get_highest_ready )( context, victim );
1204
1205 action = _Scheduler_SMP_Try_to_schedule(
1206 highest_ready,
1207 get_idle_node,
1208 context
1209 );
1210
1211 if ( RTEMS_PREDICT_TRUE( action == SCHEDULER_SMP_DO_SCHEDULE ) ) {
1212 _Scheduler_SMP_Allocate_processor(
1213 context,
1214 highest_ready,
1215 cpu,
1216 allocate_processor
1217 );
1218
1219 ( *move_from_ready_to_scheduled )( context, highest_ready );
1220 return;
1221 }
1222
1223 _Assert( action == SCHEDULER_SMP_DO_NOT_SCHEDULE );
1224 ( *extract_from_ready )( context, highest_ready );
1225 }
1226}
1227
1241static inline void _Scheduler_SMP_Preempt_and_schedule_highest_ready(
1243 Scheduler_Node *victim,
1244 Scheduler_SMP_Extract extract_from_ready,
1245 Scheduler_SMP_Get_highest_ready get_highest_ready,
1246 Scheduler_SMP_Move move_from_ready_to_scheduled,
1247 Scheduler_SMP_Allocate_processor allocate_processor,
1248 Scheduler_Get_idle_node get_idle_node,
1249 Scheduler_Release_idle_node release_idle_node
1250)
1251{
1252 Thread_Control *victim_idle;
1253 Scheduler_SMP_Action action;
1254
1255 _Scheduler_SMP_Node_change_state( victim, SCHEDULER_SMP_NODE_READY );
1256 victim_idle = _Scheduler_Release_idle_thread_if_necessary(
1257 victim,
1258 release_idle_node,
1259 context
1260 );
1261
1262 while ( true ) {
1263 Scheduler_Node *highest_ready = ( *get_highest_ready )( context, victim );
1264
1265 action = _Scheduler_SMP_Try_to_schedule(
1266 highest_ready,
1267 get_idle_node,
1268 context
1269 );
1270
1271 if ( RTEMS_PREDICT_TRUE( action == SCHEDULER_SMP_DO_SCHEDULE ) ) {
1272 _Scheduler_SMP_Preempt(
1273 context,
1274 highest_ready,
1275 victim,
1276 victim_idle,
1277 allocate_processor
1278 );
1279
1280 ( *move_from_ready_to_scheduled )( context, highest_ready );
1281 return;
1282 }
1283
1284 _Assert( action == SCHEDULER_SMP_DO_NOT_SCHEDULE );
1285 ( *extract_from_ready )( context, highest_ready );
1286 }
1287}
1288
1305static inline void _Scheduler_SMP_Block(
1307 Thread_Control *thread,
1308 Scheduler_Node *node,
1309 Scheduler_SMP_Extract extract_from_scheduled,
1310 Scheduler_SMP_Extract extract_from_ready,
1311 Scheduler_SMP_Get_highest_ready get_highest_ready,
1312 Scheduler_SMP_Move move_from_ready_to_scheduled,
1313 Scheduler_SMP_Allocate_processor allocate_processor,
1314 Scheduler_Get_idle_node get_idle_node
1315)
1316{
1317 int sticky_level;
1318 ISR_lock_Context lock_context;
1319 Scheduler_SMP_Node_state node_state;
1320 Per_CPU_Control *cpu;
1321
1322 sticky_level = node->sticky_level;
1323 --sticky_level;
1324 node->sticky_level = sticky_level;
1325 _Assert( sticky_level >= 0 );
1326
1327 _Thread_Scheduler_acquire_critical( thread, &lock_context );
1328 _Scheduler_SMP_Cancel_ask_for_help( thread );
1329 cpu = _Thread_Get_CPU( thread );
1330 _Scheduler_Thread_change_state( thread, THREAD_SCHEDULER_BLOCKED );
1331 _Thread_Scheduler_release_critical( thread, &lock_context );
1332
1333 node_state = _Scheduler_SMP_Node_state( node );
1334
1335 if ( RTEMS_PREDICT_FALSE( sticky_level > 0 ) ) {
1336 if (
1337 node_state == SCHEDULER_SMP_NODE_SCHEDULED &&
1338 _Scheduler_Node_get_idle( node ) == NULL
1339 ) {
1340 Thread_Control *idle;
1341
1342 idle = _Scheduler_Use_idle_thread( node, get_idle_node, context );
1343 _Thread_Set_CPU( idle, cpu );
1344 _Thread_Dispatch_update_heir( _Per_CPU_Get(), cpu, idle );
1345 }
1346
1347 return;
1348 }
1349
1350 _Assert( _Scheduler_Node_get_user( node ) == thread );
1351 _Assert( _Scheduler_Node_get_idle( node ) == NULL );
1352
1353 if ( node_state == SCHEDULER_SMP_NODE_SCHEDULED ) {
1354 _Scheduler_SMP_Schedule_highest_ready(
1355 context,
1356 node,
1357 cpu,
1358 extract_from_scheduled,
1359 extract_from_ready,
1360 get_highest_ready,
1361 move_from_ready_to_scheduled,
1362 allocate_processor,
1363 get_idle_node
1364 );
1365 } else if ( node_state == SCHEDULER_SMP_NODE_READY ) {
1366 _Scheduler_SMP_Node_change_state( node, SCHEDULER_SMP_NODE_BLOCKED );
1367 ( *extract_from_ready )( context, node );
1368 }
1369}
1370
1381static inline void _Scheduler_SMP_Unblock(
1383 Thread_Control *thread,
1384 Scheduler_Node *node,
1385 Scheduler_SMP_Update update,
1386 Scheduler_SMP_Enqueue enqueue,
1387 Scheduler_Release_idle_node release_idle_node
1388)
1389{
1390 Scheduler_SMP_Node_state node_state;
1391 Priority_Control priority;
1392
1393 _Assert( _Chain_Is_node_off_chain( &thread->Scheduler.Help_node ) );
1394
1395 ++node->sticky_level;
1396 _Assert( node->sticky_level > 0 );
1397
1398 node_state = _Scheduler_SMP_Node_state( node );
1399
1400 if ( RTEMS_PREDICT_FALSE( node_state == SCHEDULER_SMP_NODE_SCHEDULED ) ) {
1401 _Scheduler_Thread_change_state( thread, THREAD_SCHEDULER_SCHEDULED );
1402 _Scheduler_Discard_idle_thread(
1403 thread,
1404 node,
1405 release_idle_node,
1406 context
1407 );
1408
1409 return;
1410 }
1411
1412 _Scheduler_Thread_change_state( thread, THREAD_SCHEDULER_READY );
1413
1414 priority = _Scheduler_Node_get_priority( node );
1415 priority = SCHEDULER_PRIORITY_PURIFY( priority );
1416
1417 if ( priority != _Scheduler_SMP_Node_priority( node ) ) {
1418 ( *update )( context, node, priority );
1419 }
1420
1421 if ( node_state == SCHEDULER_SMP_NODE_BLOCKED ) {
1422 Priority_Control insert_priority;
1423 bool needs_help;
1424
1425 insert_priority = SCHEDULER_PRIORITY_APPEND( priority );
1426 needs_help = ( *enqueue )( context, node, insert_priority );
1427
1428 if ( needs_help && thread->Scheduler.helping_nodes > 0 ) {
1429 _Scheduler_SMP_Request_ask_for_help( thread );
1430 }
1431 } else {
1432 _Assert( node_state == SCHEDULER_SMP_NODE_READY );
1433 _Assert( node->sticky_level > 0 );
1434 _Assert( node->idle == NULL );
1435 _Scheduler_SMP_Request_ask_for_help( thread );
1436 }
1437}
1438
1460static inline void _Scheduler_SMP_Update_priority(
1462 Thread_Control *thread,
1463 Scheduler_Node *node,
1464 Scheduler_SMP_Extract extract_from_scheduled,
1465 Scheduler_SMP_Extract extract_from_ready,
1466 Scheduler_SMP_Update update,
1467 Scheduler_SMP_Enqueue enqueue,
1468 Scheduler_SMP_Enqueue_scheduled enqueue_scheduled,
1469 Scheduler_SMP_Ask_for_help ask_for_help
1470)
1471{
1472 Priority_Control priority;
1473 Priority_Control insert_priority;
1474 Scheduler_SMP_Node_state node_state;
1475
1476 insert_priority = _Scheduler_Node_get_priority( node );
1477 priority = SCHEDULER_PRIORITY_PURIFY( insert_priority );
1478
1479 if ( priority == _Scheduler_SMP_Node_priority( node ) ) {
1480 if ( _Thread_Is_ready( thread ) ) {
1481 ( *ask_for_help )( context, thread, node );
1482 }
1483
1484 return;
1485 }
1486
1487 node_state = _Scheduler_SMP_Node_state( node );
1488
1489 if ( node_state == SCHEDULER_SMP_NODE_SCHEDULED ) {
1490 ( *extract_from_scheduled )( context, node );
1491 ( *update )( context, node, priority );
1492 ( *enqueue_scheduled )( context, node, insert_priority );
1493 } else if ( node_state == SCHEDULER_SMP_NODE_READY ) {
1494 ( *extract_from_ready )( context, node );
1495 ( *update )( context, node, priority );
1496 ( *enqueue )( context, node, insert_priority );
1497 } else {
1498 ( *update )( context, node, priority );
1499
1500 if ( _Thread_Is_ready( thread ) ) {
1501 ( *ask_for_help )( context, thread, node );
1502 }
1503 }
1504}
1505
1519static inline void _Scheduler_SMP_Yield(
1521 Thread_Control *thread,
1522 Scheduler_Node *node,
1523 Scheduler_SMP_Extract extract_from_scheduled,
1524 Scheduler_SMP_Extract extract_from_ready,
1525 Scheduler_SMP_Enqueue enqueue,
1526 Scheduler_SMP_Enqueue_scheduled enqueue_scheduled
1527)
1528{
1529 Scheduler_SMP_Node_state node_state;
1530 Priority_Control insert_priority;
1531
1532 node_state = _Scheduler_SMP_Node_state( node );
1533 insert_priority = _Scheduler_SMP_Node_priority( node );
1534 insert_priority = SCHEDULER_PRIORITY_APPEND( insert_priority );
1535
1536 if ( node_state == SCHEDULER_SMP_NODE_SCHEDULED ) {
1537 ( *extract_from_scheduled )( context, node );
1538 ( *enqueue_scheduled )( context, node, insert_priority );
1539 } else if ( node_state == SCHEDULER_SMP_NODE_READY ) {
1540 ( *extract_from_ready )( context, node );
1541 (void) ( *enqueue )( context, node, insert_priority );
1542 }
1543}
1544
1552static inline void _Scheduler_SMP_Insert_scheduled(
1554 Scheduler_Node *node_to_insert,
1555 Priority_Control priority_to_insert
1556)
1557{
1559
1560 self = _Scheduler_SMP_Get_self( context );
1561
1562 _Chain_Insert_ordered_unprotected(
1563 &self->Scheduled,
1564 &node_to_insert->Node.Chain,
1565 &priority_to_insert,
1566 _Scheduler_SMP_Priority_less_equal
1567 );
1568}
1569
1592static inline bool _Scheduler_SMP_Ask_for_help(
1594 Thread_Control *thread,
1595 Scheduler_Node *node,
1596 Chain_Node_order order,
1597 Scheduler_SMP_Insert insert_ready,
1598 Scheduler_SMP_Insert insert_scheduled,
1599 Scheduler_SMP_Move move_from_scheduled_to_ready,
1600 Scheduler_SMP_Get_lowest_scheduled get_lowest_scheduled,
1601 Scheduler_SMP_Allocate_processor allocate_processor,
1602 Scheduler_Release_idle_node release_idle_node
1603)
1604{
1605 Scheduler_Node *lowest_scheduled;
1606 ISR_lock_Context lock_context;
1607 bool success;
1608
1609 if ( thread->Scheduler.pinned_scheduler != NULL ) {
1610 /*
1611 * Pinned threads are not allowed to ask for help. Return success to break
1612 * the loop in _Thread_Ask_for_help() early.
1613 */
1614 return true;
1615 }
1616
1617 lowest_scheduled = ( *get_lowest_scheduled )( context, node );
1618
1619 _Thread_Scheduler_acquire_critical( thread, &lock_context );
1620
1621 if ( thread->Scheduler.state == THREAD_SCHEDULER_READY ) {
1622 Scheduler_SMP_Node_state node_state;
1623
1624 node_state = _Scheduler_SMP_Node_state( node );
1625
1626 if ( node_state == SCHEDULER_SMP_NODE_BLOCKED ) {
1627 Priority_Control insert_priority;
1628
1629 insert_priority = _Scheduler_SMP_Node_priority( node );
1630
1631 if (
1632 ( *order )(
1633 &insert_priority,
1634 &node->Node.Chain,
1635 &lowest_scheduled->Node.Chain
1636 )
1637 ) {
1638 Thread_Control *lowest_scheduled_idle;
1639
1640 _Scheduler_SMP_Cancel_ask_for_help( thread );
1641 _Scheduler_Thread_change_state( thread, THREAD_SCHEDULER_SCHEDULED );
1642 _Thread_Scheduler_release_critical( thread, &lock_context );
1643
1644 lowest_scheduled_idle = _Scheduler_Release_idle_thread_if_necessary(
1645 lowest_scheduled,
1646 release_idle_node,
1647 context
1648 );
1649
1650 _Scheduler_SMP_Preempt(
1651 context,
1652 node,
1653 lowest_scheduled,
1654 lowest_scheduled_idle,
1655 allocate_processor
1656 );
1657
1658 ( *move_from_scheduled_to_ready )( context, lowest_scheduled );
1659 ( *insert_scheduled )( context, node, insert_priority );
1660
1661 success = true;
1662 } else {
1663 _Thread_Scheduler_release_critical( thread, &lock_context );
1664
1665 _Scheduler_SMP_Node_change_state( node, SCHEDULER_SMP_NODE_READY );
1666 ( *insert_ready )( context, node, insert_priority );
1667 success = false;
1668 }
1669 } else if ( node_state == SCHEDULER_SMP_NODE_SCHEDULED ) {
1670 _Scheduler_SMP_Cancel_ask_for_help( thread );
1671 _Scheduler_Thread_change_state( thread, THREAD_SCHEDULER_SCHEDULED );
1672 _Thread_Scheduler_release_critical( thread, &lock_context );
1673 _Scheduler_Discard_idle_thread(
1674 thread,
1675 node,
1676 release_idle_node,
1677 context
1678 );
1679 success = true;
1680 } else {
1681 _Thread_Scheduler_release_critical( thread, &lock_context );
1682 success = false;
1683 }
1684 } else {
1685 _Thread_Scheduler_release_critical( thread, &lock_context );
1686 success = false;
1687 }
1688
1689 return success;
1690}
1691
1701static inline void _Scheduler_SMP_Reconsider_help_request(
1703 Thread_Control *thread,
1704 Scheduler_Node *node,
1705 Scheduler_SMP_Extract extract_from_ready
1706)
1707{
1708 ISR_lock_Context lock_context;
1709
1710 _Thread_Scheduler_acquire_critical( thread, &lock_context );
1711
1712 if (
1713 thread->Scheduler.state == THREAD_SCHEDULER_SCHEDULED
1714 && _Scheduler_SMP_Node_state( node ) == SCHEDULER_SMP_NODE_READY
1715 && node->sticky_level == 1
1716 ) {
1717 _Scheduler_SMP_Node_change_state( node, SCHEDULER_SMP_NODE_BLOCKED );
1718 ( *extract_from_ready )( context, node );
1719 }
1720
1721 _Thread_Scheduler_release_critical( thread, &lock_context );
1722}
1723
1741static inline void _Scheduler_SMP_Withdraw_node(
1743 Thread_Control *thread,
1744 Scheduler_Node *node,
1745 Thread_Scheduler_state next_state,
1746 Scheduler_SMP_Extract extract_from_scheduled,
1747 Scheduler_SMP_Extract extract_from_ready,
1748 Scheduler_SMP_Get_highest_ready get_highest_ready,
1749 Scheduler_SMP_Move move_from_ready_to_scheduled,
1750 Scheduler_SMP_Allocate_processor allocate_processor,
1751 Scheduler_Get_idle_node get_idle_node
1752)
1753{
1754 ISR_lock_Context lock_context;
1755 Scheduler_SMP_Node_state node_state;
1756
1757 _Thread_Scheduler_acquire_critical( thread, &lock_context );
1758
1759 node_state = _Scheduler_SMP_Node_state( node );
1760
1761 if ( node_state == SCHEDULER_SMP_NODE_SCHEDULED ) {
1762 Per_CPU_Control *cpu;
1763
1764 _Assert( thread == _Scheduler_Node_get_user( node ) );
1765 cpu = _Thread_Get_CPU( thread );
1766 _Scheduler_Thread_change_state( thread, next_state );
1767 _Thread_Scheduler_release_critical( thread, &lock_context );
1768
1769 _Assert( _Scheduler_Node_get_user( node ) == thread );
1770 _Assert( _Scheduler_Node_get_idle( node ) == NULL );
1771
1772 _Scheduler_SMP_Schedule_highest_ready(
1773 context,
1774 node,
1775 cpu,
1776 extract_from_scheduled,
1777 extract_from_ready,
1778 get_highest_ready,
1779 move_from_ready_to_scheduled,
1780 allocate_processor,
1781 get_idle_node
1782 );
1783 } else if ( node_state == SCHEDULER_SMP_NODE_READY ) {
1784 _Thread_Scheduler_release_critical( thread, &lock_context );
1785 _Scheduler_SMP_Node_change_state( node, SCHEDULER_SMP_NODE_BLOCKED );
1786 ( *extract_from_ready )( context, node );
1787 } else {
1788 _Assert( node_state == SCHEDULER_SMP_NODE_BLOCKED );
1789 _Thread_Scheduler_release_critical( thread, &lock_context );
1790 }
1791}
1792
1802static inline void _Scheduler_SMP_Make_sticky(
1803 const Scheduler_Control *scheduler,
1804 Thread_Control *the_thread,
1805 Scheduler_Node *node,
1806 Scheduler_SMP_Update update,
1807 Scheduler_SMP_Enqueue enqueue
1808)
1809{
1810 Scheduler_SMP_Node_state node_state;
1811
1812 node_state = _Scheduler_SMP_Node_state( node );
1813
1814 if ( node_state == SCHEDULER_SMP_NODE_BLOCKED ) {
1816 Priority_Control insert_priority;
1817 Priority_Control priority;
1818
1819 context = _Scheduler_Get_context( scheduler );
1820 priority = _Scheduler_Node_get_priority( node );
1821 priority = SCHEDULER_PRIORITY_PURIFY( priority );
1822
1823 if ( priority != _Scheduler_SMP_Node_priority( node ) ) {
1824 ( *update )( context, node, priority );
1825 }
1826
1827 insert_priority = SCHEDULER_PRIORITY_APPEND( priority );
1828 (void) ( *enqueue )( context, node, insert_priority );
1829 }
1830}
1831
1841static inline void _Scheduler_SMP_Clean_sticky(
1842 const Scheduler_Control *scheduler,
1843 Thread_Control *the_thread,
1844 Scheduler_Node *node,
1845 Scheduler_SMP_Extract extract_from_scheduled,
1846 Scheduler_SMP_Extract extract_from_ready,
1847 Scheduler_SMP_Get_highest_ready get_highest_ready,
1848 Scheduler_SMP_Move move_from_ready_to_scheduled,
1849 Scheduler_SMP_Allocate_processor allocate_processor,
1850 Scheduler_Get_idle_node get_idle_node,
1851 Scheduler_Release_idle_node release_idle_node
1852)
1853{
1854 Scheduler_SMP_Node_state node_state;
1855
1856 node_state = _Scheduler_SMP_Node_state( node );
1857
1858 if ( node_state == SCHEDULER_SMP_NODE_SCHEDULED ) {
1859 Thread_Control *idle;
1860
1861 idle = _Scheduler_Node_get_idle( node );
1862
1863 if ( idle != NULL ) {
1865
1866 context = _Scheduler_Get_context( scheduler );
1867
1868 _Scheduler_Release_idle_thread( node, idle, release_idle_node, context );
1869 _Scheduler_SMP_Schedule_highest_ready(
1870 context,
1871 node,
1872 _Thread_Get_CPU( idle ),
1873 extract_from_scheduled,
1874 extract_from_ready,
1875 get_highest_ready,
1876 move_from_ready_to_scheduled,
1877 allocate_processor,
1878 get_idle_node
1879 );
1880 }
1881 }
1882}
1883
1892static inline void _Scheduler_SMP_Do_start_idle(
1894 Thread_Control *idle,
1895 Per_CPU_Control *cpu,
1896 Scheduler_SMP_Register_idle register_idle
1897)
1898{
1900 Scheduler_SMP_Node *node;
1901
1902 self = _Scheduler_SMP_Get_self( context );
1903 node = _Scheduler_SMP_Thread_get_node( idle );
1904
1905 _Scheduler_Thread_change_state( idle, THREAD_SCHEDULER_SCHEDULED );
1906 node->state = SCHEDULER_SMP_NODE_SCHEDULED;
1907
1908 _Thread_Set_CPU( idle, cpu );
1909 ( *register_idle )( context, &node->Base, cpu );
1910 _Chain_Append_unprotected( &self->Scheduled, &node->Base.Node.Chain );
1911}
1912
1922static inline void _Scheduler_SMP_Add_processor(
1924 Thread_Control *idle,
1925 Scheduler_SMP_Has_ready has_ready,
1926 Scheduler_SMP_Enqueue_scheduled enqueue_scheduled,
1927 Scheduler_SMP_Register_idle register_idle
1928)
1929{
1931 Scheduler_Node *node;
1932
1933 self = _Scheduler_SMP_Get_self( context );
1934 idle->Scheduler.state = THREAD_SCHEDULER_SCHEDULED;
1935 node = _Thread_Scheduler_get_home_node( idle );
1936 _Scheduler_SMP_Node_change_state( node, SCHEDULER_SMP_NODE_SCHEDULED );
1937 ( *register_idle )( context, node, _Thread_Get_CPU( idle ) );
1938
1939 if ( ( *has_ready )( &self->Base ) ) {
1940 Priority_Control insert_priority;
1941
1942 insert_priority = _Scheduler_SMP_Node_priority( node );
1943 insert_priority = SCHEDULER_PRIORITY_APPEND( insert_priority );
1944 ( *enqueue_scheduled )( &self->Base, node, insert_priority );
1945 } else {
1946 _Chain_Append_unprotected( &self->Scheduled, &node->Node.Chain );
1947 }
1948}
1949
1963static inline Thread_Control *_Scheduler_SMP_Remove_processor(
1965 Per_CPU_Control *cpu,
1966 Scheduler_SMP_Extract extract_from_scheduled,
1967 Scheduler_SMP_Extract extract_from_ready,
1968 Scheduler_SMP_Enqueue enqueue,
1969 Scheduler_Get_idle_node get_idle_node,
1970 Scheduler_Release_idle_node release_idle_node
1971)
1972{
1974 Chain_Node *chain_node;
1975 Scheduler_Node *victim_node;
1976 Thread_Control *victim_user;
1977 Thread_Control *victim_owner;
1978 Thread_Control *idle;
1979
1980 self = _Scheduler_SMP_Get_self( context );
1981 chain_node = _Chain_First( &self->Scheduled );
1982
1983 do {
1984 _Assert( chain_node != _Chain_Immutable_tail( &self->Scheduled ) );
1985 victim_node = (Scheduler_Node *) chain_node;
1986 victim_user = _Scheduler_Node_get_user( victim_node );
1987 chain_node = _Chain_Next( chain_node );
1988 } while ( _Thread_Get_CPU( victim_user ) != cpu );
1989
1990 ( *extract_from_scheduled )( &self->Base, victim_node );
1991 victim_owner = _Scheduler_Node_get_owner( victim_node );
1992
1993 if ( !victim_owner->is_idle ) {
1994 Thread_Control *victim_idle;
1995 Scheduler_Node *idle_node;
1996 Priority_Control insert_priority;
1997
1998 victim_idle = _Scheduler_Release_idle_thread_if_necessary(
1999 victim_node,
2000 release_idle_node,
2001 &self->Base
2002 );
2003 idle_node = ( *get_idle_node )( &self->Base );
2004 idle = _Scheduler_Node_get_owner( idle_node );
2005 _Scheduler_SMP_Preempt(
2006 &self->Base,
2007 idle_node,
2008 victim_node,
2009 victim_idle,
2010 _Scheduler_SMP_Allocate_processor_exact
2011 );
2012
2013 _Assert( !_Chain_Is_empty( &self->Scheduled ) );
2014 insert_priority = _Scheduler_SMP_Node_priority( victim_node );
2015 insert_priority = SCHEDULER_PRIORITY_APPEND( insert_priority );
2016 ( *enqueue )( &self->Base, victim_node, insert_priority );
2017 } else {
2018 _Assert( victim_owner == victim_user );
2019 _Assert( _Scheduler_Node_get_idle( victim_node ) == NULL );
2020 idle = victim_owner;
2021 }
2022
2023 return idle;
2024}
2025
2047static inline void _Scheduler_SMP_Set_affinity(
2049 Thread_Control *thread,
2050 Scheduler_Node *node,
2051 void *arg,
2052 Scheduler_SMP_Set_affinity set_affinity,
2053 Scheduler_SMP_Extract extract_from_scheduled,
2054 Scheduler_SMP_Extract extract_from_ready,
2055 Scheduler_SMP_Get_highest_ready get_highest_ready,
2056 Scheduler_SMP_Move move_from_ready_to_scheduled,
2057 Scheduler_SMP_Enqueue enqueue,
2058 Scheduler_SMP_Allocate_processor allocate_processor,
2059 Scheduler_Get_idle_node get_idle_node,
2060 Scheduler_Release_idle_node release_idle_node
2061)
2062{
2063 Scheduler_SMP_Node_state node_state;
2064 Priority_Control insert_priority;
2065
2066 node_state = _Scheduler_SMP_Node_state( node );
2067 insert_priority = _Scheduler_SMP_Node_priority( node );
2068 insert_priority = SCHEDULER_PRIORITY_APPEND( insert_priority );
2069
2070 if ( node_state == SCHEDULER_SMP_NODE_SCHEDULED ) {
2071 ( *extract_from_scheduled )( context, node );
2072 _Scheduler_SMP_Preempt_and_schedule_highest_ready(
2073 context,
2074 node,
2075 extract_from_ready,
2076 get_highest_ready,
2077 move_from_ready_to_scheduled,
2078 allocate_processor,
2079 get_idle_node,
2080 release_idle_node
2081 );
2082 ( *set_affinity )( context, node, arg );
2083 ( *enqueue )( context, node, insert_priority );
2084 } else if ( node_state == SCHEDULER_SMP_NODE_READY ) {
2085 ( *extract_from_ready )( context, node );
2086 ( *set_affinity )( context, node, arg );
2087 ( *enqueue )( context, node, insert_priority );
2088 } else {
2089 _Assert( node_state == SCHEDULER_SMP_NODE_BLOCKED );
2090 ( *set_affinity )( context, node, arg );
2091 }
2092}
2093
2096#ifdef __cplusplus
2097}
2098#endif /* __cplusplus */
2099
2100#endif /* _RTEMS_SCORE_SCHEDULERSMPIMPL_H */
This header file provides the interfaces of the Assert Handler.
This header file provides the kernel character input/output support API.
This header file provides interfaces of the Chain Handler which are only used by the implementation.
#define RTEMS_PREDICT_FALSE(_exp)
Evaluates the integral expression and tells the compiler that the predicted value is false (0).
Definition: basedefs.h:732
#define RTEMS_PREDICT_TRUE(_exp)
Evaluates the integral expression and tells the compiler that the predicted value is true (1).
Definition: basedefs.h:751
#define _Assert_Unused_variable_equals(_var, _val)
Assert if unused return value is equal.
Definition: assert.h:108
#define _Assert(_e)
Assertion similar to assert() controlled via RTEMS_DEBUG instead of NDEBUG and static analysis runs.
Definition: assert.h:96
bool(* Chain_Node_order)(const void *key, const Chain_Node *left, const Chain_Node *right)
Chain node order.
Definition: chainimpl.h:847
#define _ISR_Get_level()
Return current interrupt level.
Definition: isrlevel.h:147
uint64_t Priority_Control
The thread priority control.
Definition: priority.h:91
void _Scheduler_SMP_Remove_ask_for_help_from_processor(Thread_Control *thread, Per_CPU_Control *cpu)
Removes the thread's ask for help request from the processor.
Definition: schedulersmp.c:43
Scheduler_SMP_Action
This enumeration defines what a scheduler should do with a node which could be scheduled.
Definition: schedulersmpimpl.h:649
Scheduler_SMP_Node_state
SMP scheduler node states.
Definition: schedulersmp.h:76
@ SCHEDULER_SMP_NODE_READY
This scheduler node is ready.
Definition: schedulersmp.h:100
@ SCHEDULER_SMP_NODE_BLOCKED
This scheduler node is blocked.
Definition: schedulersmp.h:82
@ SCHEDULER_SMP_NODE_SCHEDULED
The scheduler node is scheduled.
Definition: schedulersmp.h:92
#define SCHEDULER_PRIORITY_APPEND(priority)
Returns the priority control with the append indicator bit set.
Definition: schedulernodeimpl.h:81
#define SCHEDULER_PRIORITY_PURIFY(priority)
Clears the priority append indicator bit.
Definition: schedulernodeimpl.h:75
#define NULL
Requests a GPIO pin group configuration.
Definition: xil_types.h:54
rtems_termios_device_context * context
Definition: console-config.c:62
This header file provides interfaces of the Simple Priority Scheduler which are only used by the impl...
This header file provides interfaces of the SMP Scheduler which are used by the implementation and th...
This structure represents a chain node.
Definition: chain.h:78
Local ISR lock context for acquire and release pairs.
Definition: isrlock.h:81
Per CPU Core Structure.
Definition: percpu.h:384
struct _Thread_Control * heir
This is the heir thread for this processor.
Definition: percpu.h:473
volatile bool dispatch_necessary
This is set to true when this processor needs to run the thread dispatcher.
Definition: percpu.h:437
Scheduler context.
Definition: scheduler.h:318
Scheduler node for per-thread data.
Definition: schedulernode.h:94
Scheduler context specialization for SMP schedulers.
Definition: schedulersmp.h:61
Chain_Control Scheduled
The chain of scheduled nodes.
Definition: schedulersmp.h:70
Scheduler_Context Base
Basic scheduler context.
Definition: schedulersmp.h:65
Scheduler node specialization for SMP schedulers.
Definition: schedulersmp.h:106
Scheduler_SMP_Node_state state
The state of this node.
Definition: schedulersmp.h:115
Priority_Control priority
The current priority of thread owning this node.
Definition: schedulersmp.h:120
Scheduler control.
Definition: scheduler.h:335
Definition: thread.h:812
Thread_Scheduler_control Scheduler
Scheduler related control.
Definition: thread.h:849