File indexing completed on 2025-05-11 08:24:44
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 #ifdef HAVE_CONFIG_H
0030 #include "config.h"
0031 #endif
0032
0033 #include <tmacros.h>
0034
0035 #include <rtems.h>
0036
0037 const char rtems_test_name[] = "SMPSTRONGAPA 1";
0038
0039 #define CPU_COUNT 4
0040
0041 #define TASK_COUNT 5
0042
0043 #define P(i) (UINT32_C(2) + i)
0044
0045 #define ALL ((UINT32_C(1) << CPU_COUNT) - 1)
0046
0047 #define A(cpu0, cpu1, cpu2, cpu3) ( (cpu3 << 3) | (cpu2 << 2) | (cpu1 << 1)| cpu0 )
0048
0049 typedef enum {
0050 T0,
0051 T1,
0052 T2,
0053 T3,
0054 T4,
0055 IDLE
0056 } task_index;
0057
0058 typedef struct {
0059 enum {
0060 KIND_RESET,
0061 KIND_SET_PRIORITY,
0062 KIND_SET_AFFINITY,
0063 KIND_BLOCK,
0064 KIND_UNBLOCK
0065 } kind;
0066
0067 task_index index;
0068
0069 struct {
0070 rtems_task_priority priority;
0071 uint32_t cpu_set;
0072 } data;
0073
0074 uint8_t expected_cpu_allocations[CPU_COUNT];
0075 } test_action;
0076
0077 typedef struct {
0078 rtems_id timer_id;
0079 rtems_id master_id;
0080 rtems_id task_ids[TASK_COUNT];
0081 size_t action_index;
0082 } test_context;
0083
0084 #define RESET \
0085 { \
0086 KIND_RESET, \
0087 0, \
0088 { 0 }, \
0089 { IDLE, IDLE, IDLE, IDLE } \
0090 }
0091
0092 #define SET_PRIORITY(index, prio, cpu0, cpu1, cpu2, cpu3) \
0093 { \
0094 KIND_SET_PRIORITY, \
0095 index, \
0096 { .priority = prio }, \
0097 { cpu0, cpu1, cpu2, cpu3 } \
0098 }
0099
0100 #define SET_AFFINITY(index, aff, cpu0, cpu1, cpu2, cpu3) \
0101 { \
0102 KIND_SET_AFFINITY, \
0103 index, \
0104 { .cpu_set = aff }, \
0105 { cpu0, cpu1, cpu2, cpu3 } \
0106 }
0107
0108 #define BLOCK(index, cpu0, cpu1, cpu2, cpu3) \
0109 { \
0110 KIND_BLOCK, \
0111 index, \
0112 { 0 }, \
0113 { cpu0, cpu1, cpu2, cpu3 } \
0114 }
0115
0116 #define UNBLOCK(index, cpu0, cpu1, cpu2, cpu3) \
0117 { \
0118 KIND_UNBLOCK, \
0119 index, \
0120 { 0 }, \
0121 { cpu0, cpu1, cpu2, cpu3 } \
0122 }
0123
0124 static const test_action test_actions[] = {
0125 RESET,
0126 UNBLOCK( T0, T0, IDLE, IDLE, IDLE),
0127 UNBLOCK( T1, T0, T1, IDLE, IDLE),
0128 UNBLOCK( T2, T0, T1, T2, IDLE),
0129 UNBLOCK( T3, T0, T1, T2, T3),
0130 UNBLOCK( T4, T0, T1, T2, T3),
0131 SET_PRIORITY( T0, P(0), T0, T1, T2, T3),
0132 SET_PRIORITY( T1, P(1), T0, T1, T2, T3),
0133 SET_PRIORITY( T2, P(2), T0, T1, T2, T3),
0134 SET_PRIORITY( T4, P(4), T0, T1, T2, T3),
0135
0136
0137
0138 SET_PRIORITY( T3, P(8), T0, T1, T2, T4),
0139 SET_AFFINITY( T0, ALL, T0, T1, T2, T4),
0140 SET_AFFINITY( T1, A(0, 1, 0, 0), T0, T1, T2, T4),
0141 SET_AFFINITY( T2, A(0, 0, 1, 0), T0, T1, T2, T4),
0142 SET_AFFINITY( T4, A(0, 0, 0, 1), T0, T1, T2, T4),
0143
0144
0145
0146 SET_AFFINITY( T3, A(1, 0, 0, 0), T0, T1, T2, T4),
0147
0148
0149
0150
0151
0152
0153 SET_PRIORITY( T3, P(3), T3, T1, T2, T0),
0154 RESET
0155 };
0156
0157 static test_context test_instance;
0158
0159 static void set_priority(rtems_id id, rtems_task_priority prio)
0160 {
0161 rtems_status_code sc;
0162
0163 sc = rtems_task_set_priority(id, prio, &prio);
0164 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0165 }
0166
0167 static void set_affinity(rtems_id id, uint32_t cpu_set_32)
0168 {
0169 rtems_status_code sc;
0170 cpu_set_t cpu_set;
0171 size_t i;
0172
0173 CPU_ZERO(&cpu_set);
0174
0175 for (i = 0; i < CPU_COUNT; ++i) {
0176 if ((cpu_set_32 & (UINT32_C(1) << i)) != 0) {
0177 CPU_SET(i, &cpu_set);
0178 }
0179 }
0180
0181 sc = rtems_task_set_affinity(id, sizeof(cpu_set), &cpu_set);
0182 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0183 }
0184
0185 static void reset(test_context *ctx)
0186 {
0187 rtems_status_code sc;
0188 size_t i;
0189
0190 for (i = CPU_COUNT; i < TASK_COUNT; ++i) {
0191 set_priority(ctx->task_ids[i], P(i));
0192 set_affinity(ctx->task_ids[i], ALL);
0193
0194 sc = rtems_task_suspend(ctx->task_ids[i]);
0195 rtems_test_assert(sc == RTEMS_SUCCESSFUL || sc == RTEMS_ALREADY_SUSPENDED);
0196 }
0197
0198 for (i = 0; i < CPU_COUNT; ++i) {
0199 set_priority(ctx->task_ids[i], P(i));
0200
0201 sc = rtems_task_resume(ctx->task_ids[i]);
0202 rtems_test_assert(sc == RTEMS_SUCCESSFUL || sc == RTEMS_INCORRECT_STATE);
0203 }
0204
0205
0206 for (i = 0; i < CPU_COUNT; ++i) {
0207 const Per_CPU_Control *c;
0208 const Thread_Control *h;
0209
0210 c = _Per_CPU_Get_by_index(CPU_COUNT - 1 - i);
0211 h = c->heir;
0212
0213 sc = rtems_task_suspend(h->Object.id);
0214 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0215 }
0216 }
0217
0218 static void check_cpu_allocations(test_context *ctx, const test_action *action)
0219 {
0220 size_t i;
0221
0222 for (i = 0; i < CPU_COUNT; ++i) {
0223 task_index e;
0224 const Per_CPU_Control *c;
0225 const Thread_Control *h;
0226
0227 e = action->expected_cpu_allocations[i];
0228 c = _Per_CPU_Get_by_index(i);
0229 h = c->heir;
0230
0231 if (e != IDLE) {
0232 rtems_test_assert(h->Object.id == ctx->task_ids[e]);
0233 } else {
0234 rtems_test_assert(h->is_idle);
0235 }
0236 }
0237 }
0238
0239
0240
0241
0242
0243 static void timer(rtems_id id, void *arg)
0244 {
0245 test_context *ctx;
0246 rtems_status_code sc;
0247 size_t i;
0248
0249 ctx = arg;
0250 i = ctx->action_index;
0251
0252 if (i == 0) {
0253 sc = rtems_task_suspend(ctx->master_id);
0254 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0255 }
0256
0257 if (i < RTEMS_ARRAY_SIZE(test_actions)) {
0258 const test_action *action = &test_actions[i];
0259 rtems_id task;
0260
0261 ctx->action_index = i + 1;
0262
0263 task = ctx->task_ids[action->index];
0264
0265 switch (action->kind) {
0266 case KIND_SET_PRIORITY:
0267 set_priority(task, action->data.priority);
0268 break;
0269 case KIND_SET_AFFINITY:
0270 set_affinity(task, action->data.cpu_set);
0271 break;
0272 case KIND_BLOCK:
0273 sc = rtems_task_suspend(task);
0274 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0275 break;
0276 case KIND_UNBLOCK:
0277 sc = rtems_task_resume(task);
0278 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0279 break;
0280 default:
0281 rtems_test_assert(action->kind == KIND_RESET);
0282 reset(ctx);
0283 break;
0284 }
0285
0286 check_cpu_allocations(ctx, action);
0287
0288 sc = rtems_timer_reset(id);
0289 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0290 } else {
0291 sc = rtems_task_resume(ctx->master_id);
0292 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0293
0294 sc = rtems_event_transient_send(ctx->master_id);
0295 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0296 }
0297 }
0298
0299 static void do_nothing_task(rtems_task_argument arg)
0300 {
0301 (void) arg;
0302
0303 while (true) {
0304
0305 }
0306 }
0307
0308 static void test(void)
0309 {
0310 test_context *ctx;
0311 rtems_status_code sc;
0312 size_t i;
0313
0314 ctx = &test_instance;
0315
0316 ctx->master_id = rtems_task_self();
0317
0318 for (i = 0; i < TASK_COUNT; ++i) {
0319 sc = rtems_task_create(
0320 rtems_build_name(' ', ' ', 'T', '0' + i),
0321 P(i),
0322 RTEMS_MINIMUM_STACK_SIZE,
0323 RTEMS_DEFAULT_MODES,
0324 RTEMS_DEFAULT_ATTRIBUTES,
0325 &ctx->task_ids[i]
0326 );
0327 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0328
0329 sc = rtems_task_start(ctx->task_ids[i], do_nothing_task, 0);
0330 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0331 }
0332
0333 sc = rtems_timer_create(
0334 rtems_build_name('A', 'C', 'T', 'N'),
0335 &ctx->timer_id
0336 );
0337 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0338
0339 sc = rtems_timer_fire_after(ctx->timer_id, 1, timer, ctx);
0340 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0341
0342 sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
0343 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0344
0345 for (i = 0; i < TASK_COUNT; ++i) {
0346 sc = rtems_task_delete(ctx->task_ids[i]);
0347 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0348 }
0349
0350 sc = rtems_timer_delete(ctx->timer_id);
0351 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0352 }
0353
0354 static void Init(rtems_task_argument arg)
0355 {
0356 TEST_BEGIN();
0357
0358 if (rtems_scheduler_get_processor_maximum() == CPU_COUNT) {
0359 test();
0360 } else {
0361 puts("warning: wrong processor count to run the test");
0362 }
0363
0364 TEST_END();
0365 rtems_test_exit(0);
0366 }
0367
0368 #define CONFIGURE_MICROSECONDS_PER_TICK 1000
0369
0370 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
0371 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
0372
0373 #define CONFIGURE_MAXIMUM_TASKS (1 + TASK_COUNT)
0374 #define CONFIGURE_MAXIMUM_TIMERS 1
0375
0376 #define CONFIGURE_MAXIMUM_PROCESSORS CPU_COUNT
0377
0378 #define CONFIGURE_SCHEDULER_STRONG_APA
0379
0380 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
0381
0382 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
0383
0384 #define CONFIGURE_INIT
0385
0386 #include <rtems/confdefs.h>