Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*
0004  * Copyright (C) 2015, 2016 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 "tmacros.h"
0033 
0034 #include <sys/lock.h>
0035 #include <errno.h>
0036 #include <limits.h>
0037 #include <setjmp.h>
0038 #include <string.h>
0039 #include <time.h>
0040 
0041 const char rtems_test_name[] = "SPSYSLOCK 1";
0042 
0043 #define US_PER_TICK 10000
0044 
0045 #define EVENT_MTX_ACQUIRE RTEMS_EVENT_0
0046 
0047 #define EVENT_MTX_RELEASE RTEMS_EVENT_1
0048 
0049 #define EVENT_MTX_PRIO_INV RTEMS_EVENT_2
0050 
0051 #define EVENT_REC_MTX_ACQUIRE RTEMS_EVENT_4
0052 
0053 #define EVENT_REC_MTX_RELEASE RTEMS_EVENT_5
0054 
0055 #define EVENT_REC_MTX_PRIO_INV RTEMS_EVENT_6
0056 
0057 #define EVENT_SEM_WAIT RTEMS_EVENT_7
0058 
0059 #define EVENT_FUTEX_WAIT RTEMS_EVENT_8
0060 
0061 #define EVENT_CONDITION_WAIT RTEMS_EVENT_9
0062 
0063 #define EVENT_CONDITION_WAIT_REC RTEMS_EVENT_10
0064 
0065 typedef struct {
0066   rtems_id high[2];
0067   rtems_id mid;
0068   rtems_id low;
0069   struct _Mutex_Control mtx;
0070   struct _Mutex_recursive_Control rec_mtx;
0071   struct _Condition_Control cond;
0072   struct _Semaphore_Control sem;
0073   struct _Futex_Control futex;
0074   int val;
0075   int eno[2];
0076   int generation[2];
0077   int current_generation[2];
0078   jmp_buf deadlock_return_context;
0079 } test_context;
0080 
0081 static test_context test_instance;
0082 
0083 static int generation(test_context *ctx, size_t idx)
0084 {
0085   return ++ctx->current_generation[idx];
0086 }
0087 
0088 static void send_event(test_context *ctx, size_t idx, rtems_event_set events)
0089 {
0090   rtems_status_code sc;
0091 
0092   sc = rtems_event_send(ctx->high[idx], events);
0093   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0094 }
0095 
0096 static void get_abs_timeout(struct timespec *to)
0097 {
0098   int rv;
0099 
0100   rv = clock_gettime(CLOCK_REALTIME, to);
0101   rtems_test_assert(rv == 0);
0102 
0103   to->tv_nsec += 2 * US_PER_TICK * 1000;
0104   if (to->tv_nsec >= 1000000000) {
0105     ++to->tv_sec;
0106     to->tv_nsec -= 1000000000;
0107   }
0108 }
0109 
0110 static bool eq_tq(
0111   const struct _Thread_queue_Queue *a,
0112   const struct _Thread_queue_Queue *b
0113 )
0114 {
0115   return a->_Lock._next_ticket == b->_Lock._next_ticket
0116     && a->_Lock._now_serving == b->_Lock._now_serving
0117     && a->_heads == b->_heads
0118     && a->_owner == b->_owner
0119     && a->_name == b->_name;
0120 }
0121 
0122 static bool eq_mtx(
0123   const struct _Mutex_Control *a,
0124   const struct _Mutex_Control *b
0125 )
0126 {
0127   return eq_tq(&a->_Queue, &b->_Queue);
0128 }
0129 
0130 static bool eq_rec_mtx(
0131   const struct _Mutex_recursive_Control *a,
0132   const struct _Mutex_recursive_Control *b
0133 )
0134 {
0135   return eq_mtx(&a->_Mutex, &b->_Mutex)
0136     && a->_nest_level == b->_nest_level;
0137 }
0138 
0139 static bool eq_cond(
0140   const struct _Condition_Control *a,
0141   const struct _Condition_Control *b
0142 )
0143 {
0144   return eq_tq(&a->_Queue, &b->_Queue);
0145 }
0146 
0147 static bool eq_sem(
0148   const struct _Semaphore_Control *a,
0149   const struct _Semaphore_Control *b
0150 )
0151 {
0152   return eq_tq(&a->_Queue, &b->_Queue)
0153     && a->_count == b->_count;
0154 }
0155 
0156 static bool eq_futex(
0157   const struct _Futex_Control *a,
0158   const struct _Futex_Control *b
0159 )
0160 {
0161   return eq_tq(&a->_Queue, &b->_Queue);
0162 }
0163 
0164 static void test_initialization(test_context *ctx)
0165 {
0166   struct _Mutex_Control mtx = _MUTEX_INITIALIZER;
0167   struct _Mutex_recursive_Control rec_mtx = _MUTEX_RECURSIVE_INITIALIZER;
0168   struct _Condition_Control cond = _CONDITION_INITIALIZER;
0169   struct _Semaphore_Control sem = _SEMAPHORE_INITIALIZER(1);
0170   struct _Futex_Control futex = _FUTEX_INITIALIZER;
0171 
0172   _Mutex_Initialize(&ctx->mtx);
0173   _Mutex_recursive_Initialize(&ctx->rec_mtx);
0174   _Condition_Initialize(&ctx->cond);
0175   _Semaphore_Initialize(&ctx->sem, 1);
0176   _Futex_Initialize(&ctx->futex);
0177 
0178   rtems_test_assert(eq_mtx(&mtx, &ctx->mtx));
0179   rtems_test_assert(eq_rec_mtx(&rec_mtx, &ctx->rec_mtx));
0180   rtems_test_assert(eq_cond(&cond, &ctx->cond));
0181   rtems_test_assert(eq_sem(&sem, &ctx->sem));
0182   rtems_test_assert(eq_futex(&futex, &ctx->futex));
0183 
0184   _Mutex_Destroy(&mtx);
0185   _Mutex_recursive_Destroy(&rec_mtx);
0186   _Condition_Destroy(&cond);
0187   _Semaphore_Destroy(&sem);
0188   _Futex_Destroy(&futex);
0189 }
0190 
0191 static void test_recursive_acquire_normal(test_context *ctx)
0192 {
0193   struct _Mutex_Control *mtx = &ctx->mtx;
0194   size_t idx = 0;
0195   int eno;
0196 
0197   eno = _Mutex_Try_acquire(mtx);
0198   rtems_test_assert(eno == 0);
0199 
0200   eno = _Mutex_Try_acquire(mtx);
0201   rtems_test_assert(eno == EBUSY);
0202 
0203   _Mutex_Release(mtx);
0204 
0205   eno = _Mutex_Try_acquire(mtx);
0206   rtems_test_assert(eno == 0);
0207 
0208   _Mutex_Release(mtx);
0209 
0210   _Mutex_Acquire(mtx);
0211 
0212   eno = _Mutex_Try_acquire(mtx);
0213   rtems_test_assert(eno == EBUSY);
0214 
0215   _Mutex_Release(mtx);
0216 
0217   send_event(ctx, idx, EVENT_MTX_ACQUIRE);
0218 
0219   eno = _Mutex_Try_acquire(mtx);
0220   rtems_test_assert(eno == EBUSY);
0221 
0222   send_event(ctx, idx, EVENT_MTX_RELEASE);
0223 }
0224 
0225 static void test_recursive_acquire_recursive(test_context *ctx)
0226 {
0227   struct _Mutex_recursive_Control *mtx = &ctx->rec_mtx;
0228   size_t idx = 0;
0229   int eno;
0230 
0231   eno = _Mutex_recursive_Try_acquire(mtx);
0232   rtems_test_assert(eno == 0);
0233 
0234   _Mutex_recursive_Acquire(mtx);
0235 
0236   eno = _Mutex_recursive_Try_acquire(mtx);
0237   rtems_test_assert(eno == 0);
0238 
0239   _Mutex_recursive_Release(mtx);
0240   _Mutex_recursive_Release(mtx);
0241   _Mutex_recursive_Release(mtx);
0242 
0243   send_event(ctx, idx, EVENT_REC_MTX_ACQUIRE);
0244 
0245   eno = _Mutex_recursive_Try_acquire(mtx);
0246   rtems_test_assert(eno == EBUSY);
0247 
0248   send_event(ctx, idx, EVENT_REC_MTX_RELEASE);
0249 }
0250 
0251 static void test_prio_acquire_order(test_context *ctx)
0252 {
0253   struct _Mutex_Control *mtx = &ctx->mtx;
0254   size_t a = 0;
0255   size_t b = 1;
0256   int gen_a;
0257   int gen_b;
0258 
0259   _Mutex_Acquire(mtx);
0260 
0261   gen_a = ctx->generation[a];
0262   gen_b = ctx->generation[b];
0263 
0264   send_event(ctx, b, EVENT_MTX_ACQUIRE);
0265   send_event(ctx, a, EVENT_MTX_ACQUIRE);
0266 
0267   rtems_test_assert(ctx->generation[a] == gen_a);
0268   rtems_test_assert(ctx->generation[b] == gen_b);
0269 
0270   _Mutex_Release(mtx);
0271 
0272   rtems_test_assert(ctx->generation[a] == gen_a + 1);
0273   rtems_test_assert(ctx->generation[b] == gen_b);
0274 
0275   send_event(ctx, a, EVENT_MTX_RELEASE);
0276 
0277   rtems_test_assert(ctx->generation[a] == gen_a + 1);
0278   rtems_test_assert(ctx->generation[b] == gen_b + 1);
0279 
0280   send_event(ctx, b, EVENT_MTX_RELEASE);
0281 }
0282 
0283 static void test_prio_inv_normal(test_context *ctx)
0284 {
0285   struct _Mutex_Control *mtx = &ctx->mtx;
0286   size_t idx = 0;
0287   int gen;
0288 
0289   _Mutex_Acquire(mtx);
0290   gen = ctx->generation[idx];
0291   send_event(ctx, idx, EVENT_MTX_PRIO_INV);
0292   rtems_test_assert(ctx->generation[idx] == gen);
0293   _Mutex_Release(mtx);
0294   rtems_test_assert(ctx->generation[idx] == gen + 1);
0295 }
0296 
0297 static void test_prio_inv_recursive(test_context *ctx)
0298 {
0299   struct _Mutex_recursive_Control *mtx = &ctx->rec_mtx;
0300   size_t idx = 0;
0301   int gen;
0302 
0303   _Mutex_recursive_Acquire(mtx);
0304   gen = ctx->generation[idx];
0305   send_event(ctx, idx, EVENT_REC_MTX_PRIO_INV);
0306   rtems_test_assert(ctx->generation[idx] == gen);
0307   _Mutex_recursive_Release(mtx);
0308   rtems_test_assert(ctx->generation[idx] == gen + 1);
0309 }
0310 
0311 static void test_mtx_timeout_normal(test_context *ctx)
0312 {
0313   struct _Mutex_Control *mtx = &ctx->mtx;
0314   size_t idx = 0;
0315   struct timespec to;
0316   int eno;
0317 
0318   eno = _Mutex_Acquire_timed(mtx, NULL);
0319   rtems_test_assert(eno == 0);
0320   _Mutex_Release(mtx);
0321 
0322   send_event(ctx, idx, EVENT_MTX_ACQUIRE);
0323 
0324   memset(&to, 0x00, sizeof(to));
0325   eno = _Mutex_Acquire_timed(mtx, &to);
0326   rtems_test_assert(eno == ETIMEDOUT);
0327   memset(&to, 0xff, sizeof(to));
0328   eno = _Mutex_Acquire_timed(mtx, &to);
0329   rtems_test_assert(eno == EINVAL);
0330   get_abs_timeout(&to);
0331   eno = _Mutex_Acquire_timed(mtx, &to);
0332   rtems_test_assert(eno == ETIMEDOUT);
0333 
0334   send_event(ctx, idx, EVENT_MTX_RELEASE);
0335 }
0336 
0337 static void test_mtx_timeout_recursive(test_context *ctx)
0338 {
0339   struct _Mutex_recursive_Control *mtx = &ctx->rec_mtx;
0340   size_t idx = 0;
0341   struct timespec to;
0342   int eno;
0343 
0344   eno = _Mutex_recursive_Acquire_timed(mtx, NULL);
0345   rtems_test_assert(eno == 0);
0346   eno = _Mutex_recursive_Acquire_timed(mtx, NULL);
0347   rtems_test_assert(eno == 0);
0348   _Mutex_recursive_Release(mtx);
0349   _Mutex_recursive_Release(mtx);
0350 
0351   send_event(ctx, idx, EVENT_REC_MTX_ACQUIRE);
0352 
0353   memset(&to, 0x00, sizeof(to));
0354   eno = _Mutex_recursive_Acquire_timed(mtx, &to);
0355   rtems_test_assert(eno == ETIMEDOUT);
0356   memset(&to, 0xff, sizeof(to));
0357   eno = _Mutex_recursive_Acquire_timed(mtx, &to);
0358   rtems_test_assert(eno == EINVAL);
0359   get_abs_timeout(&to);
0360   eno = _Mutex_recursive_Acquire_timed(mtx, &to);
0361   rtems_test_assert(eno == ETIMEDOUT);
0362 
0363   send_event(ctx, idx, EVENT_REC_MTX_RELEASE);
0364 }
0365 
0366 static void test_mtx_deadlock(test_context *ctx)
0367 {
0368   struct _Mutex_Control *mtx = &ctx->mtx;
0369 
0370   _Mutex_Acquire(mtx);
0371 
0372   if (setjmp(ctx->deadlock_return_context) == 0) {
0373     _Mutex_Acquire(mtx);
0374   }
0375 
0376   _Mutex_Release(mtx);
0377 }
0378 
0379 static void test_condition(test_context *ctx)
0380 {
0381   struct _Condition_Control *cond = &ctx->cond;
0382   size_t a = 0;
0383   size_t b = 1;
0384   int gen_a;
0385   int gen_b;
0386 
0387   gen_a = ctx->generation[a];
0388   gen_b = ctx->generation[b];
0389 
0390   _Condition_Signal(cond);
0391   _Condition_Broadcast(cond);
0392 
0393   send_event(ctx, a, EVENT_CONDITION_WAIT);
0394   send_event(ctx, b, EVENT_CONDITION_WAIT_REC);
0395 
0396   rtems_test_assert(ctx->generation[a] == gen_a + 1);
0397   rtems_test_assert(ctx->generation[b] == gen_b + 1);
0398 
0399   _Condition_Signal(cond);
0400 
0401   rtems_test_assert(ctx->generation[a] == gen_a + 2);
0402   rtems_test_assert(ctx->generation[b] == gen_b + 1);
0403 
0404   _Condition_Signal(cond);
0405 
0406   rtems_test_assert(ctx->generation[a] == gen_a + 2);
0407   rtems_test_assert(ctx->generation[b] == gen_b + 2);
0408 
0409   send_event(ctx, a, EVENT_CONDITION_WAIT);
0410   send_event(ctx, b, EVENT_CONDITION_WAIT_REC);
0411 
0412   rtems_test_assert(ctx->generation[a] == gen_a + 3);
0413   rtems_test_assert(ctx->generation[b] == gen_b + 3);
0414 
0415   _Condition_Broadcast(cond);
0416 
0417   rtems_test_assert(ctx->generation[a] == gen_a + 4);
0418   rtems_test_assert(ctx->generation[b] == gen_b + 4);
0419 }
0420 
0421 static void test_condition_timeout(test_context *ctx)
0422 {
0423   struct timespec to;
0424   int eno;
0425 
0426   _Mutex_Acquire(&ctx->mtx);
0427   memset(&to, 0x00, sizeof(to));
0428   eno = _Condition_Wait_timed(&ctx->cond, &ctx->mtx, &to);
0429   rtems_test_assert(eno == ETIMEDOUT);
0430   memset(&to, 0xff, sizeof(to));
0431   eno = _Condition_Wait_timed(&ctx->cond, &ctx->mtx, &to);
0432   rtems_test_assert(eno == EINVAL);
0433   get_abs_timeout(&to);
0434   eno = _Condition_Wait_timed(&ctx->cond, &ctx->mtx, &to);
0435   rtems_test_assert(eno == ETIMEDOUT);
0436   _Mutex_Release(&ctx->mtx);
0437 
0438   _Mutex_recursive_Acquire(&ctx->rec_mtx);
0439   _Mutex_recursive_Acquire(&ctx->rec_mtx);
0440   memset(&to, 0x00, sizeof(to));
0441   eno = _Condition_Wait_recursive_timed(&ctx->cond, &ctx->rec_mtx, &to);
0442   rtems_test_assert(eno == ETIMEDOUT);
0443   memset(&to, 0xff, sizeof(to));
0444   eno = _Condition_Wait_recursive_timed(&ctx->cond, &ctx->rec_mtx, &to);
0445   rtems_test_assert(eno == EINVAL);
0446   get_abs_timeout(&to);
0447   eno = _Condition_Wait_recursive_timed(&ctx->cond, &ctx->rec_mtx, &to);
0448   rtems_test_assert(eno == ETIMEDOUT);
0449   _Mutex_recursive_Release(&ctx->rec_mtx);
0450   _Mutex_recursive_Release(&ctx->rec_mtx);
0451 }
0452 
0453 static void test_sem(test_context *ctx)
0454 {
0455   struct _Semaphore_Control *sem = &ctx->sem;
0456   size_t idx = 0;
0457   int gen;
0458 
0459   _Semaphore_Wait(sem);
0460   gen = ctx->generation[idx];
0461   send_event(ctx, idx, EVENT_SEM_WAIT);
0462   rtems_test_assert(ctx->generation[idx] == gen);
0463   _Semaphore_Post(sem);
0464   rtems_test_assert(ctx->generation[idx] == gen + 1);
0465   _Semaphore_Post(sem);
0466 }
0467 
0468 static void test_sem_prio_wait_order(test_context *ctx)
0469 {
0470   struct _Semaphore_Control *sem = &ctx->sem;
0471   size_t a = 0;
0472   size_t b = 1;
0473   int gen_a;
0474   int gen_b;
0475 
0476   _Semaphore_Wait(sem);
0477 
0478   gen_a = ctx->generation[a];
0479   gen_b = ctx->generation[b];
0480 
0481   send_event(ctx, b, EVENT_SEM_WAIT);
0482   send_event(ctx, a, EVENT_SEM_WAIT);
0483 
0484   rtems_test_assert(ctx->generation[a] == gen_a);
0485   rtems_test_assert(ctx->generation[b] == gen_b);
0486 
0487   _Semaphore_Post(sem);
0488 
0489   rtems_test_assert(ctx->generation[a] == gen_a + 1);
0490   rtems_test_assert(ctx->generation[b] == gen_b);
0491 
0492   _Semaphore_Post(sem);
0493 
0494   rtems_test_assert(ctx->generation[a] == gen_a + 1);
0495   rtems_test_assert(ctx->generation[b] == gen_b + 1);
0496 }
0497 
0498 static void test_futex(test_context *ctx)
0499 {
0500   struct _Futex_Control *futex = &ctx->futex;
0501   size_t a = 0;
0502   size_t b = 1;
0503   int eno;
0504   int woken;
0505 
0506   eno = _Futex_Wait(futex, &ctx->val, 1);
0507   rtems_test_assert(eno == EWOULDBLOCK);
0508 
0509   woken = _Futex_Wake(futex, 0);
0510   rtems_test_assert(woken == 0);
0511 
0512   woken = _Futex_Wake(futex, 1);
0513   rtems_test_assert(woken == 0);
0514 
0515   ctx->val = 1;
0516 
0517   ctx->eno[a] = -1;
0518   send_event(ctx, a, EVENT_FUTEX_WAIT);
0519   rtems_test_assert(ctx->eno[a] == -1);
0520 
0521   woken = _Futex_Wake(futex, INT_MAX);
0522   rtems_test_assert(woken == 1);
0523   rtems_test_assert(ctx->eno[a] == 0);
0524 
0525   ctx->eno[a] = -1;
0526   ctx->eno[b] = -1;
0527   send_event(ctx, a, EVENT_FUTEX_WAIT);
0528   send_event(ctx, b, EVENT_FUTEX_WAIT);
0529   rtems_test_assert(ctx->eno[a] == -1);
0530   rtems_test_assert(ctx->eno[b] == -1);
0531 
0532   woken = _Futex_Wake(futex, 1);
0533   rtems_test_assert(woken == 1);
0534   rtems_test_assert(ctx->eno[a] == 0);
0535   rtems_test_assert(ctx->eno[b] == -1);
0536 
0537   woken = _Futex_Wake(futex, 1);
0538   rtems_test_assert(woken == 1);
0539   rtems_test_assert(ctx->eno[a] == 0);
0540   rtems_test_assert(ctx->eno[b] == 0);
0541 
0542   ctx->eno[a] = -1;
0543   ctx->eno[b] = -1;
0544   send_event(ctx, a, EVENT_FUTEX_WAIT);
0545   send_event(ctx, b, EVENT_FUTEX_WAIT);
0546   rtems_test_assert(ctx->eno[a] == -1);
0547   rtems_test_assert(ctx->eno[b] == -1);
0548 
0549   woken = _Futex_Wake(futex, 2);
0550   rtems_test_assert(woken == 2);
0551   rtems_test_assert(ctx->eno[a] == 0);
0552   rtems_test_assert(ctx->eno[b] == 0);
0553 }
0554 
0555 static void test_sched(void)
0556 {
0557   rtems_test_assert(_Sched_Index() == 0);
0558   rtems_test_assert(_Sched_Name_to_index("", 0) == -1);
0559   rtems_test_assert(_Sched_Name_to_index("b", 1) == -1);
0560   rtems_test_assert(_Sched_Name_to_index("bl", 2) == -1);
0561   rtems_test_assert(_Sched_Name_to_index("blu", 3) == -1);
0562   rtems_test_assert(_Sched_Name_to_index("blue", 4) == 0);
0563   rtems_test_assert(_Sched_Name_to_index("blueX", 5) == 0);
0564   rtems_test_assert(_Sched_Processor_count(-1) == 0);
0565   rtems_test_assert(_Sched_Processor_count(0) == 1);
0566   rtems_test_assert(_Sched_Processor_count(1) == 0);
0567 }
0568 
0569 static void mid_task(rtems_task_argument arg)
0570 {
0571   rtems_test_assert(0);
0572 }
0573 
0574 static void high_task(rtems_task_argument idx)
0575 {
0576   test_context *ctx = &test_instance;
0577   rtems_status_code sc;
0578 
0579   if (idx == 0) {
0580     sc = rtems_task_start(ctx->mid, mid_task, 0);
0581     rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0582 
0583     sc = rtems_task_suspend(ctx->mid);
0584     rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0585   }
0586 
0587   while (true) {
0588     rtems_event_set events;
0589 
0590     sc = rtems_event_receive(
0591       RTEMS_ALL_EVENTS,
0592       RTEMS_EVENT_ANY | RTEMS_WAIT,
0593       RTEMS_NO_TIMEOUT,
0594       &events
0595     );
0596     rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0597 
0598     if ((events & EVENT_MTX_ACQUIRE) != 0) {
0599       _Mutex_Acquire(&ctx->mtx);
0600       ctx->generation[idx] = generation(ctx, idx);
0601     }
0602 
0603     if ((events & EVENT_MTX_RELEASE) != 0) {
0604       _Mutex_Release(&ctx->mtx);
0605     }
0606 
0607     if ((events & EVENT_MTX_PRIO_INV) != 0) {
0608       sc = rtems_task_resume(ctx->mid);
0609       rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0610 
0611       _Mutex_Acquire(&ctx->mtx);
0612       ctx->generation[idx] = generation(ctx, idx);
0613       _Mutex_Release(&ctx->mtx);
0614 
0615       sc = rtems_task_suspend(ctx->mid);
0616       rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0617     }
0618 
0619     if ((events & EVENT_REC_MTX_ACQUIRE) != 0) {
0620       _Mutex_recursive_Acquire(&ctx->rec_mtx);
0621     }
0622 
0623     if ((events & EVENT_REC_MTX_RELEASE) != 0) {
0624       _Mutex_recursive_Release(&ctx->rec_mtx);
0625     }
0626 
0627     if ((events & EVENT_REC_MTX_PRIO_INV) != 0) {
0628       sc = rtems_task_resume(ctx->mid);
0629       rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0630 
0631       _Mutex_recursive_Acquire(&ctx->rec_mtx);
0632       ctx->generation[idx] = generation(ctx, idx);
0633       _Mutex_recursive_Release(&ctx->rec_mtx);
0634 
0635       sc = rtems_task_suspend(ctx->mid);
0636       rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0637     }
0638 
0639     if ((events & EVENT_SEM_WAIT) != 0) {
0640       _Semaphore_Wait(&ctx->sem);
0641       ctx->generation[idx] = generation(ctx, idx);
0642     }
0643 
0644     if ((events & EVENT_FUTEX_WAIT) != 0) {
0645       ctx->eno[idx] = _Futex_Wait(&ctx->futex, &ctx->val, 1);
0646     }
0647 
0648     if ((events & EVENT_CONDITION_WAIT) != 0) {
0649       _Mutex_Acquire(&ctx->mtx);
0650       ctx->generation[idx] = generation(ctx, idx);
0651       _Condition_Wait(&ctx->cond, &ctx->mtx);
0652       ctx->generation[idx] = generation(ctx, idx);
0653       _Mutex_Release(&ctx->mtx);
0654     }
0655 
0656     if ((events & EVENT_CONDITION_WAIT_REC) != 0) {
0657       _Mutex_recursive_Acquire(&ctx->rec_mtx);
0658       _Mutex_recursive_Acquire(&ctx->rec_mtx);
0659       ctx->generation[idx] = generation(ctx, idx);
0660       _Condition_Wait_recursive(&ctx->cond, &ctx->rec_mtx);
0661       ctx->generation[idx] = generation(ctx, idx);
0662       _Mutex_recursive_Release(&ctx->rec_mtx);
0663       _Mutex_recursive_Release(&ctx->rec_mtx);
0664     }
0665   }
0666 }
0667 
0668 static void test(void)
0669 {
0670   test_context *ctx = &test_instance;
0671   rtems_status_code sc;
0672 
0673   test_initialization(ctx);
0674 
0675   ctx->low = rtems_task_self();
0676 
0677   sc = rtems_task_create(
0678     rtems_build_name('M', 'I', 'D', ' '),
0679     3,
0680     RTEMS_MINIMUM_STACK_SIZE,
0681     RTEMS_DEFAULT_MODES,
0682     RTEMS_DEFAULT_ATTRIBUTES,
0683     &ctx->mid
0684   );
0685   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0686 
0687   sc = rtems_task_create(
0688     rtems_build_name('H', 'I', 'G', '0'),
0689     1,
0690     RTEMS_MINIMUM_STACK_SIZE,
0691     RTEMS_DEFAULT_MODES,
0692     RTEMS_DEFAULT_ATTRIBUTES,
0693     &ctx->high[0]
0694   );
0695   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0696 
0697   sc = rtems_task_start(ctx->high[0], high_task, 0);
0698   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0699 
0700   sc = rtems_task_create(
0701     rtems_build_name('H', 'I', 'G', '1'),
0702     2,
0703     RTEMS_MINIMUM_STACK_SIZE,
0704     RTEMS_DEFAULT_MODES,
0705     RTEMS_DEFAULT_ATTRIBUTES,
0706     &ctx->high[1]
0707   );
0708   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0709 
0710   sc = rtems_task_start(ctx->high[1], high_task, 1);
0711   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0712 
0713   test_recursive_acquire_normal(ctx);
0714   test_recursive_acquire_recursive(ctx);
0715   test_prio_acquire_order(ctx);
0716   test_prio_inv_normal(ctx);
0717   test_prio_inv_recursive(ctx);
0718   test_mtx_timeout_normal(ctx);
0719   test_mtx_timeout_recursive(ctx);
0720   test_mtx_deadlock(ctx);
0721   test_condition(ctx);
0722   test_condition_timeout(ctx);
0723   test_sem(ctx);
0724   test_sem_prio_wait_order(ctx);
0725   test_futex(ctx);
0726   test_sched();
0727 
0728   sc = rtems_task_delete(ctx->mid);
0729   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0730 
0731   sc = rtems_task_delete(ctx->high[0]);
0732   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0733 
0734   sc = rtems_task_delete(ctx->high[1]);
0735   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0736 
0737   _Mutex_Destroy(&ctx->mtx);
0738   _Mutex_recursive_Destroy(&ctx->rec_mtx);
0739   _Condition_Destroy(&ctx->cond);
0740   _Semaphore_Destroy(&ctx->sem);
0741   _Futex_Destroy(&ctx->futex);
0742 }
0743 
0744 static void Init(rtems_task_argument arg)
0745 {
0746   TEST_BEGIN();
0747 
0748   test();
0749 
0750   TEST_END();
0751   rtems_test_exit(0);
0752 }
0753 
0754 static void fatal_extension(
0755   rtems_fatal_source source,
0756   bool always_set_to_false,
0757   rtems_fatal_code error
0758 )
0759 {
0760 
0761   if (
0762     source == INTERNAL_ERROR_CORE
0763       && !always_set_to_false
0764       && error == INTERNAL_ERROR_THREAD_QUEUE_DEADLOCK
0765   ) {
0766     test_context *ctx = &test_instance;
0767 
0768     _ISR_Set_level(0);
0769     longjmp(ctx->deadlock_return_context, 1);
0770   }
0771 }
0772 
0773 #define CONFIGURE_MICROSECONDS_PER_TICK US_PER_TICK
0774 
0775 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
0776 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
0777 
0778 #define CONFIGURE_MAXIMUM_TASKS 4
0779 
0780 #define CONFIGURE_INITIAL_EXTENSIONS \
0781   { .fatal = fatal_extension }, \
0782   RTEMS_TEST_INITIAL_EXTENSION
0783 
0784 #define CONFIGURE_INIT_TASK_PRIORITY 4
0785 #define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES
0786 
0787 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
0788 
0789 #define CONFIGURE_SCHEDULER_NAME rtems_build_name('b', 'l', 'u', 'e')
0790 
0791 #define CONFIGURE_INIT
0792 
0793 #include <rtems/confdefs.h>