File indexing completed on 2025-05-11 08:24:43
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 #ifdef HAVE_CONFIG_H
0029 #include "config.h"
0030 #endif
0031
0032 #include <rtems.h>
0033 #include <rtems/libcsupport.h>
0034 #include <rtems/score/threadimpl.h>
0035 #include <rtems/score/schedulersmpimpl.h>
0036
0037 #include "tmacros.h"
0038
0039 void Init(rtems_task_argument arg);
0040
0041 static Scheduler_SMP_Node *get_scheduler_node(Thread_Control *thread)
0042 {
0043 return _Scheduler_SMP_Node_downcast(_Thread_Scheduler_get_home_node(thread));
0044 }
0045
0046 static void apply_priority(
0047 Thread_Control *thread,
0048 Priority_Control new_priority,
0049 Priority_Group_order priority_group_order,
0050 Thread_queue_Context *queue_context
0051 )
0052 {
0053 const Scheduler_Control *scheduler;
0054
0055 scheduler = _Thread_Scheduler_get_home(thread);
0056 new_priority = _Scheduler_Map_priority(scheduler, new_priority);
0057
0058 _Thread_queue_Context_initialize(queue_context);
0059 _Thread_queue_Context_clear_priority_updates(queue_context);
0060 _Thread_Wait_acquire(thread, queue_context);
0061 _Thread_Priority_change(
0062 thread,
0063 &thread->Real_priority,
0064 new_priority,
0065 priority_group_order,
0066 queue_context
0067 );
0068 _Thread_Wait_release(thread, queue_context);
0069 }
0070
0071 static void change_priority(
0072 Thread_Control *thread,
0073 Priority_Control new_priority,
0074 Priority_Group_order priority_group_order
0075 )
0076 {
0077 Thread_queue_Context queue_context;
0078
0079 apply_priority(thread, new_priority, priority_group_order, &queue_context);
0080 _Thread_Priority_update(&queue_context);
0081 }
0082
0083 static void task(rtems_task_argument arg)
0084 {
0085 rtems_test_assert(0);
0086 }
0087
0088 static rtems_id start_task(rtems_task_priority prio)
0089 {
0090 rtems_status_code sc;
0091 rtems_id task_id;
0092
0093 sc = rtems_task_create(
0094 rtems_build_name('T', 'A', 'S', 'K'),
0095 prio,
0096 RTEMS_MINIMUM_STACK_SIZE,
0097 RTEMS_DEFAULT_MODES,
0098 RTEMS_DEFAULT_ATTRIBUTES,
0099 &task_id
0100 );
0101 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0102
0103 sc = rtems_task_start(task_id, task, 0);
0104 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0105
0106 return task_id;
0107 }
0108
0109 static Thread_Control *get_thread_by_id(rtems_id task_id)
0110 {
0111 ISR_lock_Context lock_context;
0112 Thread_Control *thread;
0113
0114 thread = _Thread_Get(task_id, &lock_context);
0115 rtems_test_assert(thread != NULL);
0116 _ISR_lock_ISR_enable(&lock_context);
0117
0118 return thread;
0119 }
0120
0121 static void test_case_change_priority(
0122 Thread_Control *executing,
0123 Scheduler_SMP_Node *executing_node,
0124 Scheduler_SMP_Node_state start_state,
0125 Priority_Control prio,
0126 Priority_Group_order priority_group_order,
0127 Scheduler_SMP_Node_state new_state
0128 )
0129 {
0130 Per_CPU_Control *cpu_self;
0131
0132 cpu_self = _Thread_Dispatch_disable();
0133
0134 switch (start_state) {
0135 case SCHEDULER_SMP_NODE_SCHEDULED:
0136 change_priority(executing, 1, PRIORITY_GROUP_FIRST);
0137 break;
0138 case SCHEDULER_SMP_NODE_READY:
0139 change_priority(executing, 4, PRIORITY_GROUP_FIRST);
0140 break;
0141 default:
0142 rtems_test_assert(0);
0143 break;
0144 }
0145 rtems_test_assert(executing_node->state == start_state);
0146
0147 change_priority(executing, prio, priority_group_order);
0148 rtems_test_assert(executing_node->state == new_state);
0149
0150 change_priority(executing, 1, PRIORITY_GROUP_FIRST);
0151 rtems_test_assert(executing_node->state == SCHEDULER_SMP_NODE_SCHEDULED);
0152
0153 _Thread_Dispatch_enable( cpu_self );
0154 }
0155
0156 static const Scheduler_SMP_Node_state states[2] = {
0157 SCHEDULER_SMP_NODE_SCHEDULED,
0158 SCHEDULER_SMP_NODE_READY
0159 };
0160
0161 static const Priority_Control priorities[2] = { 2, 5 };
0162
0163 static const Priority_Group_order priority_group_order[2] = {
0164 PRIORITY_GROUP_FIRST,
0165 PRIORITY_GROUP_LAST
0166 };
0167
0168 static void test_change_priority(void)
0169 {
0170 rtems_status_code sc;
0171 rtems_id task_id;
0172 Thread_Control *executing;
0173 Scheduler_SMP_Node *executing_node;
0174 size_t i;
0175 size_t j;
0176 size_t k;
0177
0178 task_id = start_task(3);
0179 executing = _Thread_Get_executing();
0180 executing_node = get_scheduler_node(executing);
0181
0182 for (i = 0; i < RTEMS_ARRAY_SIZE(states); ++i) {
0183 for (j = 0; j < RTEMS_ARRAY_SIZE(priorities); ++j) {
0184 for (k = 0; k < RTEMS_ARRAY_SIZE(priority_group_order); ++k) {
0185 test_case_change_priority(
0186 executing,
0187 executing_node,
0188 states[i],
0189 priorities[j],
0190 priority_group_order[k],
0191 states[j]
0192 );
0193 }
0194 }
0195 }
0196
0197 sc = rtems_task_delete(task_id);
0198 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0199 }
0200
0201 static void update_priority_op(
0202 Thread_Control *thread,
0203 Scheduler_SMP_Node *scheduler_node,
0204 Priority_Control new_priority,
0205 Priority_Group_order priority_group_order
0206 )
0207 {
0208 const Scheduler_Control *scheduler;
0209 ISR_lock_Context state_lock_context;
0210 ISR_lock_Context scheduler_lock_context;
0211 Thread_queue_Context queue_context;
0212
0213 apply_priority(thread, new_priority, priority_group_order, &queue_context);
0214
0215 _Thread_State_acquire( thread, &state_lock_context );
0216 scheduler = _Thread_Scheduler_get_home( thread );
0217 _Scheduler_Acquire_critical( scheduler, &scheduler_lock_context );
0218
0219 (*scheduler->Operations.update_priority)(
0220 scheduler,
0221 thread,
0222 &scheduler_node->Base
0223 );
0224
0225 _Scheduler_Release_critical( scheduler, &scheduler_lock_context );
0226 _Thread_State_release( thread, &state_lock_context );
0227 }
0228
0229 static void test_case_update_priority_op(
0230 Thread_Control *executing,
0231 Scheduler_SMP_Node *executing_node,
0232 Thread_Control *other,
0233 Scheduler_SMP_Node_state start_state,
0234 Priority_Control prio,
0235 Priority_Group_order priority_group_order,
0236 Scheduler_SMP_Node_state new_state
0237 )
0238 {
0239 Per_CPU_Control *cpu_self;
0240
0241 cpu_self = _Thread_Dispatch_disable();
0242
0243 switch (start_state) {
0244 case SCHEDULER_SMP_NODE_SCHEDULED:
0245 change_priority(executing, 1, PRIORITY_GROUP_FIRST);
0246 break;
0247 case SCHEDULER_SMP_NODE_READY:
0248 change_priority(executing, 4, PRIORITY_GROUP_FIRST);
0249 break;
0250 default:
0251 rtems_test_assert(0);
0252 break;
0253 }
0254 rtems_test_assert(executing_node->state == start_state);
0255
0256 update_priority_op(executing, executing_node, prio, priority_group_order);
0257 rtems_test_assert(executing_node->state == new_state);
0258
0259 if (start_state != new_state) {
0260 switch (start_state) {
0261 case SCHEDULER_SMP_NODE_SCHEDULED:
0262 rtems_test_assert(cpu_self->heir == other);
0263 break;
0264 case SCHEDULER_SMP_NODE_READY:
0265 rtems_test_assert(cpu_self->heir == executing);
0266 break;
0267 default:
0268 rtems_test_assert(0);
0269 break;
0270 }
0271 }
0272
0273 change_priority(executing, 1, PRIORITY_GROUP_FIRST);
0274 rtems_test_assert(executing_node->state == SCHEDULER_SMP_NODE_SCHEDULED);
0275
0276 _Thread_Dispatch_enable( cpu_self );
0277 }
0278
0279 static void test_update_priority_op(void)
0280 {
0281 rtems_status_code sc;
0282 rtems_id task_id;
0283 Thread_Control *executing;
0284 Scheduler_SMP_Node *executing_node;
0285 Thread_Control *other;
0286 size_t i;
0287 size_t j;
0288 size_t k;
0289
0290 task_id = start_task(3);
0291 executing = _Thread_Get_executing();
0292 executing_node = get_scheduler_node(executing);
0293
0294 other = get_thread_by_id(task_id);
0295
0296 for (i = 0; i < RTEMS_ARRAY_SIZE(states); ++i) {
0297 for (j = 0; j < RTEMS_ARRAY_SIZE(priorities); ++j) {
0298 for (k = 0; k < RTEMS_ARRAY_SIZE(priority_group_order); ++k) {
0299 test_case_update_priority_op(
0300 executing,
0301 executing_node,
0302 other,
0303 states[i],
0304 priorities[j],
0305 priority_group_order[k],
0306 states[j]
0307 );
0308 }
0309 }
0310 }
0311
0312 sc = rtems_task_delete(task_id);
0313 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0314 }
0315
0316 static void yield_op(
0317 Thread_Control *thread,
0318 Scheduler_SMP_Node *scheduler_node
0319 )
0320 {
0321 const Scheduler_Control *scheduler;
0322 ISR_lock_Context state_lock_context;
0323 ISR_lock_Context scheduler_lock_context;
0324
0325 _Thread_State_acquire( thread, &state_lock_context );
0326 scheduler = _Thread_Scheduler_get_home( thread );
0327 _Scheduler_Acquire_critical( scheduler, &scheduler_lock_context );
0328
0329 (*scheduler->Operations.yield)(
0330 scheduler,
0331 thread,
0332 &scheduler_node->Base
0333 );
0334
0335 _Scheduler_Release_critical( scheduler, &scheduler_lock_context );
0336 _Thread_State_release( thread, &state_lock_context );
0337 }
0338
0339 static void test_case_yield_op(
0340 Thread_Control *executing,
0341 Scheduler_SMP_Node *executing_node,
0342 Thread_Control *other,
0343 Scheduler_SMP_Node_state start_state,
0344 Scheduler_SMP_Node_state new_state
0345 )
0346 {
0347 Per_CPU_Control *cpu_self;
0348
0349 cpu_self = _Thread_Dispatch_disable();
0350
0351 change_priority(executing, 4, PRIORITY_GROUP_LAST);
0352 change_priority(other, 4, PRIORITY_GROUP_LAST);
0353
0354 switch (start_state) {
0355 case SCHEDULER_SMP_NODE_SCHEDULED:
0356 switch (new_state) {
0357 case SCHEDULER_SMP_NODE_SCHEDULED:
0358 change_priority(executing, 2, PRIORITY_GROUP_LAST);
0359 change_priority(other, 3, PRIORITY_GROUP_LAST);
0360 break;
0361 case SCHEDULER_SMP_NODE_READY:
0362 change_priority(executing, 2, PRIORITY_GROUP_LAST);
0363 change_priority(other, 2, PRIORITY_GROUP_LAST);
0364 break;
0365 default:
0366 rtems_test_assert(0);
0367 break;
0368 }
0369 break;
0370 case SCHEDULER_SMP_NODE_READY:
0371 switch (new_state) {
0372 case SCHEDULER_SMP_NODE_SCHEDULED:
0373 rtems_test_assert(0);
0374 break;
0375 case SCHEDULER_SMP_NODE_READY:
0376 change_priority(executing, 3, PRIORITY_GROUP_LAST);
0377 change_priority(other, 2, PRIORITY_GROUP_LAST);
0378 break;
0379 default:
0380 rtems_test_assert(0);
0381 break;
0382 }
0383 break;
0384 default:
0385 rtems_test_assert(0);
0386 break;
0387 }
0388 rtems_test_assert(executing_node->state == start_state);
0389
0390 yield_op(executing, executing_node);
0391 rtems_test_assert(executing_node->state == new_state);
0392
0393 switch (new_state) {
0394 case SCHEDULER_SMP_NODE_SCHEDULED:
0395 case SCHEDULER_SMP_NODE_READY:
0396 break;
0397 default:
0398 rtems_test_assert(0);
0399 break;
0400 }
0401
0402 change_priority(executing, 1, PRIORITY_GROUP_FIRST);
0403 rtems_test_assert(executing_node->state == SCHEDULER_SMP_NODE_SCHEDULED);
0404
0405 _Thread_Dispatch_enable( cpu_self );
0406 }
0407
0408 static void test_yield_op(void)
0409 {
0410 rtems_status_code sc;
0411 rtems_id task_id;
0412 Thread_Control *executing;
0413 Scheduler_SMP_Node *executing_node;
0414 Thread_Control *other;
0415 size_t i;
0416 size_t j;
0417
0418 task_id = start_task(2);
0419 executing = _Thread_Get_executing();
0420 executing_node = get_scheduler_node(executing);
0421
0422 other = get_thread_by_id(task_id);
0423
0424 for (i = 0; i < RTEMS_ARRAY_SIZE(states); ++i) {
0425 for (j = 0; j < RTEMS_ARRAY_SIZE(states); ++j) {
0426 if (
0427 states[i] != SCHEDULER_SMP_NODE_READY
0428 || states[j] != SCHEDULER_SMP_NODE_SCHEDULED
0429 ) {
0430 test_case_yield_op(
0431 executing,
0432 executing_node,
0433 other,
0434 states[i],
0435 states[j]
0436 );
0437 }
0438 }
0439 }
0440
0441 sc = rtems_task_delete(task_id);
0442 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0443 }
0444
0445 static void block_op(
0446 Thread_Control *thread,
0447 Scheduler_SMP_Node *scheduler_node
0448 )
0449 {
0450 const Scheduler_Control *scheduler;
0451 ISR_lock_Context state_lock_context;
0452 ISR_lock_Context scheduler_lock_context;
0453
0454 _Thread_State_acquire( thread, &state_lock_context );
0455 scheduler = _Thread_Scheduler_get_home( thread );
0456 _Scheduler_Acquire_critical( scheduler, &scheduler_lock_context );
0457
0458 (*scheduler->Operations.block)(scheduler, thread, &scheduler_node->Base);
0459
0460 _Scheduler_Release_critical( scheduler, &scheduler_lock_context );
0461 _Thread_State_release( thread, &state_lock_context );
0462 }
0463
0464 static void unblock_op(
0465 Thread_Control *thread,
0466 Scheduler_SMP_Node *scheduler_node
0467 )
0468 {
0469 const Scheduler_Control *scheduler;
0470 ISR_lock_Context state_lock_context;
0471 ISR_lock_Context scheduler_lock_context;
0472
0473 _Thread_State_acquire( thread, &state_lock_context );
0474 scheduler = _Thread_Scheduler_get_home( thread );
0475 _Scheduler_Acquire_critical( scheduler, &scheduler_lock_context );
0476
0477 (*scheduler->Operations.unblock)(
0478 scheduler,
0479 thread,
0480 &scheduler_node->Base
0481 );
0482
0483 _Scheduler_Release_critical( scheduler, &scheduler_lock_context );
0484 _Thread_State_release( thread, &state_lock_context );
0485 }
0486
0487 static void test_case_unblock_op(
0488 Thread_Control *executing,
0489 Scheduler_SMP_Node *executing_node,
0490 Thread_Control *other,
0491 Scheduler_SMP_Node_state new_state
0492 )
0493 {
0494 Per_CPU_Control *cpu_self;
0495
0496 cpu_self = _Thread_Dispatch_disable();
0497
0498 switch (new_state) {
0499 case SCHEDULER_SMP_NODE_SCHEDULED:
0500 change_priority(executing, 2, PRIORITY_GROUP_LAST);
0501 rtems_test_assert(executing_node->state == SCHEDULER_SMP_NODE_SCHEDULED);
0502 break;
0503 case SCHEDULER_SMP_NODE_READY:
0504 change_priority(executing, 4, PRIORITY_GROUP_LAST);
0505 rtems_test_assert(executing_node->state == SCHEDULER_SMP_NODE_READY);
0506 break;
0507 default:
0508 rtems_test_assert(0);
0509 break;
0510 }
0511
0512 block_op(executing, executing_node);
0513 rtems_test_assert(executing_node->state == SCHEDULER_SMP_NODE_BLOCKED);
0514
0515 unblock_op(executing, executing_node);
0516 rtems_test_assert(executing_node->state == new_state);
0517
0518 switch (new_state) {
0519 case SCHEDULER_SMP_NODE_SCHEDULED:
0520 case SCHEDULER_SMP_NODE_READY:
0521 break;
0522 default:
0523 rtems_test_assert(0);
0524 break;
0525 }
0526
0527 change_priority(executing, 1, PRIORITY_GROUP_FIRST);
0528 rtems_test_assert(executing_node->state == SCHEDULER_SMP_NODE_SCHEDULED);
0529
0530 _Thread_Dispatch_enable( cpu_self );
0531 }
0532
0533 static void test_unblock_op(void)
0534 {
0535 rtems_status_code sc;
0536 rtems_id task_id;
0537 Thread_Control *executing;
0538 Scheduler_SMP_Node *executing_node;
0539 Thread_Control *other;
0540 size_t i;
0541
0542 task_id = start_task(3);
0543 executing = _Thread_Get_executing();
0544 executing_node = get_scheduler_node(executing);
0545
0546 other = get_thread_by_id(task_id);
0547
0548 for (i = 0; i < RTEMS_ARRAY_SIZE(states); ++i) {
0549 test_case_unblock_op(
0550 executing,
0551 executing_node,
0552 other,
0553 states[i]
0554 );
0555 }
0556
0557 sc = rtems_task_delete(task_id);
0558 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0559 }
0560
0561 void Init(rtems_task_argument arg)
0562 {
0563 rtems_resource_snapshot snapshot;
0564 rtems_status_code sc;
0565 rtems_id task_id;
0566
0567 TEST_BEGIN();
0568
0569 rtems_resource_snapshot_take(&snapshot);
0570
0571 sc = rtems_task_create(
0572 rtems_build_name('T', 'A', 'S', 'K'),
0573 255,
0574 RTEMS_MINIMUM_STACK_SIZE,
0575 RTEMS_DEFAULT_MODES,
0576 RTEMS_DEFAULT_ATTRIBUTES,
0577 &task_id
0578 );
0579 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0580
0581 test_change_priority();
0582 test_update_priority_op();
0583 test_yield_op();
0584 test_unblock_op();
0585
0586 sc = rtems_task_delete(task_id);
0587 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0588
0589 rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
0590
0591 TEST_END();
0592 rtems_test_exit(0);
0593 }