File indexing completed on 2025-05-11 08:24:48
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 <errno.h>
0033 #include <pthread.h>
0034 #include <setjmp.h>
0035 #include <threads.h>
0036
0037 #include <rtems.h>
0038 #include <rtems/libcsupport.h>
0039
0040 #include "tmacros.h"
0041
0042 const char rtems_test_name[] = "SPMUTEX 1";
0043
0044 #define TASK_COUNT 5
0045
0046 #define MTX_COUNT 3
0047
0048 typedef enum {
0049 REQ_WAKE_UP_MASTER = RTEMS_EVENT_0,
0050 REQ_WAKE_UP_HELPER = RTEMS_EVENT_1,
0051 REQ_MTX_0_OBTAIN = RTEMS_EVENT_2,
0052 REQ_MTX_0_OBTAIN_UNSATISFIED = RTEMS_EVENT_3,
0053 REQ_MTX_0_RELEASE = RTEMS_EVENT_4,
0054 REQ_MTX_1_OBTAIN = RTEMS_EVENT_5,
0055 REQ_MTX_1_OBTAIN_TIMEOUT = RTEMS_EVENT_6,
0056 REQ_MTX_1_RELEASE = RTEMS_EVENT_7,
0057 REQ_MTX_2_OBTAIN = RTEMS_EVENT_8,
0058 REQ_MTX_2_RELEASE = RTEMS_EVENT_9,
0059 REQ_MTX_C11_OBTAIN = RTEMS_EVENT_10,
0060 REQ_MTX_C11_RELEASE = RTEMS_EVENT_11,
0061 REQ_MTX_POSIX_OBTAIN = RTEMS_EVENT_12,
0062 REQ_MTX_POSIX_RELEASE = RTEMS_EVENT_13
0063 } request_id;
0064
0065 typedef enum {
0066 M,
0067 A_1,
0068 A_2_0,
0069 A_2_1,
0070 H,
0071 NONE
0072 } task_id;
0073
0074 typedef enum {
0075 MTX_0,
0076 MTX_1,
0077 MTX_2
0078 } mutex_id;
0079
0080 typedef struct {
0081 rtems_id mtx[MTX_COUNT];
0082 mtx_t mtx_c11;
0083 pthread_mutex_t mtx_posix;
0084 rtems_id tasks[TASK_COUNT];
0085 int generation[TASK_COUNT];
0086 int expected_generation[TASK_COUNT];
0087 jmp_buf deadlock_return_context;
0088 } test_context;
0089
0090 static test_context test_instance;
0091
0092 static void start_task(
0093 test_context *ctx,
0094 task_id id,
0095 rtems_task_entry entry,
0096 rtems_task_priority prio
0097 )
0098 {
0099 rtems_status_code sc;
0100
0101 sc = rtems_task_create(
0102 rtems_build_name('T', 'A', 'S', 'K'),
0103 prio,
0104 RTEMS_MINIMUM_STACK_SIZE,
0105 RTEMS_DEFAULT_MODES,
0106 RTEMS_DEFAULT_ATTRIBUTES,
0107 &ctx->tasks[id]
0108 );
0109 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0110
0111 sc = rtems_task_start(ctx->tasks[id], entry, id);
0112 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0113 }
0114
0115 static void send_event(test_context *ctx, task_id id, rtems_event_set events)
0116 {
0117 rtems_status_code sc;
0118
0119 sc = rtems_event_send(ctx->tasks[id], events);
0120 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0121 }
0122
0123 static void wait(void)
0124 {
0125 rtems_status_code sc;
0126
0127 sc = rtems_task_wake_after(4);
0128 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0129 }
0130
0131 static rtems_event_set wait_for_events(void)
0132 {
0133 rtems_event_set events;
0134 rtems_status_code sc;
0135
0136 sc = rtems_event_receive(
0137 RTEMS_ALL_EVENTS,
0138 RTEMS_EVENT_ANY | RTEMS_WAIT,
0139 RTEMS_NO_TIMEOUT,
0140 &events
0141 );
0142 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0143
0144 return events;
0145 }
0146
0147 static void sync_with_helper(test_context *ctx)
0148 {
0149 rtems_event_set events;
0150
0151 send_event(ctx, H, REQ_WAKE_UP_HELPER);
0152 events = wait_for_events();
0153 rtems_test_assert(events == REQ_WAKE_UP_MASTER);
0154 }
0155
0156 static void request(test_context *ctx, task_id id, request_id req)
0157 {
0158 send_event(ctx, id, req);
0159 sync_with_helper(ctx);
0160 }
0161
0162 static void obtain_timeout(test_context *ctx, mutex_id id)
0163 {
0164 rtems_status_code sc;
0165
0166 sc = rtems_semaphore_obtain(ctx->mtx[id], RTEMS_WAIT, 2);
0167 rtems_test_assert(sc == RTEMS_TIMEOUT);
0168 }
0169
0170 static void obtain_unsatisfied(test_context *ctx, mutex_id id)
0171 {
0172 rtems_status_code sc;
0173
0174 sc = rtems_semaphore_obtain(ctx->mtx[id], RTEMS_WAIT, RTEMS_NO_TIMEOUT);
0175 rtems_test_assert(sc == RTEMS_UNSATISFIED);
0176 }
0177
0178 static void obtain(test_context *ctx, mutex_id id)
0179 {
0180 rtems_status_code sc;
0181
0182 sc = rtems_semaphore_obtain(ctx->mtx[id], RTEMS_WAIT, RTEMS_NO_TIMEOUT);
0183 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0184 }
0185
0186 static void deadlock_obtain(test_context *ctx, mutex_id id)
0187 {
0188 rtems_status_code sc;
0189
0190 sc = rtems_semaphore_obtain(ctx->mtx[id], RTEMS_WAIT, RTEMS_NO_TIMEOUT);
0191 rtems_test_assert(sc == RTEMS_INCORRECT_STATE);
0192 }
0193
0194 static void release(test_context *ctx, mutex_id id)
0195 {
0196 rtems_status_code sc;
0197
0198 sc = rtems_semaphore_release(ctx->mtx[id]);
0199 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0200 }
0201
0202 static void flush(test_context *ctx, mutex_id id)
0203 {
0204 rtems_status_code sc;
0205
0206 sc = rtems_semaphore_flush(ctx->mtx[id]);
0207 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0208 }
0209
0210 static void obtain_c11(test_context *ctx)
0211 {
0212 int status;
0213
0214 status = mtx_lock(&ctx->mtx_c11);
0215 rtems_test_assert(status == thrd_success);
0216 }
0217
0218 static void deadlock_obtain_c11(test_context *ctx)
0219 {
0220 if (setjmp(ctx->deadlock_return_context) == 0) {
0221 (void) mtx_lock(&ctx->mtx_c11);
0222 }
0223 }
0224
0225 static void release_c11(test_context *ctx)
0226 {
0227 int status;
0228
0229 status = mtx_unlock(&ctx->mtx_c11);
0230 rtems_test_assert(status == thrd_success);
0231 }
0232
0233 static void obtain_posix(test_context *ctx)
0234 {
0235 int error;
0236
0237 error = pthread_mutex_lock(&ctx->mtx_posix);
0238 rtems_test_assert(error == 0);
0239 }
0240
0241 static void deadlock_obtain_posix(test_context *ctx)
0242 {
0243 int error;
0244
0245 error = pthread_mutex_lock(&ctx->mtx_posix);
0246 rtems_test_assert(error == EDEADLK);
0247 }
0248
0249 static void release_posix(test_context *ctx)
0250 {
0251 int error;
0252
0253 error = pthread_mutex_unlock(&ctx->mtx_posix);
0254 rtems_test_assert(error == 0);
0255 }
0256
0257 static void check_generations(test_context *ctx, task_id a, task_id b)
0258 {
0259 size_t i;
0260
0261 if (a != NONE) {
0262 ++ctx->expected_generation[a];
0263 }
0264
0265 if (b != NONE) {
0266 ++ctx->expected_generation[b];
0267 }
0268
0269 for (i = 0; i < TASK_COUNT; ++i) {
0270 rtems_test_assert(ctx->generation[i] == ctx->expected_generation[i]);
0271 }
0272 }
0273
0274 static void assert_prio(
0275 test_context *ctx,
0276 task_id id,
0277 rtems_task_priority expected
0278 )
0279 {
0280 rtems_task_priority actual;
0281 rtems_status_code sc;
0282
0283 sc = rtems_task_set_priority(
0284 ctx->tasks[id],
0285 RTEMS_CURRENT_PRIORITY,
0286 &actual
0287 );
0288 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0289 rtems_test_assert(expected == actual);
0290 }
0291
0292 static void change_prio(
0293 test_context *ctx,
0294 task_id id,
0295 rtems_task_priority prio
0296 )
0297 {
0298 rtems_status_code sc;
0299
0300 sc = rtems_task_set_priority(
0301 ctx->tasks[id],
0302 prio,
0303 &prio
0304 );
0305 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0306 }
0307
0308 static void helper(rtems_task_argument arg)
0309 {
0310 test_context *ctx = &test_instance;
0311
0312 while (true) {
0313 rtems_event_set events = wait_for_events();
0314 rtems_test_assert(events == REQ_WAKE_UP_HELPER);
0315 send_event(ctx, M, REQ_WAKE_UP_MASTER);
0316 }
0317 }
0318
0319 static void worker(rtems_task_argument arg)
0320 {
0321 test_context *ctx = &test_instance;
0322 task_id id = arg;
0323
0324 while (true) {
0325 rtems_event_set events = wait_for_events();
0326
0327 if ((events & REQ_MTX_0_OBTAIN) != 0) {
0328 obtain(ctx, MTX_0);
0329 ++ctx->generation[id];
0330 }
0331
0332 if ((events & REQ_MTX_0_OBTAIN_UNSATISFIED) != 0) {
0333 obtain_unsatisfied(ctx, MTX_0);
0334 ++ctx->generation[id];
0335 }
0336
0337 if ((events & REQ_MTX_0_RELEASE) != 0) {
0338 release(ctx, MTX_0);
0339 ++ctx->generation[id];
0340 }
0341
0342 if ((events & REQ_MTX_1_OBTAIN) != 0) {
0343 obtain(ctx, MTX_1);
0344 ++ctx->generation[id];
0345 }
0346
0347 if ((events & REQ_MTX_1_OBTAIN_TIMEOUT) != 0) {
0348 obtain_timeout(ctx, MTX_1);
0349 ++ctx->generation[id];
0350 }
0351
0352 if ((events & REQ_MTX_1_RELEASE) != 0) {
0353 release(ctx, MTX_1);
0354 ++ctx->generation[id];
0355 }
0356
0357 if ((events & REQ_MTX_2_OBTAIN) != 0) {
0358 obtain(ctx, MTX_2);
0359 ++ctx->generation[id];
0360 }
0361
0362 if ((events & REQ_MTX_2_RELEASE) != 0) {
0363 release(ctx, MTX_2);
0364 ++ctx->generation[id];
0365 }
0366
0367 if ((events & REQ_MTX_C11_OBTAIN) != 0) {
0368 obtain_c11(ctx);
0369 ++ctx->generation[id];
0370 }
0371
0372 if ((events & REQ_MTX_C11_RELEASE) != 0) {
0373 release_c11(ctx);
0374 ++ctx->generation[id];
0375 }
0376
0377 if ((events & REQ_MTX_POSIX_OBTAIN) != 0) {
0378 obtain_posix(ctx);
0379 ++ctx->generation[id];
0380 }
0381
0382 if ((events & REQ_MTX_POSIX_RELEASE) != 0) {
0383 release_posix(ctx);
0384 ++ctx->generation[id];
0385 }
0386 }
0387 }
0388
0389 static void set_up(test_context *ctx)
0390 {
0391 rtems_status_code sc;
0392 int status;
0393 size_t i;
0394 int error;
0395 pthread_mutexattr_t attr;
0396
0397 ctx->tasks[M] = rtems_task_self();
0398 start_task(ctx, A_1, worker, 1);
0399 start_task(ctx, A_2_0, worker, 2);
0400 start_task(ctx, A_2_1, worker, 2);
0401 start_task(ctx, H, helper, 3);
0402
0403 for (i = 0; i < MTX_COUNT; ++i) {
0404 sc = rtems_semaphore_create(
0405 rtems_build_name(' ', 'M', 'T', 'X'),
0406 1,
0407 RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY,
0408 0,
0409 &ctx->mtx[i]
0410 );
0411 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0412 }
0413
0414 status = mtx_init(&ctx->mtx_c11, mtx_plain);
0415 rtems_test_assert(status == thrd_success);
0416
0417 error = pthread_mutexattr_init(&attr);
0418 rtems_test_assert(error == 0);
0419
0420 error = pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
0421 rtems_test_assert(error == 0);
0422
0423 error = pthread_mutex_init(&ctx->mtx_posix, &attr);
0424 rtems_test_assert(error == 0);
0425
0426 error = pthread_mutexattr_destroy(&attr);
0427 rtems_test_assert(error == 0);
0428 }
0429
0430 static void test_inherit(test_context *ctx)
0431 {
0432 assert_prio(ctx, M, 3);
0433 obtain(ctx, MTX_0);
0434 request(ctx, A_1, REQ_MTX_0_OBTAIN);
0435 check_generations(ctx, NONE, NONE);
0436 assert_prio(ctx, M, 1);
0437 change_prio(ctx, A_1, 2);
0438 assert_prio(ctx, M, 2);
0439 change_prio(ctx, A_1, 3);
0440 assert_prio(ctx, M, 3);
0441 change_prio(ctx, A_1, 4);
0442 assert_prio(ctx, M, 3);
0443 change_prio(ctx, A_1, 1);
0444 assert_prio(ctx, M, 1);
0445 release(ctx, MTX_0);
0446 check_generations(ctx, A_1, NONE);
0447 assert_prio(ctx, M, 3);
0448 request(ctx, A_1, REQ_MTX_0_RELEASE);
0449 check_generations(ctx, A_1, NONE);
0450 }
0451
0452 static void test_inherit_fifo_for_equal_priority(test_context *ctx)
0453 {
0454 assert_prio(ctx, M, 3);
0455 obtain(ctx, MTX_0);
0456 request(ctx, A_2_0, REQ_MTX_0_OBTAIN);
0457 request(ctx, A_1, REQ_MTX_0_OBTAIN);
0458 request(ctx, A_2_1, REQ_MTX_0_OBTAIN);
0459 check_generations(ctx, NONE, NONE);
0460 assert_prio(ctx, M, 1);
0461 release(ctx, MTX_0);
0462 check_generations(ctx, A_1, NONE);
0463 assert_prio(ctx, M, 3);
0464 assert_prio(ctx, A_1, 1);
0465 request(ctx, A_1, REQ_MTX_0_RELEASE);
0466 check_generations(ctx, A_1, A_2_0);
0467 request(ctx, A_2_0, REQ_MTX_0_RELEASE);
0468 check_generations(ctx, A_2_0, A_2_1);
0469 request(ctx, A_2_1, REQ_MTX_0_RELEASE);
0470 check_generations(ctx, A_2_1, NONE);
0471 }
0472
0473 static void test_inherit_nested_vertical(test_context *ctx)
0474 {
0475 assert_prio(ctx, M, 3);
0476 obtain(ctx, MTX_0);
0477 obtain(ctx, MTX_1);
0478 request(ctx, A_1, REQ_MTX_1_OBTAIN);
0479 check_generations(ctx, NONE, NONE);
0480 assert_prio(ctx, M, 1);
0481 release(ctx, MTX_1);
0482 check_generations(ctx, A_1, NONE);
0483 assert_prio(ctx, M, 3);
0484 request(ctx, A_1, REQ_MTX_1_RELEASE);
0485 check_generations(ctx, A_1, NONE);
0486 release(ctx, MTX_0);
0487 }
0488
0489 static void test_inherit_nested_vertical_timeout(test_context *ctx)
0490 {
0491 assert_prio(ctx, M, 3);
0492 obtain(ctx, MTX_0);
0493 obtain(ctx, MTX_1);
0494 request(ctx, A_1, REQ_MTX_1_OBTAIN_TIMEOUT);
0495 check_generations(ctx, NONE, NONE);
0496 assert_prio(ctx, M, 1);
0497 wait();
0498 check_generations(ctx, A_1, NONE);
0499 assert_prio(ctx, M, 3);
0500 release(ctx, MTX_1);
0501 release(ctx, MTX_0);
0502 }
0503
0504 static void test_inherit_nested_horizontal(test_context *ctx)
0505 {
0506 assert_prio(ctx, M, 3);
0507 obtain(ctx, MTX_0);
0508 request(ctx, A_2_0, REQ_MTX_1_OBTAIN);
0509 check_generations(ctx, A_2_0, NONE);
0510 request(ctx, A_2_0, REQ_MTX_0_OBTAIN);
0511 check_generations(ctx, NONE, NONE);
0512 assert_prio(ctx, M, 2);
0513 request(ctx, A_1, REQ_MTX_1_OBTAIN_TIMEOUT);
0514 check_generations(ctx, NONE, NONE);
0515 assert_prio(ctx, A_2_0, 1);
0516 assert_prio(ctx, M, 1);
0517 wait();
0518 check_generations(ctx, A_1, NONE);
0519 assert_prio(ctx, A_2_0, 2);
0520 assert_prio(ctx, M, 2);
0521 request(ctx, A_1, REQ_MTX_1_OBTAIN);
0522 check_generations(ctx, NONE, NONE);
0523 assert_prio(ctx, A_2_0, 1);
0524 assert_prio(ctx, M, 1);
0525 change_prio(ctx, A_1, 2);
0526 assert_prio(ctx, M, 2);
0527 change_prio(ctx, A_1, 3);
0528 assert_prio(ctx, M, 2);
0529 change_prio(ctx, A_2_0, 3);
0530 assert_prio(ctx, M, 3);
0531 change_prio(ctx, A_2_0, 2);
0532 assert_prio(ctx, M, 2);
0533 change_prio(ctx, A_1, 1);
0534 assert_prio(ctx, M, 1);
0535 release(ctx, MTX_0);
0536 check_generations(ctx, A_2_0, NONE);
0537 assert_prio(ctx, A_2_0, 1);
0538 assert_prio(ctx, M, 3);
0539 request(ctx, A_2_0, REQ_MTX_0_RELEASE);
0540 check_generations(ctx, A_2_0, NONE);
0541 assert_prio(ctx, A_2_0, 1);
0542 request(ctx, A_2_0, REQ_MTX_1_RELEASE);
0543 check_generations(ctx, A_1, A_2_0);
0544 assert_prio(ctx, A_2_0, 2);
0545 request(ctx, A_1, REQ_MTX_1_RELEASE);
0546 check_generations(ctx, A_1, NONE);
0547 }
0548
0549 static void test_inherit_flush(test_context *ctx)
0550 {
0551 assert_prio(ctx, M, 3);
0552 obtain(ctx, MTX_0);
0553 request(ctx, A_1, REQ_MTX_0_OBTAIN_UNSATISFIED);
0554 check_generations(ctx, NONE, NONE);
0555 assert_prio(ctx, M, 1);
0556 flush(ctx, MTX_0);
0557 check_generations(ctx, A_1, NONE);
0558 assert_prio(ctx, M, 3);
0559 release(ctx, MTX_0);
0560 }
0561
0562 static void test_deadlock_two_classic(test_context *ctx)
0563 {
0564 obtain(ctx, MTX_0);
0565 request(ctx, A_1, REQ_MTX_1_OBTAIN);
0566 check_generations(ctx, A_1, NONE);
0567 request(ctx, A_1, REQ_MTX_0_OBTAIN);
0568 check_generations(ctx, NONE, NONE);
0569 deadlock_obtain(ctx, MTX_1);
0570 release(ctx, MTX_0);
0571 check_generations(ctx, A_1, NONE);
0572 request(ctx, A_1, REQ_MTX_0_RELEASE);
0573 check_generations(ctx, A_1, NONE);
0574 request(ctx, A_1, REQ_MTX_1_RELEASE);
0575 check_generations(ctx, A_1, NONE);
0576 }
0577
0578 static void test_deadlock_three_classic(test_context *ctx)
0579 {
0580 obtain(ctx, MTX_0);
0581 request(ctx, A_1, REQ_MTX_1_OBTAIN);
0582 check_generations(ctx, A_1, NONE);
0583 request(ctx, A_2_0, REQ_MTX_2_OBTAIN);
0584 check_generations(ctx, A_2_0, NONE);
0585 request(ctx, A_2_0, REQ_MTX_1_OBTAIN);
0586 check_generations(ctx, NONE, NONE);
0587 request(ctx, A_1, REQ_MTX_0_OBTAIN);
0588 check_generations(ctx, NONE, NONE);
0589 deadlock_obtain(ctx, MTX_2);
0590 release(ctx, MTX_0);
0591 check_generations(ctx, A_1, NONE);
0592 request(ctx, A_1, REQ_MTX_0_RELEASE);
0593 check_generations(ctx, A_1, NONE);
0594 request(ctx, A_1, REQ_MTX_1_RELEASE);
0595 check_generations(ctx, A_1, A_2_0);
0596 request(ctx, A_2_0, REQ_MTX_2_RELEASE);
0597 check_generations(ctx, A_2_0, NONE);
0598 request(ctx, A_2_0, REQ_MTX_1_RELEASE);
0599 check_generations(ctx, A_2_0, NONE);
0600 }
0601
0602 static void test_deadlock_c11_and_classic(test_context *ctx)
0603 {
0604 obtain_c11(ctx);
0605 request(ctx, A_1, REQ_MTX_0_OBTAIN);
0606 check_generations(ctx, A_1, NONE);
0607 request(ctx, A_1, REQ_MTX_C11_OBTAIN);
0608 check_generations(ctx, NONE, NONE);
0609 deadlock_obtain(ctx, MTX_0);
0610 release_c11(ctx);
0611 check_generations(ctx, A_1, NONE);
0612 request(ctx, A_1, REQ_MTX_C11_RELEASE);
0613 check_generations(ctx, A_1, NONE);
0614 request(ctx, A_1, REQ_MTX_0_RELEASE);
0615 check_generations(ctx, A_1, NONE);
0616 }
0617
0618 static void test_deadlock_classic_and_c11(test_context *ctx)
0619 {
0620 obtain(ctx, MTX_0);
0621 request(ctx, A_1, REQ_MTX_C11_OBTAIN);
0622 check_generations(ctx, A_1, NONE);
0623 request(ctx, A_1, REQ_MTX_0_OBTAIN);
0624 check_generations(ctx, NONE, NONE);
0625 deadlock_obtain_c11(ctx);
0626 release(ctx, MTX_0);
0627 check_generations(ctx, A_1, NONE);
0628 request(ctx, A_1, REQ_MTX_0_RELEASE);
0629 check_generations(ctx, A_1, NONE);
0630 request(ctx, A_1, REQ_MTX_C11_RELEASE);
0631 check_generations(ctx, A_1, NONE);
0632 }
0633
0634 static void test_deadlock_posix_and_classic(test_context *ctx)
0635 {
0636 obtain_posix(ctx);
0637 request(ctx, A_1, REQ_MTX_0_OBTAIN);
0638 check_generations(ctx, A_1, NONE);
0639 request(ctx, A_1, REQ_MTX_POSIX_OBTAIN);
0640 check_generations(ctx, NONE, NONE);
0641 deadlock_obtain(ctx, MTX_0);
0642 release_posix(ctx);
0643 check_generations(ctx, A_1, NONE);
0644 request(ctx, A_1, REQ_MTX_POSIX_RELEASE);
0645 check_generations(ctx, A_1, NONE);
0646 request(ctx, A_1, REQ_MTX_0_RELEASE);
0647 check_generations(ctx, A_1, NONE);
0648 }
0649
0650 static void test_deadlock_classic_and_posix(test_context *ctx)
0651 {
0652 obtain(ctx, MTX_0);
0653 request(ctx, A_1, REQ_MTX_POSIX_OBTAIN);
0654 check_generations(ctx, A_1, NONE);
0655 request(ctx, A_1, REQ_MTX_0_OBTAIN);
0656 check_generations(ctx, NONE, NONE);
0657 deadlock_obtain_posix(ctx);
0658 release(ctx, MTX_0);
0659 check_generations(ctx, A_1, NONE);
0660 request(ctx, A_1, REQ_MTX_0_RELEASE);
0661 check_generations(ctx, A_1, NONE);
0662 request(ctx, A_1, REQ_MTX_POSIX_RELEASE);
0663 check_generations(ctx, A_1, NONE);
0664 }
0665
0666 static void tear_down(test_context *ctx)
0667 {
0668 rtems_status_code sc;
0669 size_t i;
0670 int error;
0671
0672 for (i = 1; i < TASK_COUNT; ++i) {
0673 sc = rtems_task_delete(ctx->tasks[i]);
0674 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0675 }
0676
0677 for (i = 0; i < MTX_COUNT; ++i) {
0678 sc = rtems_semaphore_delete(ctx->mtx[i]);
0679 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0680 }
0681
0682 mtx_destroy(&ctx->mtx_c11);
0683
0684 error = pthread_mutex_destroy(&ctx->mtx_posix);
0685 rtems_test_assert(error == 0);
0686 }
0687
0688 static void Init(rtems_task_argument arg)
0689 {
0690 test_context *ctx = &test_instance;
0691 rtems_resource_snapshot snapshot;
0692
0693 TEST_BEGIN();
0694 rtems_resource_snapshot_take(&snapshot);
0695
0696 set_up(ctx);
0697 test_inherit(ctx);
0698 test_inherit_fifo_for_equal_priority(ctx);
0699 test_inherit_nested_vertical(ctx);
0700 test_inherit_nested_vertical_timeout(ctx);
0701 test_inherit_nested_horizontal(ctx);
0702 test_inherit_flush(ctx);
0703 test_deadlock_two_classic(ctx);
0704 test_deadlock_three_classic(ctx);
0705 test_deadlock_c11_and_classic(ctx);
0706 test_deadlock_classic_and_c11(ctx);
0707 test_deadlock_posix_and_classic(ctx);
0708 test_deadlock_classic_and_posix(ctx);
0709 tear_down(ctx);
0710
0711 rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
0712 TEST_END();
0713 rtems_test_exit(0);
0714 }
0715
0716 static void fatal_extension(
0717 rtems_fatal_source source,
0718 bool always_set_to_false,
0719 rtems_fatal_code error
0720 )
0721 {
0722
0723 if (
0724 source == INTERNAL_ERROR_CORE
0725 && !always_set_to_false
0726 && error == INTERNAL_ERROR_THREAD_QUEUE_DEADLOCK
0727 ) {
0728 test_context *ctx = &test_instance;
0729
0730 _ISR_Set_level(0);
0731 longjmp(ctx->deadlock_return_context, 1);
0732 }
0733 }
0734
0735 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
0736 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
0737
0738 #define CONFIGURE_MAXIMUM_TASKS TASK_COUNT
0739
0740 #define CONFIGURE_MAXIMUM_SEMAPHORES 3
0741
0742 #define CONFIGURE_INITIAL_EXTENSIONS \
0743 { .fatal = fatal_extension }, \
0744 RTEMS_TEST_INITIAL_EXTENSION
0745
0746 #define CONFIGURE_INIT_TASK_PRIORITY 3
0747
0748 #define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES
0749
0750 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
0751
0752 #define CONFIGURE_INIT
0753
0754 #include <rtems/confdefs.h>