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/objectimpl.h>
0035 #include <rtems/score/threadimpl.h>
0036
0037 #include "tmacros.h"
0038
0039 const char rtems_test_name[] = "SMPMIGRATION 2";
0040
0041 #define CPU_COUNT 32
0042
0043 #define TASK_COUNT (CPU_COUNT + 1)
0044
0045 #define PRIO_LOW 3
0046
0047 #define PRIO_HIGH 2
0048
0049 typedef struct {
0050 uint32_t value;
0051 uint32_t cache_line_separation[31];
0052 } test_counter;
0053
0054 typedef struct {
0055 test_counter counters[TASK_COUNT];
0056 rtems_id scheduler_ids[CPU_COUNT];
0057 rtems_id task_ids[TASK_COUNT];
0058 } test_context;
0059
0060 static test_context test_instance;
0061
0062 static rtems_task_priority migration_task_prio(uint32_t task_index)
0063 {
0064 return task_index > 0 ? PRIO_LOW : PRIO_HIGH;
0065 }
0066
0067 static void migration_task(rtems_task_argument arg)
0068 {
0069 test_context *ctx = &test_instance;
0070 uint32_t task_index = arg;
0071 rtems_task_priority prio = migration_task_prio(task_index);
0072 uint32_t cpu_count = rtems_scheduler_get_processor_maximum();
0073 uint32_t cpu_index = rtems_scheduler_get_processor();
0074
0075 while (true) {
0076 rtems_status_code sc;
0077
0078 cpu_index = (cpu_index + 1) % cpu_count;
0079
0080 sc = rtems_task_set_scheduler(
0081 RTEMS_SELF,
0082 ctx->scheduler_ids[cpu_index],
0083 prio
0084 );
0085 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0086
0087 ++ctx->counters[task_index].value;
0088
0089 rtems_test_assert(cpu_index == rtems_scheduler_get_processor());
0090 }
0091 }
0092
0093 static void test_migrations(test_context *ctx)
0094 {
0095 rtems_status_code sc;
0096 uint32_t cpu_count = rtems_scheduler_get_processor_maximum();
0097 uint32_t task_count = cpu_count + 1;
0098 uint32_t task_index;
0099
0100 for (task_index = 0; task_index < task_count; ++task_index) {
0101 rtems_id task_id;
0102
0103 sc = rtems_task_create(
0104 rtems_build_name('T', 'A', 'S', 'K'),
0105 255,
0106 RTEMS_MINIMUM_STACK_SIZE,
0107 RTEMS_DEFAULT_MODES,
0108 RTEMS_DEFAULT_ATTRIBUTES,
0109 &task_id
0110 );
0111 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0112
0113 sc = rtems_task_set_scheduler(
0114 task_id,
0115 ctx->scheduler_ids[task_index % cpu_count],
0116 migration_task_prio(task_index)
0117 );
0118 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0119
0120 sc = rtems_task_start(task_id, migration_task, task_index);
0121 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0122
0123 ctx->task_ids[task_index] = task_id;
0124 }
0125
0126 sc = rtems_task_wake_after(30 * rtems_clock_get_ticks_per_second());
0127 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0128
0129 for (task_index = 0; task_index < task_count; ++task_index) {
0130 printf(
0131 "task %" PRIu32 " counter: %" PRIu32 "\n",
0132 task_index,
0133 ctx->counters[task_index].value
0134 );
0135
0136 sc = rtems_task_delete(ctx->task_ids[task_index]);
0137 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0138 }
0139 }
0140
0141 static void busy_loop_task(rtems_task_argument arg)
0142 {
0143 while (true) {
0144
0145 }
0146 }
0147
0148 static Thread_Control *get_thread_by_id(rtems_id task_id)
0149 {
0150 ISR_lock_Context lock_context;
0151 Thread_Control *thread;
0152
0153 thread = _Thread_Get(task_id, &lock_context);
0154 rtems_test_assert(thread != NULL);
0155 _ISR_lock_ISR_enable(&lock_context);
0156
0157 return thread;
0158 }
0159
0160 static void test_double_migration(test_context *ctx)
0161 {
0162 uint32_t cpu_count = rtems_scheduler_get_processor_maximum();
0163
0164 if (cpu_count >= 2) {
0165 rtems_status_code sc;
0166 rtems_id task_id;
0167 rtems_id scheduler_id;
0168 uint32_t cpu_self_index = 0;
0169 uint32_t cpu_other_index = 1;
0170 Per_CPU_Control *cpu_self = _Per_CPU_Get_by_index(cpu_self_index);
0171 Per_CPU_Control *cpu_other = _Per_CPU_Get_by_index(cpu_other_index);
0172 Per_CPU_Control *cpu_self_dispatch_disabled;
0173 Thread_Control *self;
0174 Thread_Control *other;
0175
0176 sc = rtems_task_get_scheduler(RTEMS_SELF, &scheduler_id);
0177 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0178
0179 rtems_test_assert(scheduler_id == ctx->scheduler_ids[cpu_self_index]);
0180
0181 sc = rtems_task_create(
0182 rtems_build_name('T', 'A', 'S', 'K'),
0183 2,
0184 RTEMS_MINIMUM_STACK_SIZE,
0185 RTEMS_DEFAULT_MODES,
0186 RTEMS_DEFAULT_ATTRIBUTES,
0187 &task_id
0188 );
0189 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0190
0191 other = get_thread_by_id(task_id);
0192
0193 sc = rtems_task_set_scheduler(
0194 task_id,
0195 ctx->scheduler_ids[cpu_other_index],
0196 2
0197 );
0198 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0199
0200 sc = rtems_task_start(task_id, busy_loop_task, 0);
0201 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0202
0203 while (!_Thread_Is_executing_on_a_processor(other)) {
0204
0205 }
0206
0207 cpu_self_dispatch_disabled = _Thread_Dispatch_disable();
0208 rtems_test_assert(cpu_self == cpu_self_dispatch_disabled);
0209
0210 self = _Thread_Executing;
0211
0212 rtems_test_assert(cpu_self->executing == self);
0213 rtems_test_assert(cpu_self->heir == self);
0214 rtems_test_assert(!cpu_self->dispatch_necessary);
0215
0216 rtems_test_assert(cpu_other->executing == other);
0217 rtems_test_assert(cpu_other->heir == other);
0218 rtems_test_assert(!cpu_other->dispatch_necessary);
0219
0220 sc = rtems_task_set_scheduler(
0221 RTEMS_SELF,
0222 ctx->scheduler_ids[cpu_other_index],
0223 1
0224 );
0225 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0226
0227 rtems_test_assert(cpu_self->executing == self);
0228 rtems_test_assert(cpu_self->heir != self);
0229 rtems_test_assert(cpu_self->dispatch_necessary);
0230
0231 while (_Thread_Is_executing_on_a_processor(other)) {
0232
0233 }
0234
0235 rtems_test_assert(cpu_other->executing == self);
0236 rtems_test_assert(cpu_other->heir == self);
0237 rtems_test_assert(!cpu_other->dispatch_necessary);
0238
0239 sc = rtems_task_set_scheduler(
0240 RTEMS_SELF,
0241 ctx->scheduler_ids[cpu_self_index],
0242 1
0243 );
0244 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0245
0246 rtems_test_assert(cpu_self->executing == self);
0247 rtems_test_assert(cpu_self->heir == self);
0248 rtems_test_assert(cpu_self->dispatch_necessary);
0249
0250 rtems_test_assert(cpu_other->heir == other);
0251
0252 _Thread_Dispatch_enable(cpu_self_dispatch_disabled);
0253
0254 while (!_Thread_Is_executing_on_a_processor(other)) {
0255
0256 }
0257
0258 sc = rtems_task_delete(task_id);
0259 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0260 }
0261 }
0262
0263 static void init_scheduler_ids(test_context *ctx)
0264 {
0265 rtems_status_code sc;
0266 uint32_t cpu_count = rtems_scheduler_get_processor_maximum();
0267 uint32_t cpu_index;
0268
0269 for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) {
0270 sc = rtems_scheduler_ident(cpu_index, &ctx->scheduler_ids[cpu_index]);
0271 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0272 }
0273 }
0274
0275 static void Init(rtems_task_argument arg)
0276 {
0277 test_context *ctx = &test_instance;
0278 rtems_resource_snapshot snapshot;
0279
0280 TEST_BEGIN();
0281
0282 rtems_resource_snapshot_take(&snapshot);
0283
0284 init_scheduler_ids(ctx);
0285 test_double_migration(ctx);
0286 test_migrations(ctx);
0287
0288 rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
0289
0290 TEST_END();
0291 rtems_test_exit(0);
0292 }
0293
0294 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
0295 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
0296
0297 #define CONFIGURE_MAXIMUM_PROCESSORS CPU_COUNT
0298
0299 #define CONFIGURE_SCHEDULER_SIMPLE_SMP
0300
0301 #include <rtems/scheduler.h>
0302
0303 RTEMS_SCHEDULER_SIMPLE_SMP(0);
0304 RTEMS_SCHEDULER_SIMPLE_SMP(1);
0305 RTEMS_SCHEDULER_SIMPLE_SMP(2);
0306 RTEMS_SCHEDULER_SIMPLE_SMP(3);
0307 RTEMS_SCHEDULER_SIMPLE_SMP(4);
0308 RTEMS_SCHEDULER_SIMPLE_SMP(5);
0309 RTEMS_SCHEDULER_SIMPLE_SMP(6);
0310 RTEMS_SCHEDULER_SIMPLE_SMP(7);
0311 RTEMS_SCHEDULER_SIMPLE_SMP(8);
0312 RTEMS_SCHEDULER_SIMPLE_SMP(9);
0313 RTEMS_SCHEDULER_SIMPLE_SMP(10);
0314 RTEMS_SCHEDULER_SIMPLE_SMP(11);
0315 RTEMS_SCHEDULER_SIMPLE_SMP(12);
0316 RTEMS_SCHEDULER_SIMPLE_SMP(13);
0317 RTEMS_SCHEDULER_SIMPLE_SMP(14);
0318 RTEMS_SCHEDULER_SIMPLE_SMP(15);
0319 RTEMS_SCHEDULER_SIMPLE_SMP(16);
0320 RTEMS_SCHEDULER_SIMPLE_SMP(17);
0321 RTEMS_SCHEDULER_SIMPLE_SMP(18);
0322 RTEMS_SCHEDULER_SIMPLE_SMP(19);
0323 RTEMS_SCHEDULER_SIMPLE_SMP(20);
0324 RTEMS_SCHEDULER_SIMPLE_SMP(21);
0325 RTEMS_SCHEDULER_SIMPLE_SMP(22);
0326 RTEMS_SCHEDULER_SIMPLE_SMP(23);
0327 RTEMS_SCHEDULER_SIMPLE_SMP(24);
0328 RTEMS_SCHEDULER_SIMPLE_SMP(25);
0329 RTEMS_SCHEDULER_SIMPLE_SMP(26);
0330 RTEMS_SCHEDULER_SIMPLE_SMP(27);
0331 RTEMS_SCHEDULER_SIMPLE_SMP(28);
0332 RTEMS_SCHEDULER_SIMPLE_SMP(29);
0333 RTEMS_SCHEDULER_SIMPLE_SMP(30);
0334 RTEMS_SCHEDULER_SIMPLE_SMP(31);
0335
0336 #define CONFIGURE_SCHEDULER_TABLE_ENTRIES \
0337 RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(0, 0), \
0338 RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(1, 1), \
0339 RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(2, 2), \
0340 RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(3, 3), \
0341 RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(4, 4), \
0342 RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(5, 5), \
0343 RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(6, 6), \
0344 RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(7, 7), \
0345 RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(8, 8), \
0346 RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(9, 9), \
0347 RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(10, 10), \
0348 RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(11, 11), \
0349 RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(12, 12), \
0350 RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(13, 13), \
0351 RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(14, 14), \
0352 RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(15, 15), \
0353 RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(16, 16), \
0354 RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(17, 17), \
0355 RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(18, 18), \
0356 RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(19, 19), \
0357 RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(20, 20), \
0358 RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(21, 21), \
0359 RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(22, 22), \
0360 RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(23, 23), \
0361 RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(24, 24), \
0362 RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(25, 25), \
0363 RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(26, 26), \
0364 RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(27, 27), \
0365 RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(28, 28), \
0366 RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(29, 29), \
0367 RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(30, 30), \
0368 RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(31, 31)
0369
0370 #define CONFIGURE_SCHEDULER_ASSIGNMENTS \
0371 RTEMS_SCHEDULER_ASSIGN(0, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
0372 RTEMS_SCHEDULER_ASSIGN(1, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
0373 RTEMS_SCHEDULER_ASSIGN(2, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
0374 RTEMS_SCHEDULER_ASSIGN(3, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
0375 RTEMS_SCHEDULER_ASSIGN(4, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
0376 RTEMS_SCHEDULER_ASSIGN(5, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
0377 RTEMS_SCHEDULER_ASSIGN(6, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
0378 RTEMS_SCHEDULER_ASSIGN(7, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
0379 RTEMS_SCHEDULER_ASSIGN(8, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
0380 RTEMS_SCHEDULER_ASSIGN(9, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
0381 RTEMS_SCHEDULER_ASSIGN(10, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
0382 RTEMS_SCHEDULER_ASSIGN(11, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
0383 RTEMS_SCHEDULER_ASSIGN(12, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
0384 RTEMS_SCHEDULER_ASSIGN(13, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
0385 RTEMS_SCHEDULER_ASSIGN(14, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
0386 RTEMS_SCHEDULER_ASSIGN(15, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
0387 RTEMS_SCHEDULER_ASSIGN(16, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
0388 RTEMS_SCHEDULER_ASSIGN(17, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
0389 RTEMS_SCHEDULER_ASSIGN(18, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
0390 RTEMS_SCHEDULER_ASSIGN(19, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
0391 RTEMS_SCHEDULER_ASSIGN(20, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
0392 RTEMS_SCHEDULER_ASSIGN(21, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
0393 RTEMS_SCHEDULER_ASSIGN(22, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
0394 RTEMS_SCHEDULER_ASSIGN(23, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
0395 RTEMS_SCHEDULER_ASSIGN(24, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
0396 RTEMS_SCHEDULER_ASSIGN(25, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
0397 RTEMS_SCHEDULER_ASSIGN(26, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
0398 RTEMS_SCHEDULER_ASSIGN(27, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
0399 RTEMS_SCHEDULER_ASSIGN(28, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
0400 RTEMS_SCHEDULER_ASSIGN(29, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
0401 RTEMS_SCHEDULER_ASSIGN(30, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
0402 RTEMS_SCHEDULER_ASSIGN(31, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL)
0403
0404 #define CONFIGURE_MAXIMUM_TASKS (1 + TASK_COUNT)
0405
0406 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
0407
0408 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
0409
0410 #define CONFIGURE_INIT
0411
0412 #include <rtems/confdefs.h>