Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:48

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*
0004  * Copyright (C) 2015, 2017 embedded brains GmbH & Co. KG
0005  *
0006  * Redistribution and use in source and binary forms, with or without
0007  * modification, are permitted provided that the following conditions
0008  * are met:
0009  * 1. Redistributions of source code must retain the above copyright
0010  *    notice, this list of conditions and the following disclaimer.
0011  * 2. Redistributions in binary form must reproduce the above copyright
0012  *    notice, this list of conditions and the following disclaimer in the
0013  *    documentation and/or other materials provided with the distribution.
0014  *
0015  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0016  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0017  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0018  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0019  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0020  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0021  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0022  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0023  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0024  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0025  * POSSIBILITY OF SUCH DAMAGE.
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>