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 #ifdef HAVE_CONFIG_H
0029 #include "config.h"
0030 #endif
0031
0032 #include "tmacros.h"
0033
0034 #include <rtems.h>
0035 #include <rtems/counter.h>
0036 #include <rtems/libcsupport.h>
0037 #include <rtems/score/profiling.h>
0038 #include <rtems/score/smpbarrier.h>
0039 #include <rtems/score/threadimpl.h>
0040
0041 const char rtems_test_name[] = "SMPTHREADLIFE 1";
0042
0043 #define CPU_COUNT 2
0044
0045 typedef struct {
0046 volatile rtems_task_argument main_arg;
0047 volatile rtems_task_argument worker_arg;
0048 volatile bool terminated;
0049 SMP_barrier_Control barrier;
0050 SMP_barrier_State main_barrier_state;
0051 SMP_barrier_State worker_barrier_state;
0052 Thread_Control *delay_switch_for_executing;
0053 rtems_id worker_id;
0054 } test_context;
0055
0056 static test_context test_instance = {
0057 .barrier = SMP_BARRIER_CONTROL_INITIALIZER,
0058 .main_barrier_state = SMP_BARRIER_STATE_INITIALIZER,
0059 .worker_barrier_state = SMP_BARRIER_STATE_INITIALIZER
0060 };
0061
0062 static void barrier(test_context *ctx, SMP_barrier_State *state)
0063 {
0064 _SMP_barrier_Wait(&ctx->barrier, state, CPU_COUNT);
0065 }
0066
0067 static void restart_extension(
0068 Thread_Control *executing,
0069 Thread_Control *restarted
0070 )
0071 {
0072 rtems_test_assert(executing == restarted);
0073 }
0074
0075 static void delete_extension(
0076 Thread_Control *executing,
0077 Thread_Control *deleted
0078 )
0079 {
0080 rtems_test_assert(executing != deleted);
0081 }
0082
0083 static void terminate_extension(Thread_Control *executing)
0084 {
0085 test_context *ctx = &test_instance;
0086
0087 ctx->terminated = true;
0088 }
0089
0090 static void switch_extension(Thread_Control *executing, Thread_Control *heir)
0091 {
0092 test_context *ctx = &test_instance;
0093
0094 if (ctx->delay_switch_for_executing == executing) {
0095 ctx->delay_switch_for_executing = NULL;
0096
0097
0098 barrier(ctx, &ctx->worker_barrier_state);
0099
0100 rtems_counter_delay_nanoseconds(100000000);
0101
0102
0103 _Profiling_Thread_dispatch_disable( _Per_CPU_Get(), 0 );
0104 }
0105 }
0106
0107 static void worker_task(rtems_task_argument arg)
0108 {
0109 test_context *ctx = &test_instance;
0110
0111 rtems_test_assert(arg == ctx->main_arg);
0112
0113 ctx->worker_arg = arg;
0114
0115
0116 barrier(ctx, &ctx->worker_barrier_state);
0117
0118 while (true) {
0119
0120 }
0121 }
0122
0123 static void test_restart(void)
0124 {
0125 test_context *ctx = &test_instance;
0126 rtems_status_code sc;
0127 rtems_id id;
0128 rtems_task_argument arg;
0129 rtems_resource_snapshot snapshot;
0130
0131 rtems_resource_snapshot_take(&snapshot);
0132
0133 sc = rtems_task_create(
0134 rtems_build_name('W', 'O', 'R', 'K'),
0135 1,
0136 RTEMS_MINIMUM_STACK_SIZE,
0137 RTEMS_DEFAULT_MODES,
0138 RTEMS_DEFAULT_ATTRIBUTES,
0139 &id
0140 );
0141 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0142
0143 sc = rtems_task_start(id, worker_task, 0);
0144 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0145
0146
0147 barrier(ctx, &ctx->main_barrier_state);
0148
0149 for (arg = 1; arg < 23; ++arg) {
0150 ctx->main_arg = arg;
0151 ctx->worker_arg = 0;
0152
0153 sc = rtems_task_restart(id, arg);
0154 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0155
0156
0157 barrier(ctx, &ctx->main_barrier_state);
0158
0159 rtems_test_assert(ctx->worker_arg == arg);
0160 }
0161
0162 sc = rtems_task_delete(id);
0163 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0164
0165 rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
0166 }
0167
0168 static void test_delete(void)
0169 {
0170 test_context *ctx = &test_instance;
0171 rtems_status_code sc;
0172 rtems_id id;
0173 rtems_task_argument arg;
0174 rtems_resource_snapshot snapshot;
0175
0176 rtems_resource_snapshot_take(&snapshot);
0177
0178 for (arg = 31; arg < 57; ++arg) {
0179 ctx->main_arg = arg;
0180 ctx->worker_arg = 0;
0181 ctx->terminated = false;
0182
0183 sc = rtems_task_create(
0184 rtems_build_name('W', 'O', 'R', 'K'),
0185 1,
0186 RTEMS_MINIMUM_STACK_SIZE,
0187 RTEMS_DEFAULT_MODES,
0188 RTEMS_DEFAULT_ATTRIBUTES,
0189 &id
0190 );
0191 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0192
0193 sc = rtems_task_start(id, worker_task, arg);
0194 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0195
0196
0197 barrier(ctx, &ctx->main_barrier_state);
0198
0199 rtems_test_assert(ctx->worker_arg == arg);
0200 rtems_test_assert(!ctx->terminated);
0201
0202 sc = rtems_task_delete(id);
0203 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0204
0205 rtems_test_assert(ctx->terminated);
0206
0207 rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
0208 }
0209 }
0210
0211 static void delay_ipi_task(rtems_task_argument variant)
0212 {
0213 test_context *ctx = &test_instance;
0214 ISR_Level level;
0215
0216 _ISR_Local_disable(level);
0217
0218
0219 barrier(ctx, &ctx->worker_barrier_state);
0220
0221
0222
0223
0224
0225 rtems_counter_delay_nanoseconds(100000000);
0226
0227 if (variant != 0) {
0228 _Thread_Dispatch_disable();
0229 }
0230
0231 _ISR_Local_enable(level);
0232
0233
0234
0235
0236
0237 _Thread_Set_life_protection( THREAD_LIFE_PROTECTED );
0238
0239 if (variant != 0) {
0240 _Thread_Dispatch_enable( _Per_CPU_Get() );
0241 }
0242
0243 rtems_test_assert(0);
0244 }
0245
0246 static void test_set_life_protection(rtems_task_argument variant)
0247 {
0248 test_context *ctx = &test_instance;
0249 rtems_status_code sc;
0250 rtems_id id;
0251 rtems_resource_snapshot snapshot;
0252
0253 rtems_resource_snapshot_take(&snapshot);
0254
0255 sc = rtems_task_create(
0256 rtems_build_name('D', 'E', 'L', 'Y'),
0257 1,
0258 RTEMS_MINIMUM_STACK_SIZE,
0259 RTEMS_DEFAULT_MODES,
0260 RTEMS_DEFAULT_ATTRIBUTES,
0261 &id
0262 );
0263 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0264
0265 sc = rtems_task_start(id, delay_ipi_task, variant);
0266 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0267
0268
0269 barrier(ctx, &ctx->main_barrier_state);
0270
0271 sc = rtems_task_delete(id);
0272 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0273
0274 rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
0275 }
0276
0277 static void delay_switch_task(rtems_task_argument arg)
0278 {
0279 test_context *ctx = &test_instance;
0280
0281 ctx->delay_switch_for_executing = _Thread_Get_executing();
0282
0283
0284 barrier(ctx, &ctx->worker_barrier_state);
0285
0286 rtems_task_exit();
0287 }
0288
0289 static void test_wait_for_execution_stop(void)
0290 {
0291 test_context *ctx = &test_instance;
0292 rtems_status_code sc;
0293 rtems_id id;
0294 rtems_resource_snapshot snapshot;
0295
0296 rtems_resource_snapshot_take(&snapshot);
0297
0298 sc = rtems_task_create(
0299 rtems_build_name('S', 'W', 'I', 'T'),
0300 1,
0301 RTEMS_MINIMUM_STACK_SIZE,
0302 RTEMS_DEFAULT_MODES,
0303 RTEMS_DEFAULT_ATTRIBUTES,
0304 &id
0305 );
0306 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0307
0308 sc = rtems_task_start(id, delay_switch_task, 0);
0309 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0310
0311
0312 barrier(ctx, &ctx->main_barrier_state);
0313
0314
0315 barrier(ctx, &ctx->main_barrier_state);
0316
0317 sc = rtems_task_create(
0318 rtems_build_name('W', 'A', 'I', 'T'),
0319 1,
0320 RTEMS_MINIMUM_STACK_SIZE,
0321 RTEMS_DEFAULT_MODES,
0322 RTEMS_DEFAULT_ATTRIBUTES,
0323 &id
0324 );
0325 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0326
0327 sc = rtems_task_delete(id);
0328 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0329
0330 rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
0331 }
0332
0333 typedef enum {
0334 TEST_OP_SUSPEND,
0335 TEST_OP_EVENT,
0336 TEST_OP_EVENT_SYSTEM
0337 } test_op;
0338
0339 static void op_begin_suspend(void)
0340 {
0341 rtems_status_code sc;
0342
0343 sc = rtems_task_suspend(RTEMS_SELF);
0344 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0345 }
0346
0347 static void op_begin_event(void)
0348 {
0349 rtems_status_code sc;
0350 rtems_event_set events;
0351
0352 events = 0;
0353 sc = rtems_event_receive(
0354 RTEMS_EVENT_0,
0355 RTEMS_EVENT_ALL | RTEMS_WAIT,
0356 RTEMS_NO_TIMEOUT,
0357 &events
0358 );
0359 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0360 rtems_test_assert(events == RTEMS_EVENT_0);
0361 }
0362
0363 static void op_begin_event_system(void)
0364 {
0365 rtems_status_code sc;
0366 rtems_event_set events;
0367
0368 events = 0;
0369 sc = rtems_event_system_receive(
0370 RTEMS_EVENT_0,
0371 RTEMS_EVENT_ALL | RTEMS_WAIT,
0372 RTEMS_NO_TIMEOUT,
0373 &events
0374 );
0375 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0376 rtems_test_assert(events == RTEMS_EVENT_0);
0377 }
0378
0379 static void (*const test_ops_begin[])(void) = {
0380 op_begin_suspend,
0381 op_begin_event,
0382 op_begin_event_system
0383 };
0384
0385 static void op_end_suspend(test_context *ctx)
0386 {
0387 rtems_status_code sc;
0388
0389 sc = rtems_task_resume(ctx->worker_id);
0390 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0391 }
0392
0393 static void op_end_event(test_context *ctx)
0394 {
0395 rtems_status_code sc;
0396
0397 sc = rtems_event_send(ctx->worker_id, RTEMS_EVENT_0);
0398 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0399 }
0400
0401 static void op_end_event_system(test_context *ctx)
0402 {
0403 rtems_status_code sc;
0404
0405 sc = rtems_event_system_send(ctx->worker_id, RTEMS_EVENT_0);
0406 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0407 }
0408
0409 static void (*const test_ops_end[])(test_context *) = {
0410 op_end_suspend,
0411 op_end_event,
0412 op_end_event_system
0413 };
0414
0415 static void op_worker_task(rtems_task_argument arg)
0416 {
0417 test_context *ctx = &test_instance;
0418 test_op op = arg;
0419 Thread_Life_state previous_life_state;
0420
0421 previous_life_state = _Thread_Set_life_protection(THREAD_LIFE_PROTECTED);
0422
0423
0424 barrier(ctx, &ctx->worker_barrier_state);
0425
0426
0427 barrier(ctx, &ctx->worker_barrier_state);
0428
0429 (*test_ops_begin[op])();
0430
0431 _Thread_Set_life_protection(previous_life_state);
0432 rtems_test_assert(0);
0433 }
0434
0435 static void help_task(rtems_task_argument arg)
0436 {
0437 test_context *ctx = &test_instance;
0438 test_op op = arg;
0439
0440
0441 barrier(ctx, &ctx->main_barrier_state);
0442
0443 rtems_counter_delay_nanoseconds(100000000);
0444
0445 (*test_ops_end[op])(ctx);
0446
0447 rtems_task_suspend(RTEMS_SELF);
0448 rtems_test_assert(0);
0449 }
0450
0451 static void test_operation_with_delete_in_progress(test_op op)
0452 {
0453 test_context *ctx = &test_instance;
0454 rtems_status_code sc;
0455 rtems_id help_id;
0456 rtems_resource_snapshot snapshot;
0457
0458 rtems_resource_snapshot_take(&snapshot);
0459
0460 sc = rtems_task_create(
0461 rtems_build_name('W', 'O', 'R', 'K'),
0462 1,
0463 RTEMS_MINIMUM_STACK_SIZE,
0464 RTEMS_DEFAULT_MODES,
0465 RTEMS_DEFAULT_ATTRIBUTES,
0466 &ctx->worker_id
0467 );
0468 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0469
0470 sc = rtems_task_start(ctx->worker_id, op_worker_task, op);
0471 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0472
0473
0474 barrier(ctx, &ctx->main_barrier_state);
0475
0476 sc = rtems_task_create(
0477 rtems_build_name('H', 'E', 'L', 'P'),
0478 2,
0479 RTEMS_MINIMUM_STACK_SIZE,
0480 RTEMS_DEFAULT_MODES,
0481 RTEMS_DEFAULT_ATTRIBUTES,
0482 &help_id
0483 );
0484 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0485
0486 sc = rtems_task_start(help_id, help_task, op);
0487 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0488
0489 sc = rtems_task_delete(ctx->worker_id);
0490 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0491
0492 sc = rtems_task_delete(help_id);
0493 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0494
0495 rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
0496 }
0497
0498 static void Init(rtems_task_argument arg)
0499 {
0500 TEST_BEGIN();
0501
0502 if (rtems_scheduler_get_processor_maximum() >= CPU_COUNT) {
0503 test_restart();
0504 test_delete();
0505 test_set_life_protection(0);
0506 test_set_life_protection(1);
0507 test_wait_for_execution_stop();
0508 test_operation_with_delete_in_progress(TEST_OP_SUSPEND);
0509 test_operation_with_delete_in_progress(TEST_OP_EVENT);
0510 test_operation_with_delete_in_progress(TEST_OP_EVENT_SYSTEM);
0511 }
0512
0513 TEST_END();
0514 rtems_test_exit(0);
0515 }
0516
0517 #define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER
0518 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
0519
0520 #define CONFIGURE_MAXIMUM_PROCESSORS CPU_COUNT
0521
0522 #define CONFIGURE_MAXIMUM_TASKS (CPU_COUNT + 1)
0523
0524 #define CONFIGURE_INITIAL_EXTENSIONS \
0525 { \
0526 .thread_restart = restart_extension, \
0527 .thread_delete = delete_extension, \
0528 .thread_terminate = terminate_extension, \
0529 .thread_switch = switch_extension \
0530 }, \
0531 RTEMS_TEST_INITIAL_EXTENSION
0532
0533 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
0534
0535 #define CONFIGURE_INIT
0536
0537 #include <rtems/confdefs.h>