File indexing completed on 2025-05-11 08:24:49
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
0035 #include <rtems/score/threadimpl.h>
0036
0037 #include "tmacros.h"
0038
0039 #define PRIO_INIT 1
0040 #define PRIO_HIGH 2
0041 #define PRIO_MID 3
0042 #define PRIO_LOW 4
0043 #define PRIO_VERY_LOW 5
0044
0045 const char rtems_test_name[] = "SPTHREADLIFE 1";
0046
0047 typedef enum {
0048 INIT,
0049 SET_PRIO,
0050 SET_PRIO_DONE,
0051 DO_OBTAIN_0,
0052 OBTAIN_DONE_0,
0053 DO_RELEASE_0,
0054 RELEASE_DONE_0,
0055 DO_OBTAIN_1,
0056 OBTAIN_DONE_1,
0057 RESTART_0,
0058 RESTART_1,
0059 RESTART_2,
0060 RESTART_3,
0061 DO_RELEASE_1,
0062 RELEASE_DONE_1,
0063 DELETE_0,
0064 DELETE_1,
0065 DELETE_2,
0066 DELETE_3,
0067 SET_PROTECTION,
0068 SET_PROTECTION_DONE,
0069 CLEAR_PROTECTION,
0070 DELETE_4,
0071 DELETE_5,
0072 DELETE_6,
0073 DELETE_SELF,
0074 DELETE_7,
0075 DELETE_8,
0076 DELETE_9,
0077 EXIT_0,
0078 EXIT_1,
0079 EXIT_2,
0080 EXIT_3,
0081 INVALID
0082 } test_state;
0083
0084 typedef struct {
0085 rtems_id main_task_id;
0086 rtems_id worker_task_id;
0087 rtems_id sema_id;
0088 test_state current;
0089 test_state next;
0090 } test_context;
0091
0092 static test_context test_instance;
0093
0094 static void wake_up_main(const test_context *ctx)
0095 {
0096 rtems_status_code sc;
0097
0098 sc = rtems_event_transient_send(ctx->main_task_id);
0099 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0100 }
0101
0102 static void wait(void)
0103 {
0104 rtems_status_code sc;
0105
0106 sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
0107 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0108 }
0109
0110 static void change_state(
0111 test_context *ctx,
0112 test_state expected,
0113 test_state current,
0114 test_state next
0115 )
0116 {
0117 rtems_test_assert(ctx->current == expected);
0118 ctx->current = current;
0119 ctx->next = next;
0120 }
0121
0122 static void change_state_and_wait(
0123 test_context *ctx,
0124 test_state expected,
0125 test_state current,
0126 test_state next
0127 )
0128 {
0129 change_state(ctx, expected, current, next);
0130 wait();
0131 }
0132
0133 static void set_priority(rtems_task_priority prio)
0134 {
0135 rtems_status_code sc;
0136
0137 sc = rtems_task_set_priority(RTEMS_SELF, prio, &prio);
0138 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0139 }
0140
0141 static void assert_priority(rtems_task_priority expected)
0142 {
0143 rtems_status_code sc;
0144 rtems_task_priority prio;
0145
0146 sc = rtems_task_set_priority(RTEMS_SELF, RTEMS_CURRENT_PRIORITY, &prio);
0147 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0148
0149 rtems_test_assert(prio == expected);
0150 }
0151
0152 static void restart_extension(
0153 Thread_Control *executing,
0154 Thread_Control *restarted
0155 )
0156 {
0157 test_context *ctx = &test_instance;
0158 rtems_status_code sc;
0159
0160 rtems_test_assert(executing == restarted);
0161
0162 switch (ctx->current) {
0163 case RESTART_0:
0164 rtems_test_assert(ctx->worker_task_id == rtems_task_self());
0165 ctx->current = RESTART_1;
0166 sc = rtems_task_restart(RTEMS_SELF, 0);
0167 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0168 break;
0169 case RESTART_1:
0170 rtems_test_assert(ctx->worker_task_id == rtems_task_self());
0171 ctx->current = RESTART_2;
0172 break;
0173 default:
0174 rtems_test_assert(0);
0175 break;
0176 }
0177 }
0178
0179 static void delete_extension(
0180 Thread_Control *executing,
0181 Thread_Control *deleted
0182 )
0183 {
0184 test_context *ctx = &test_instance;
0185
0186 rtems_test_assert(executing != deleted);
0187 rtems_test_assert(ctx->main_task_id == rtems_task_self());
0188
0189 switch (ctx->current) {
0190 case DELETE_2:
0191 assert_priority(PRIO_INIT);
0192 ctx->current = DELETE_3;
0193 break;
0194 case DELETE_5:
0195 assert_priority(PRIO_INIT);
0196 ctx->current = DELETE_6;
0197 break;
0198 case DELETE_8:
0199 assert_priority(PRIO_VERY_LOW);
0200 ctx->current = DELETE_9;
0201 break;
0202 case EXIT_2:
0203 assert_priority(PRIO_VERY_LOW);
0204 ctx->current = EXIT_3;
0205 break;
0206 default:
0207 rtems_test_assert(0);
0208 break;
0209 }
0210 }
0211
0212 static void terminate_extension(Thread_Control *executing)
0213 {
0214 test_context *ctx = &test_instance;
0215
0216 rtems_test_assert(ctx->worker_task_id == rtems_task_self());
0217
0218 switch (ctx->current) {
0219 case DELETE_0:
0220 assert_priority(PRIO_INIT);
0221 ctx->current = DELETE_1;
0222 rtems_task_delete(RTEMS_SELF);
0223 rtems_test_assert(0);
0224 break;
0225 case DELETE_1:
0226 assert_priority(PRIO_INIT);
0227 ctx->current = DELETE_2;
0228 break;
0229 case DELETE_4:
0230 assert_priority(PRIO_INIT);
0231 ctx->current = DELETE_5;
0232 break;
0233 case DELETE_7:
0234 assert_priority(PRIO_LOW);
0235 ctx->current = DELETE_8;
0236 break;
0237 case EXIT_1:
0238 assert_priority(PRIO_LOW);
0239 ctx->current = EXIT_2;
0240 break;
0241 default:
0242 rtems_test_assert(0);
0243 break;
0244 }
0245 }
0246
0247 static void worker_task(rtems_task_argument arg)
0248 {
0249 test_context *ctx = &test_instance;
0250
0251 while (true) {
0252 test_state state = ctx->current;
0253 rtems_status_code sc;
0254 Thread_Life_state previous_thread_life_state;
0255 Per_CPU_Control *cpu_self;
0256
0257 switch (state) {
0258 case SET_PRIO:
0259 assert_priority(PRIO_LOW);
0260 set_priority(PRIO_MID);
0261 break;
0262 case DO_OBTAIN_0:
0263 case DO_OBTAIN_1:
0264 assert_priority(PRIO_MID);
0265 sc = rtems_semaphore_obtain(
0266 ctx->sema_id,
0267 RTEMS_WAIT,
0268 RTEMS_NO_TIMEOUT
0269 );
0270 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0271 assert_priority(PRIO_HIGH);
0272 break;
0273 case DO_RELEASE_0:
0274 case DO_RELEASE_1:
0275 assert_priority(PRIO_HIGH);
0276 sc = rtems_semaphore_release(ctx->sema_id);
0277 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0278
0279 switch (state) {
0280 case DO_RELEASE_0:
0281 assert_priority(PRIO_MID);
0282 break;
0283 case DO_RELEASE_1:
0284 assert_priority(PRIO_LOW);
0285 break;
0286 default:
0287 rtems_test_assert(0);
0288 break;
0289 }
0290
0291 break;
0292 case RESTART_2:
0293 assert_priority(PRIO_HIGH);
0294 break;
0295 case SET_PROTECTION:
0296 cpu_self = _Thread_Dispatch_disable();
0297 previous_thread_life_state =
0298 _Thread_Set_life_protection(THREAD_LIFE_PROTECTED);
0299 rtems_test_assert(
0300 (previous_thread_life_state & THREAD_LIFE_PROTECTED) == 0
0301 );
0302 _Thread_Dispatch_enable(cpu_self);
0303 break;
0304 case CLEAR_PROTECTION:
0305 cpu_self = _Thread_Dispatch_disable();
0306 previous_thread_life_state = _Thread_Set_life_protection(0);
0307 rtems_test_assert(
0308 (previous_thread_life_state & THREAD_LIFE_PROTECTED) != 0
0309 );
0310 ctx->current = DELETE_4;
0311 _Thread_Dispatch_enable(cpu_self);
0312 break;
0313 case DELETE_SELF:
0314 ctx->current = DELETE_7;
0315 rtems_task_delete(RTEMS_SELF);
0316 rtems_test_assert(0);
0317 break;
0318 case EXIT_0:
0319 ctx->current = EXIT_1;
0320 rtems_task_exit();
0321 rtems_test_assert(0);
0322 break;
0323 default:
0324 rtems_test_assert(0);
0325 break;
0326 }
0327
0328 ctx->current = ctx->next;
0329 wake_up_main(ctx);
0330 }
0331 }
0332
0333 static void create_sema(test_context *ctx)
0334 {
0335 rtems_status_code sc;
0336
0337 sc = rtems_semaphore_create(
0338 rtems_build_name('S', 'E', 'M', 'A'),
0339 1,
0340 RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_PRIORITY_CEILING,
0341 PRIO_HIGH,
0342 &ctx->sema_id
0343 );
0344 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0345 }
0346
0347 static void create_and_start_worker(test_context *ctx)
0348 {
0349 rtems_status_code sc;
0350
0351 sc = rtems_task_create(
0352 rtems_build_name('W', 'O', 'R', 'K'),
0353 PRIO_LOW,
0354 RTEMS_MINIMUM_STACK_SIZE,
0355 RTEMS_DEFAULT_MODES,
0356 RTEMS_DEFAULT_ATTRIBUTES,
0357 &ctx->worker_task_id
0358 );
0359 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0360
0361 sc = rtems_task_start(ctx->worker_task_id, worker_task, 0);
0362 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0363 }
0364
0365 static void test(void)
0366 {
0367 test_context *ctx = &test_instance;
0368 rtems_status_code sc;
0369 rtems_resource_snapshot snapshot;
0370
0371 ctx->main_task_id = rtems_task_self();
0372
0373 rtems_resource_snapshot_take(&snapshot);
0374
0375 create_sema(ctx);
0376 create_and_start_worker(ctx);
0377
0378 change_state_and_wait(ctx, INIT, SET_PRIO, SET_PRIO_DONE);
0379 change_state_and_wait(ctx, SET_PRIO_DONE, DO_OBTAIN_0, OBTAIN_DONE_0);
0380
0381 sc = rtems_semaphore_delete(ctx->sema_id);
0382 rtems_test_assert(sc == RTEMS_RESOURCE_IN_USE);
0383
0384 change_state_and_wait(ctx, OBTAIN_DONE_0, DO_RELEASE_0, RELEASE_DONE_0);
0385
0386 sc = rtems_semaphore_delete(ctx->sema_id);
0387 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0388
0389 create_sema(ctx);
0390
0391 change_state_and_wait(ctx, RELEASE_DONE_0, DO_OBTAIN_1, OBTAIN_DONE_1);
0392
0393 sc = rtems_semaphore_delete(ctx->sema_id);
0394 rtems_test_assert(sc == RTEMS_RESOURCE_IN_USE);
0395
0396 sc = rtems_task_restart(ctx->worker_task_id, 0);
0397 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0398
0399 change_state_and_wait(ctx, OBTAIN_DONE_1, RESTART_0, RESTART_3);
0400 change_state_and_wait(ctx, RESTART_3, DO_RELEASE_1, RELEASE_DONE_1);
0401
0402 sc = rtems_semaphore_delete(ctx->sema_id);
0403 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0404
0405 change_state(ctx, RELEASE_DONE_1, DELETE_0, INVALID);
0406
0407 sc = rtems_task_delete(ctx->worker_task_id);
0408 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0409
0410 rtems_test_assert(ctx->current == DELETE_2);
0411
0412 rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
0413
0414 create_and_start_worker(ctx);
0415
0416 change_state_and_wait(ctx, DELETE_3, SET_PROTECTION, SET_PROTECTION_DONE);
0417 change_state(ctx, SET_PROTECTION_DONE, CLEAR_PROTECTION, INVALID);
0418
0419 sc = rtems_task_delete(ctx->worker_task_id);
0420 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0421
0422 rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
0423
0424 create_and_start_worker(ctx);
0425
0426 change_state(ctx, DELETE_6, DELETE_SELF, INVALID);
0427 set_priority(PRIO_VERY_LOW);
0428
0429 rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
0430 set_priority(PRIO_INIT);
0431
0432 create_and_start_worker(ctx);
0433
0434 change_state(ctx, DELETE_9, EXIT_0, INVALID);
0435 set_priority(PRIO_VERY_LOW);
0436
0437 rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
0438 set_priority(PRIO_INIT);
0439
0440 rtems_test_assert(ctx->current == EXIT_3);
0441 }
0442
0443 static void Init(rtems_task_argument arg)
0444 {
0445 TEST_BEGIN();
0446
0447 test();
0448
0449 TEST_END();
0450 rtems_test_exit(0);
0451 }
0452
0453 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
0454 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
0455
0456 #define CONFIGURE_MAXIMUM_TASKS 2
0457 #define CONFIGURE_MAXIMUM_SEMAPHORES 1
0458
0459 #define CONFIGURE_INITIAL_EXTENSIONS \
0460 { \
0461 .thread_restart = restart_extension, \
0462 .thread_delete = delete_extension, \
0463 .thread_terminate = terminate_extension \
0464 }, \
0465 RTEMS_TEST_INITIAL_EXTENSION
0466
0467 #define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES
0468
0469 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
0470
0471 #define CONFIGURE_INIT
0472
0473 #include <rtems/confdefs.h>