File indexing completed on 2025-05-11 08:24:21
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
0029
0030
0031
0032
0033
0034
0035
0036
0037 #ifdef HAVE_CONFIG_H
0038 #include "config.h"
0039 #endif
0040
0041 #include <rtems/test-scheduler.h>
0042
0043 #include <rtems.h>
0044 #include <rtems/score/percpu.h>
0045 #include <rtems/score/schedulerimpl.h>
0046
0047 typedef struct {
0048 RTEMS_INTERRUPT_LOCK_MEMBER(lock)
0049 T_scheduler_log *active;
0050 T_scheduler_event_handler handler;
0051 void *arg;
0052 } T_scheduler_context;
0053
0054 static T_scheduler_context T_scheduler_instance = {
0055 #ifdef RTEMS_SMP
0056 .lock = RTEMS_INTERRUPT_LOCK_INITIALIZER("Test Scheduler"),
0057 #endif
0058 .active = NULL
0059 };
0060
0061 void
0062 T_scheduler_set_event_handler(T_scheduler_event_handler handler, void *arg)
0063 {
0064 T_scheduler_context *ctx;
0065 rtems_interrupt_lock_context lock_context;
0066
0067 ctx = &T_scheduler_instance;
0068
0069 rtems_interrupt_lock_acquire(&ctx->lock, &lock_context);
0070 ctx->handler = handler;
0071 ctx->arg = arg;
0072 rtems_interrupt_lock_release(&ctx->lock, &lock_context);
0073 }
0074
0075 static void
0076 T_scheduler_before_operation(T_scheduler_event *event)
0077 {
0078 T_scheduler_context *ctx;
0079 rtems_interrupt_lock_context lock_context;
0080 T_scheduler_log *log;
0081 T_scheduler_event_handler handler;
0082 void *arg;
0083 Per_CPU_Control *cpu_self;
0084
0085 ctx = &T_scheduler_instance;
0086 log = ctx->active;
0087 handler = ctx->handler;
0088
0089 if (log == NULL && handler == NULL) {
0090 return;
0091 }
0092
0093 rtems_interrupt_lock_interrupt_disable(&lock_context);
0094 cpu_self = _Per_CPU_Get();
0095 event->cpu = _Per_CPU_Get_index( cpu_self );
0096
0097 if (_Per_CPU_Is_ISR_in_progress(cpu_self)) {
0098 event->executing = NULL;
0099 } else {
0100 event->executing = _Per_CPU_Get_executing(cpu_self);
0101 }
0102
0103 event->instant = T_now();
0104
0105 rtems_interrupt_lock_acquire_isr(&ctx->lock, &lock_context);
0106 handler = ctx->handler;
0107 arg = ctx->arg;
0108 rtems_interrupt_lock_release(&ctx->lock, &lock_context);
0109
0110 if (handler != NULL) {
0111 (*handler)(arg, event, T_SCHEDULER_BEFORE);
0112 }
0113 }
0114
0115 static void
0116 T_scheduler_record_event(T_scheduler_event *event)
0117 {
0118 T_scheduler_context *ctx;
0119 rtems_interrupt_lock_context lock_context;
0120 T_scheduler_log *log;
0121 T_scheduler_event_handler handler;
0122
0123 ctx = &T_scheduler_instance;
0124 log = ctx->active;
0125 handler = ctx->handler;
0126
0127 if (log == NULL && handler == NULL) {
0128 return;
0129 }
0130
0131 rtems_interrupt_lock_acquire(&ctx->lock, &lock_context);
0132
0133 #ifdef RTEMS_SMP
0134 handler = ctx->handler;
0135 #endif
0136
0137 if (handler != NULL) {
0138 void *arg;
0139
0140 arg = ctx->arg;
0141
0142 rtems_interrupt_lock_release(&ctx->lock, &lock_context);
0143 (*handler)(arg, event, T_SCHEDULER_AFTER);
0144 rtems_interrupt_lock_acquire(&ctx->lock, &lock_context);
0145 }
0146
0147 #ifdef RTEMS_SMP
0148 log = ctx->active;
0149 #endif
0150
0151 if (log != NULL) {
0152 size_t recorded;
0153
0154 ++log->header.operations;
0155 recorded = log->header.recorded;
0156
0157 if (recorded < log->header.capacity) {
0158 log->header.recorded = recorded + 1;
0159 log->events[recorded] = *event;
0160 }
0161 }
0162
0163 rtems_interrupt_lock_release(&ctx->lock, &lock_context);
0164 }
0165
0166 T_scheduler_log *
0167 T_scheduler_record(T_scheduler_log *log)
0168 {
0169 rtems_interrupt_lock_context lock_context;
0170 T_scheduler_log *previous;
0171 T_scheduler_context *ctx;
0172
0173 if (log != NULL) {
0174 log->header.recorded = 0;
0175 log->header.operations = 0;
0176 }
0177
0178 ctx = &T_scheduler_instance;
0179
0180 rtems_interrupt_lock_acquire(&ctx->lock, &lock_context);
0181 previous = ctx->active;
0182 ctx->active = log;
0183 rtems_interrupt_lock_release(&ctx->lock, &lock_context);
0184
0185 return previous;
0186 }
0187
0188 T_scheduler_log *
0189 T_scheduler_record_2(T_scheduler_log_2 *log)
0190 {
0191 log->header.capacity = T_ARRAY_SIZE(log->events);
0192 return T_scheduler_record((T_scheduler_log *)log);
0193 }
0194
0195 T_scheduler_log *
0196 T_scheduler_record_4(T_scheduler_log_4 *log)
0197 {
0198 log->header.capacity = T_ARRAY_SIZE(log->events);
0199 return T_scheduler_record((T_scheduler_log *)log);
0200 }
0201
0202 T_scheduler_log *
0203 T_scheduler_record_10(T_scheduler_log_10 *log)
0204 {
0205 log->header.capacity = T_ARRAY_SIZE(log->events);
0206 return T_scheduler_record((T_scheduler_log *)log);
0207 }
0208
0209 T_scheduler_log *
0210 T_scheduler_record_20(T_scheduler_log_20 *log)
0211 {
0212 log->header.capacity = T_ARRAY_SIZE(log->events);
0213 return T_scheduler_record((T_scheduler_log *)log);
0214 }
0215
0216 T_scheduler_log *
0217 T_scheduler_record_40(T_scheduler_log_40 *log)
0218 {
0219 log->header.capacity = T_ARRAY_SIZE(log->events);
0220 return T_scheduler_record((T_scheduler_log *)log);
0221 }
0222
0223 const T_scheduler_event T_scheduler_event_null;
0224
0225 const T_scheduler_event *
0226 T_scheduler_next(T_scheduler_header *header, T_scheduler_operation operation,
0227 size_t *index)
0228 {
0229 T_scheduler_log *log;
0230 size_t i;
0231
0232 log = (T_scheduler_log *)header;
0233
0234 if (log == NULL) {
0235 return &T_scheduler_event_null;
0236 }
0237
0238 i = *index;
0239
0240 while (i < log->header.recorded) {
0241 if (operation == T_SCHEDULER_ANY ||
0242 operation == log->events[i].operation) {
0243 *index = i + 1;
0244 return &log->events[i];
0245 }
0246
0247 ++i;
0248 }
0249
0250 return &T_scheduler_event_null;
0251 }
0252
0253 const T_scheduler_event *
0254 T_scheduler_next_any(T_scheduler_header *header, size_t *index)
0255 {
0256 return T_scheduler_next(header, T_SCHEDULER_ANY, index);
0257 }
0258
0259 void
0260 T_scheduler_initialize(const Scheduler_Control *scheduler)
0261 {
0262 T_scheduler_event event = {
0263 .operation = T_SCHEDULER_INITIALIZE
0264 };
0265 const Scheduler_Operations *operations;
0266
0267 operations = &T_scheduler_operations[_Scheduler_Get_index(scheduler)];
0268 T_scheduler_before_operation(&event);
0269 (*operations->initialize)(scheduler);
0270 T_scheduler_record_event(&event);
0271 }
0272
0273 void
0274 T_scheduler_schedule(const Scheduler_Control *scheduler,
0275 Thread_Control *thread)
0276 {
0277 T_scheduler_event event = {
0278 .operation = T_SCHEDULER_SCHEDULE,
0279 .thread = thread
0280 };
0281 const Scheduler_Operations *operations;
0282
0283 operations = &T_scheduler_operations[_Scheduler_Get_index(scheduler)];
0284 T_scheduler_before_operation(&event);
0285 (*operations->schedule)(scheduler, thread);
0286 T_scheduler_record_event(&event);
0287 }
0288
0289 void
0290 T_scheduler_yield(const Scheduler_Control *scheduler, Thread_Control *thread,
0291 Scheduler_Node *node)
0292 {
0293 T_scheduler_event event = {
0294 .operation = T_SCHEDULER_YIELD,
0295 .thread = thread,
0296 .node = node
0297 };
0298 const Scheduler_Operations *operations;
0299
0300 operations = &T_scheduler_operations[_Scheduler_Get_index(scheduler)];
0301 T_scheduler_before_operation(&event);
0302 (*operations->yield)(scheduler, thread, node);
0303 T_scheduler_record_event(&event);
0304 }
0305
0306 void
0307 T_scheduler_block(const Scheduler_Control *scheduler, Thread_Control *thread,
0308 Scheduler_Node *node)
0309 {
0310 T_scheduler_event event = {
0311 .operation = T_SCHEDULER_BLOCK,
0312 .thread = thread,
0313 .node = node
0314 };
0315 const Scheduler_Operations *operations;
0316
0317 operations = &T_scheduler_operations[_Scheduler_Get_index(scheduler)];
0318 T_scheduler_before_operation(&event);
0319 (*operations->block)(scheduler, thread, node);
0320 T_scheduler_record_event(&event);
0321 }
0322
0323 void
0324 T_scheduler_unblock(const Scheduler_Control *scheduler, Thread_Control *thread,
0325 Scheduler_Node *node)
0326 {
0327 T_scheduler_event event = {
0328 .operation = T_SCHEDULER_UNBLOCK,
0329 .thread = thread,
0330 .node = node
0331 };
0332 const Scheduler_Operations *operations;
0333
0334 operations = &T_scheduler_operations[_Scheduler_Get_index(scheduler)];
0335 T_scheduler_before_operation(&event);
0336 (*operations->unblock)(scheduler, thread, node);
0337 T_scheduler_record_event(&event);
0338 }
0339
0340 void
0341 T_scheduler_update_priority(const Scheduler_Control *scheduler,
0342 Thread_Control *thread, Scheduler_Node *node)
0343 {
0344 T_scheduler_event event = {
0345 .operation = T_SCHEDULER_UPDATE_PRIORITY,
0346 .thread = thread,
0347 .node = node
0348 };
0349 const Scheduler_Operations *operations;
0350
0351 operations = &T_scheduler_operations[_Scheduler_Get_index(scheduler)];
0352 T_scheduler_before_operation(&event);
0353 (*operations->update_priority)(scheduler, thread, node);
0354 T_scheduler_record_event(&event);
0355 }
0356
0357 Priority_Control T_scheduler_map_priority(const Scheduler_Control *scheduler,
0358 Priority_Control priority)
0359 {
0360 T_scheduler_event event = {
0361 .operation = T_SCHEDULER_MAP_PRIORITY
0362 };
0363 const Scheduler_Operations *operations;
0364
0365 operations = &T_scheduler_operations[_Scheduler_Get_index(scheduler)];
0366 event.map_unmap_priority.in = priority;
0367 T_scheduler_before_operation(&event);
0368 event.map_unmap_priority.out = (*operations->map_priority)(scheduler,
0369 priority);
0370 T_scheduler_record_event(&event);
0371 return event.map_unmap_priority.out;
0372 }
0373
0374 Priority_Control T_scheduler_unmap_priority(const Scheduler_Control *scheduler,
0375 Priority_Control priority)
0376 {
0377 T_scheduler_event event = {
0378 .operation = T_SCHEDULER_UNMAP_PRIORITY
0379 };
0380 const Scheduler_Operations *operations;
0381
0382 operations = &T_scheduler_operations[_Scheduler_Get_index(scheduler)];
0383 event.map_unmap_priority.in = priority;
0384 T_scheduler_before_operation(&event);
0385 event.map_unmap_priority.out = (*operations->unmap_priority)(scheduler,
0386 priority);
0387 T_scheduler_record_event(&event);
0388 return event.map_unmap_priority.out;
0389 }
0390
0391 void
0392 T_scheduler_node_initialize(const Scheduler_Control *scheduler,
0393 Scheduler_Node *node, Thread_Control *thread, Priority_Control priority)
0394 {
0395 T_scheduler_event event = {
0396 .operation = T_SCHEDULER_NODE_INITIALIZE,
0397 .thread = thread,
0398 .node = node
0399 };
0400 const Scheduler_Operations *operations;
0401
0402 operations = &T_scheduler_operations[_Scheduler_Get_index(scheduler)];
0403 T_scheduler_before_operation(&event);
0404 (*operations->node_initialize)(scheduler, node, thread, priority);
0405 T_scheduler_record_event(&event);
0406 }
0407
0408 void
0409 T_scheduler_node_destroy(const Scheduler_Control *scheduler,
0410 Scheduler_Node *node)
0411 {
0412 T_scheduler_event event = {
0413 .operation = T_SCHEDULER_NODE_DESTROY,
0414 .node = node
0415 };
0416 const Scheduler_Operations *operations;
0417
0418 operations = &T_scheduler_operations[_Scheduler_Get_index(scheduler)];
0419 T_scheduler_before_operation(&event);
0420 (*operations->node_destroy)(scheduler, node);
0421 T_scheduler_record_event(&event);
0422 }
0423
0424 void
0425 T_scheduler_release_job(const Scheduler_Control *scheduler,
0426 Thread_Control *thread, Priority_Node *priority, uint64_t deadline,
0427 Thread_queue_Context *queue_context)
0428 {
0429 T_scheduler_event event = {
0430 .operation = T_SCHEDULER_RELEASE_JOB,
0431 .thread = thread
0432 };
0433 const Scheduler_Operations *operations;
0434
0435 operations = &T_scheduler_operations[_Scheduler_Get_index(scheduler)];
0436 event.release_job.priority = priority;
0437 event.release_job.deadline = deadline;
0438 T_scheduler_before_operation(&event);
0439 (*operations->release_job)(scheduler, thread, priority, deadline, queue_context);
0440 T_scheduler_record_event(&event);
0441 }
0442
0443 void
0444 T_scheduler_cancel_job(const Scheduler_Control *scheduler,
0445 Thread_Control *thread, Priority_Node *priority,
0446 Thread_queue_Context *queue_context)
0447 {
0448 T_scheduler_event event = {
0449 .operation = T_SCHEDULER_CANCEL_JOB,
0450 .thread = thread
0451 };
0452 const Scheduler_Operations *operations;
0453
0454 operations = &T_scheduler_operations[_Scheduler_Get_index(scheduler)];
0455 event.cancel_job.priority = priority;
0456 T_scheduler_before_operation(&event);
0457 (*operations->cancel_job)(scheduler, thread, priority, queue_context);
0458 T_scheduler_record_event(&event);
0459 }
0460
0461 void
0462 T_scheduler_start_idle(const Scheduler_Control *scheduler,
0463 Thread_Control *thread, Per_CPU_Control *cpu)
0464 {
0465 T_scheduler_event event = {
0466 .operation = T_SCHEDULER_START_IDLE,
0467 .thread = thread
0468 };
0469 const Scheduler_Operations *operations;
0470
0471 operations = &T_scheduler_operations[_Scheduler_Get_index(scheduler)];
0472 T_scheduler_before_operation(&event);
0473 (*operations->start_idle)(scheduler, thread, cpu);
0474 T_scheduler_record_event(&event);
0475 }
0476
0477 #ifdef RTEMS_SMP
0478 bool
0479 T_scheduler_ask_for_help(const Scheduler_Control *scheduler,
0480 Thread_Control *thread, Scheduler_Node *node)
0481 {
0482 T_scheduler_event event = {
0483 .operation = T_SCHEDULER_ASK_FOR_HELP,
0484 .thread = thread,
0485 .node = node
0486 };
0487 const Scheduler_Operations *operations;
0488
0489 operations = &T_scheduler_operations[_Scheduler_Get_index(scheduler)];
0490 T_scheduler_before_operation(&event);
0491 event.ask_for_help.success = (*operations->ask_for_help)(scheduler,
0492 thread, node);
0493 T_scheduler_record_event(&event);
0494 return event.ask_for_help.success;
0495 }
0496
0497 void
0498 T_scheduler_reconsider_help_request(const Scheduler_Control *scheduler,
0499 Thread_Control *thread, Scheduler_Node *node)
0500 {
0501 T_scheduler_event event = {
0502 .operation = T_SCHEDULER_RECONSIDER_HELP_REQUEST,
0503 .thread = thread,
0504 .node = node
0505 };
0506 const Scheduler_Operations *operations;
0507
0508 operations = &T_scheduler_operations[_Scheduler_Get_index(scheduler)];
0509 T_scheduler_before_operation(&event);
0510 (*operations->reconsider_help_request)(scheduler, thread, node);
0511 T_scheduler_record_event(&event);
0512 }
0513
0514 void
0515 T_scheduler_withdraw_node(const Scheduler_Control *scheduler,
0516 Thread_Control *thread, Scheduler_Node *node,
0517 Thread_Scheduler_state next_state)
0518 {
0519 T_scheduler_event event = {
0520 .operation = T_SCHEDULER_WITHDRAW_NODE,
0521 .thread = thread,
0522 .node = node
0523 };
0524 const Scheduler_Operations *operations;
0525
0526 operations = &T_scheduler_operations[_Scheduler_Get_index(scheduler)];
0527 event.withdraw_node.next_state = next_state;
0528 T_scheduler_before_operation(&event);
0529 (*operations->withdraw_node)(scheduler, thread, node, next_state);
0530 T_scheduler_record_event(&event);
0531 }
0532
0533 void
0534 T_scheduler_make_sticky(const Scheduler_Control *scheduler, Thread_Control *thread,
0535 Scheduler_Node *node)
0536 {
0537 T_scheduler_event event = {
0538 .operation = T_SCHEDULER_MAKE_STICKY,
0539 .thread = thread,
0540 .node = node
0541 };
0542 const Scheduler_Operations *operations;
0543
0544 operations = &T_scheduler_operations[_Scheduler_Get_index(scheduler)];
0545 T_scheduler_before_operation(&event);
0546 (*operations->make_sticky)(scheduler, thread, node);
0547 T_scheduler_record_event(&event);
0548 }
0549
0550 void
0551 T_scheduler_clean_sticky(const Scheduler_Control *scheduler, Thread_Control *thread,
0552 Scheduler_Node *node)
0553 {
0554 T_scheduler_event event = {
0555 .operation = T_SCHEDULER_CLEAN_STICKY,
0556 .thread = thread,
0557 .node = node
0558 };
0559 const Scheduler_Operations *operations;
0560
0561 operations = &T_scheduler_operations[_Scheduler_Get_index(scheduler)];
0562 T_scheduler_before_operation(&event);
0563 (*operations->clean_sticky)(scheduler, thread, node);
0564 T_scheduler_record_event(&event);
0565 }
0566
0567 void
0568 T_scheduler_pin(const Scheduler_Control *scheduler, Thread_Control *thread,
0569 Scheduler_Node *node, Per_CPU_Control *cpu)
0570 {
0571 T_scheduler_event event = {
0572 .operation = T_SCHEDULER_PIN,
0573 .thread = thread,
0574 .node = node
0575 };
0576 const Scheduler_Operations *operations;
0577
0578 operations = &T_scheduler_operations[_Scheduler_Get_index(scheduler)];
0579 event.pin_unpin.cpu = cpu;
0580 T_scheduler_before_operation(&event);
0581 (*operations->pin)(scheduler, thread, node, cpu);
0582 T_scheduler_record_event(&event);
0583 }
0584
0585 void
0586 T_scheduler_unpin(const Scheduler_Control *scheduler, Thread_Control *thread,
0587 Scheduler_Node *node, Per_CPU_Control *cpu)
0588 {
0589 T_scheduler_event event = {
0590 .operation = T_SCHEDULER_UNPIN,
0591 .thread = thread,
0592 .node = node
0593 };
0594 const Scheduler_Operations *operations;
0595
0596 operations = &T_scheduler_operations[_Scheduler_Get_index(scheduler)];
0597 event.pin_unpin.cpu = cpu;
0598 T_scheduler_before_operation(&event);
0599 (*operations->unpin)(scheduler, thread, node, cpu);
0600 T_scheduler_record_event(&event);
0601 }
0602
0603 void
0604 T_scheduler_add_processor(const Scheduler_Control *scheduler,
0605 Thread_Control *idle)
0606 {
0607 T_scheduler_event event = {
0608 .operation = T_SCHEDULER_ADD_PROCESSOR,
0609 .thread = idle
0610 };
0611 const Scheduler_Operations *operations;
0612
0613 operations = &T_scheduler_operations[_Scheduler_Get_index(scheduler)];
0614 event.add_processor.idle = idle;
0615 T_scheduler_before_operation(&event);
0616 (*operations->add_processor)(scheduler, idle);
0617 T_scheduler_record_event(&event);
0618 }
0619
0620 Thread_Control *
0621 T_scheduler_remove_processor(const Scheduler_Control *scheduler,
0622 Per_CPU_Control *cpu)
0623 {
0624 T_scheduler_event event = {
0625 .operation = T_SCHEDULER_REMOVE_PROCESSOR
0626 };
0627 const Scheduler_Operations *operations;
0628
0629 operations = &T_scheduler_operations[_Scheduler_Get_index(scheduler)];
0630 event.remove_processor.cpu = cpu;
0631 T_scheduler_before_operation(&event);
0632 event.remove_processor.idle =
0633 (*operations->remove_processor)(scheduler, cpu);
0634 T_scheduler_record_event(&event);
0635 return event.remove_processor.idle;
0636 }
0637
0638 Status_Control
0639 T_scheduler_set_affinity(const Scheduler_Control *scheduler,
0640 Thread_Control *thread, Scheduler_Node *node,
0641 const Processor_mask *affinity)
0642 {
0643 T_scheduler_event event = {
0644 .operation = T_SCHEDULER_SET_AFFINITY,
0645 .thread = thread,
0646 .node = node
0647 };
0648 const Scheduler_Operations *operations;
0649
0650 operations = &T_scheduler_operations[_Scheduler_Get_index(scheduler)];
0651 event.set_affinity.affinity = *affinity;
0652 T_scheduler_before_operation(&event);
0653 event.set_affinity.status = (*operations->set_affinity)(scheduler,
0654 thread, node, affinity);
0655 T_scheduler_record_event(&event);
0656 return event.set_affinity.status;
0657 }
0658 #endif