File indexing completed on 2025-05-11 08:24:47
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifdef HAVE_CONFIG_H
0010 #include "config.h"
0011 #endif
0012
0013 #include "tmacros.h"
0014
0015 #include <assert.h>
0016 #include <limits.h>
0017 #include <stdlib.h>
0018
0019 #include <bsp.h>
0020
0021 #include <rtems/score/apimutex.h>
0022 #include <rtems/score/sysstate.h>
0023 #include <rtems/score/threaddispatch.h>
0024
0025 const char rtems_test_name[] = "SPEXTENSIONS 1";
0026
0027 static int counter;
0028
0029 static int active_extensions = 2;
0030
0031 static rtems_id master_task;
0032
0033 static bool before_initialization(void)
0034 {
0035 return _System_state_Is_before_initialization(_System_state_Get());
0036 }
0037
0038 static bool before_multitasking(void)
0039 {
0040 return _System_state_Is_before_multitasking(_System_state_Get());
0041 }
0042
0043 static bool life_protected(void)
0044 {
0045 Thread_Control *executing;
0046
0047 executing = _Thread_Get_executing();
0048
0049 return executing == NULL
0050 || (executing->Life.state & THREAD_LIFE_PROTECTED) != 0;
0051 }
0052
0053 static void assert_normal_thread_context(void)
0054 {
0055 assert(_Thread_Dispatch_is_enabled());
0056 assert(!_RTEMS_Allocator_is_owner());
0057 assert(!life_protected());
0058 }
0059
0060 static void assert_life_protected_thread_context(void)
0061 {
0062 assert(_Thread_Dispatch_is_enabled() || before_multitasking());
0063 assert(!_RTEMS_Allocator_is_owner());
0064 assert(life_protected() || before_multitasking());
0065 }
0066
0067 static void assert_allocator_protected_thread_context(void)
0068 {
0069 assert(
0070 _Thread_Dispatch_is_enabled() ||
0071 before_initialization() ||
0072 before_multitasking()
0073 );
0074 assert(_RTEMS_Allocator_is_owner());
0075 assert(life_protected());
0076 }
0077
0078 static void assert_thread_dispatch_disabled_context(void)
0079 {
0080 assert(!_Thread_Dispatch_is_enabled());
0081 assert(!_RTEMS_Allocator_is_owner());
0082 assert(!life_protected());
0083 }
0084
0085 static void assert_forward_order(int index)
0086 {
0087 assert((counter % active_extensions) == index);
0088 ++counter;
0089 }
0090
0091 static void assert_reverse_order(int index)
0092 {
0093 assert((counter % active_extensions) == (active_extensions - 1 - index));
0094 ++counter;
0095 }
0096
0097 static bool zero_thread_create(rtems_tcb *a, rtems_tcb *b)
0098 {
0099 assert_forward_order(0);
0100 assert_allocator_protected_thread_context();
0101 return true;
0102 }
0103
0104 static void zero_thread_start(rtems_tcb *a, rtems_tcb *b)
0105 {
0106 assert_forward_order(0);
0107 assert_thread_dispatch_disabled_context();
0108 }
0109
0110 static void zero_thread_restart(rtems_tcb *a, rtems_tcb *b)
0111 {
0112 assert_forward_order(0);
0113 assert_life_protected_thread_context();
0114 }
0115
0116 static void zero_thread_delete(rtems_tcb *a, rtems_tcb *b)
0117 {
0118 assert_reverse_order(0);
0119 assert_allocator_protected_thread_context();
0120 }
0121
0122 static void zero_thread_switch(rtems_tcb *a, rtems_tcb *b)
0123 {
0124 assert_forward_order(0);
0125 }
0126
0127 static void zero_thread_begin(rtems_tcb *a)
0128 {
0129 assert_forward_order(0);
0130 assert_normal_thread_context();
0131 }
0132
0133 static void zero_thread_exitted(rtems_tcb *a)
0134 {
0135 assert_forward_order(0);
0136 assert_normal_thread_context();
0137 }
0138
0139 static void zero_fatal(
0140 rtems_fatal_source source,
0141 bool always_set_to_false,
0142 rtems_fatal_code code
0143 )
0144 {
0145 if (source == RTEMS_FATAL_SOURCE_EXIT) {
0146 assert_forward_order(0);
0147 }
0148 }
0149
0150 static void zero_thread_terminate(rtems_tcb *a)
0151 {
0152 assert_reverse_order(0);
0153 assert_life_protected_thread_context();
0154 }
0155
0156 static bool one_thread_create(rtems_tcb *a, rtems_tcb *b)
0157 {
0158 assert_forward_order(1);
0159 assert_allocator_protected_thread_context();
0160 return true;
0161 }
0162
0163 static void one_thread_start(rtems_tcb *a, rtems_tcb *b)
0164 {
0165 assert_forward_order(1);
0166 assert_thread_dispatch_disabled_context();
0167 }
0168
0169 static void one_thread_restart(rtems_tcb *a, rtems_tcb *b)
0170 {
0171 assert_forward_order(1);
0172 assert_life_protected_thread_context();
0173 }
0174
0175 static void one_thread_delete(rtems_tcb *a, rtems_tcb *b)
0176 {
0177 assert_reverse_order(1);
0178 assert_allocator_protected_thread_context();
0179 }
0180
0181 static void one_thread_switch(rtems_tcb *a, rtems_tcb *b)
0182 {
0183 assert_forward_order(1);
0184 }
0185
0186 static void one_thread_begin(rtems_tcb *a)
0187 {
0188 assert_forward_order(1);
0189 assert_normal_thread_context();
0190 }
0191
0192 static void one_thread_exitted(rtems_tcb *a)
0193 {
0194 assert_forward_order(1);
0195 assert_normal_thread_context();
0196 }
0197
0198 static void one_fatal(
0199 rtems_fatal_source source,
0200 bool always_set_to_false,
0201 rtems_fatal_code code
0202 )
0203 {
0204 if (source == RTEMS_FATAL_SOURCE_EXIT) {
0205 assert_forward_order(1);
0206 }
0207 }
0208
0209 static void one_thread_terminate(rtems_tcb *a)
0210 {
0211 assert_reverse_order(1);
0212 assert_life_protected_thread_context();
0213 }
0214
0215 static bool two_thread_create(rtems_tcb *a, rtems_tcb *b)
0216 {
0217 assert_forward_order(2);
0218 assert_allocator_protected_thread_context();
0219 return true;
0220 }
0221
0222 static void two_thread_start(rtems_tcb *a, rtems_tcb *b)
0223 {
0224 assert_forward_order(2);
0225 assert_thread_dispatch_disabled_context();
0226 }
0227
0228 static void two_thread_restart(rtems_tcb *a, rtems_tcb *b)
0229 {
0230 assert_forward_order(2);
0231 assert_life_protected_thread_context();
0232 }
0233
0234 static void two_thread_delete(rtems_tcb *a, rtems_tcb *b)
0235 {
0236 assert_reverse_order(2);
0237 assert_allocator_protected_thread_context();
0238 }
0239
0240 static void two_thread_switch(rtems_tcb *a, rtems_tcb *b)
0241 {
0242 assert_forward_order(2);
0243 }
0244
0245 static void two_thread_begin(rtems_tcb *a)
0246 {
0247 assert_forward_order(2);
0248 assert_normal_thread_context();
0249 }
0250
0251 static void two_thread_exitted(rtems_tcb *a)
0252 {
0253 assert_forward_order(2);
0254 assert_normal_thread_context();
0255 }
0256
0257 static void two_fatal(
0258 rtems_fatal_source source,
0259 bool always_set_to_false,
0260 rtems_fatal_code code
0261 )
0262 {
0263 if (source == RTEMS_FATAL_SOURCE_EXIT) {
0264 assert_forward_order(2);
0265 }
0266 }
0267
0268 static void two_thread_terminate(rtems_tcb *a)
0269 {
0270 assert_reverse_order(2);
0271 assert_life_protected_thread_context();
0272 }
0273
0274 static bool three_thread_create(rtems_tcb *a, rtems_tcb *b)
0275 {
0276 assert_forward_order(3);
0277 assert_allocator_protected_thread_context();
0278 return true;
0279 }
0280
0281 static void three_thread_start(rtems_tcb *a, rtems_tcb *b)
0282 {
0283 assert_forward_order(3);
0284 assert_thread_dispatch_disabled_context();
0285 }
0286
0287 static void three_thread_restart(rtems_tcb *a, rtems_tcb *b)
0288 {
0289 assert_forward_order(3);
0290 assert_life_protected_thread_context();
0291 }
0292
0293 static void three_thread_delete(rtems_tcb *a, rtems_tcb *b)
0294 {
0295 assert_reverse_order(3);
0296 assert_allocator_protected_thread_context();
0297 }
0298
0299 static void three_thread_switch(rtems_tcb *a, rtems_tcb *b)
0300 {
0301 assert_forward_order(3);
0302 }
0303
0304 static void three_thread_begin(rtems_tcb *a)
0305 {
0306 assert_forward_order(3);
0307 assert_normal_thread_context();
0308 }
0309
0310 static void three_thread_exitted(rtems_tcb *a)
0311 {
0312 assert_forward_order(3);
0313 assert_normal_thread_context();
0314 }
0315
0316 static void three_fatal(
0317 rtems_fatal_source source,
0318 bool always_set_to_false,
0319 rtems_fatal_code code
0320 )
0321 {
0322 if (source == RTEMS_FATAL_SOURCE_EXIT) {
0323 assert_forward_order(3);
0324 assert(counter == 68);
0325 TEST_END();
0326 }
0327 }
0328
0329 static void three_thread_terminate(rtems_tcb *a)
0330 {
0331 assert_reverse_order(3);
0332 assert_life_protected_thread_context();
0333 }
0334
0335 #define ZERO \
0336 { \
0337 .thread_create = zero_thread_create, \
0338 .thread_start = zero_thread_start, \
0339 .thread_restart = zero_thread_restart, \
0340 .thread_delete = zero_thread_delete, \
0341 .thread_switch = zero_thread_switch, \
0342 .thread_begin = zero_thread_begin, \
0343 .thread_exitted = zero_thread_exitted, \
0344 .fatal = zero_fatal, \
0345 .thread_terminate = zero_thread_terminate \
0346 }
0347
0348 #define ONE \
0349 { \
0350 .thread_create = one_thread_create, \
0351 .thread_start = one_thread_start, \
0352 .thread_restart = one_thread_restart, \
0353 .thread_delete = one_thread_delete, \
0354 .thread_switch = one_thread_switch, \
0355 .thread_begin = one_thread_begin, \
0356 .thread_exitted = one_thread_exitted, \
0357 .fatal = one_fatal, \
0358 .thread_terminate = one_thread_terminate \
0359 }
0360
0361 static const rtems_extensions_table two = {
0362 .thread_create = two_thread_create,
0363 .thread_start = two_thread_start,
0364 .thread_restart = two_thread_restart,
0365 .thread_delete = two_thread_delete,
0366 .thread_switch = two_thread_switch,
0367 .thread_begin = two_thread_begin,
0368 .thread_exitted = two_thread_exitted,
0369 .fatal = two_fatal,
0370 .thread_terminate = two_thread_terminate
0371 };
0372
0373 static const rtems_extensions_table three = {
0374 .thread_create = three_thread_create,
0375 .thread_start = three_thread_start,
0376 .thread_restart = three_thread_restart,
0377 .thread_delete = three_thread_delete,
0378 .thread_switch = three_thread_switch,
0379 .thread_begin = three_thread_begin,
0380 .thread_exitted = three_thread_exitted,
0381 .fatal = three_fatal,
0382 .thread_terminate = three_thread_terminate
0383 };
0384
0385 static const rtems_extensions_table initial_test =
0386 RTEMS_TEST_INITIAL_EXTENSION;
0387
0388 #ifdef BSP_INITIAL_EXTENSION
0389 static const rtems_extensions_table initial_bsp =
0390 BSP_INITIAL_EXTENSION;
0391 #endif
0392
0393 static void wake_up_master(void)
0394 {
0395 rtems_status_code sc;
0396
0397 sc = rtems_event_transient_send(master_task);
0398 assert(sc == RTEMS_SUCCESSFUL);
0399 }
0400
0401 static void wait_for_worker(void)
0402 {
0403 rtems_status_code sc;
0404
0405 sc = rtems_event_transient_receive(
0406 RTEMS_WAIT,
0407 RTEMS_NO_TIMEOUT
0408 );
0409 assert(sc == RTEMS_SUCCESSFUL);
0410 }
0411
0412 static void worker(rtems_task_argument arg)
0413 {
0414 wake_up_master();
0415
0416 (void) rtems_task_suspend(RTEMS_SELF);
0417 assert(false);
0418 }
0419
0420 static void test(void)
0421 {
0422 rtems_status_code sc;
0423 rtems_id id;
0424
0425 master_task = rtems_task_self();
0426
0427 sc = rtems_extension_create(
0428 rtems_build_name('2', ' ', ' ', ' '),
0429 &two,
0430 &id
0431 );
0432 assert(sc == RTEMS_SUCCESSFUL);
0433
0434 sc = rtems_extension_create(
0435 rtems_build_name('3', ' ', ' ', ' '),
0436 &three,
0437 &id
0438 );
0439 assert(sc == RTEMS_SUCCESSFUL);
0440
0441 sc = rtems_extension_create(
0442 rtems_build_name('T', 'E', 'S', 'T'),
0443 &initial_test,
0444 &id
0445 );
0446 assert(sc == RTEMS_SUCCESSFUL);
0447
0448 #ifdef BSP_INITIAL_EXTENSION
0449 sc = rtems_extension_create(
0450 rtems_build_name(' ', 'B', 'S', 'P'),
0451 &initial_bsp,
0452 &id
0453 );
0454 assert(sc == RTEMS_SUCCESSFUL);
0455 #undef BSP_INITIAL_EXTENSION
0456 #endif
0457
0458 active_extensions = 4;
0459
0460
0461
0462
0463
0464
0465
0466
0467
0468 #ifdef RTEMS_SMP
0469 assert(counter == 12);
0470 #else
0471 assert(counter == 10);
0472 counter = 12;
0473 #endif
0474
0475 sc = rtems_task_create(
0476 rtems_build_name('W', 'O', 'R', 'K'),
0477 2,
0478 RTEMS_MINIMUM_STACK_SIZE,
0479 RTEMS_DEFAULT_MODES,
0480 RTEMS_DEFAULT_ATTRIBUTES,
0481 &id
0482 );
0483 assert(sc == RTEMS_SUCCESSFUL);
0484
0485 sc = rtems_task_start(id, worker, 0);
0486 assert(sc == RTEMS_SUCCESSFUL);
0487
0488 wait_for_worker();
0489
0490 sc = rtems_task_restart(id, 0);
0491 assert(sc == RTEMS_SUCCESSFUL);
0492
0493 wait_for_worker();
0494
0495 sc = rtems_task_delete(id);
0496 assert(sc == RTEMS_SUCCESSFUL);
0497
0498
0499 sc = rtems_task_create(
0500 rtems_build_name('N', 'U', 'L', 'L'),
0501 2,
0502 SIZE_MAX,
0503 RTEMS_DEFAULT_MODES,
0504 RTEMS_DEFAULT_ATTRIBUTES,
0505 &id
0506 );
0507 assert(sc == RTEMS_UNSATISFIED);
0508 }
0509
0510 static void Init(rtems_task_argument arg)
0511 {
0512 TEST_BEGIN();
0513
0514 test();
0515
0516 exit(0);
0517 }
0518
0519 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
0520 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
0521
0522 #define CONFIGURE_MAXIMUM_USER_EXTENSIONS 4
0523
0524 #define CONFIGURE_MAXIMUM_TASKS 2
0525
0526 #define CONFIGURE_INITIAL_EXTENSIONS ZERO, ONE
0527
0528 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
0529
0530 #define CONFIGURE_INIT
0531
0532 #include <rtems/confdefs.h>