/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015, 2016 embedded brains GmbH. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "tmacros.h" #include #include #include #include #include #include const char rtems_test_name[] = "SPSYSLOCK 1"; #define US_PER_TICK 10000 #define EVENT_MTX_ACQUIRE RTEMS_EVENT_0 #define EVENT_MTX_RELEASE RTEMS_EVENT_1 #define EVENT_MTX_PRIO_INV RTEMS_EVENT_2 #define EVENT_REC_MTX_ACQUIRE RTEMS_EVENT_4 #define EVENT_REC_MTX_RELEASE RTEMS_EVENT_5 #define EVENT_REC_MTX_PRIO_INV RTEMS_EVENT_6 #define EVENT_SEM_WAIT RTEMS_EVENT_7 #define EVENT_FUTEX_WAIT RTEMS_EVENT_8 #define EVENT_CONDITION_WAIT RTEMS_EVENT_9 #define EVENT_CONDITION_WAIT_REC RTEMS_EVENT_10 typedef struct { rtems_id high[2]; rtems_id mid; rtems_id low; struct _Mutex_Control mtx; struct _Mutex_recursive_Control rec_mtx; struct _Condition_Control cond; struct _Semaphore_Control sem; struct _Futex_Control futex; int val; int eno[2]; int generation[2]; int current_generation[2]; jmp_buf deadlock_return_context; } test_context; static test_context test_instance; static int generation(test_context *ctx, size_t idx) { return ++ctx->current_generation[idx]; } static void send_event(test_context *ctx, size_t idx, rtems_event_set events) { rtems_status_code sc; sc = rtems_event_send(ctx->high[idx], events); rtems_test_assert(sc == RTEMS_SUCCESSFUL); } static void get_abs_timeout(struct timespec *to) { int rv; rv = clock_gettime(CLOCK_REALTIME, to); rtems_test_assert(rv == 0); to->tv_nsec += 2 * US_PER_TICK * 1000; if (to->tv_nsec >= 1000000000) { ++to->tv_sec; to->tv_nsec -= 1000000000; } } static bool eq_tq( const struct _Thread_queue_Queue *a, const struct _Thread_queue_Queue *b ) { return a->_Lock._next_ticket == b->_Lock._next_ticket && a->_Lock._now_serving == b->_Lock._now_serving && a->_heads == b->_heads && a->_owner == b->_owner && a->_name == b->_name; } static bool eq_mtx( const struct _Mutex_Control *a, const struct _Mutex_Control *b ) { return eq_tq(&a->_Queue, &b->_Queue); } static bool eq_rec_mtx( const struct _Mutex_recursive_Control *a, const struct _Mutex_recursive_Control *b ) { return eq_mtx(&a->_Mutex, &b->_Mutex) && a->_nest_level == b->_nest_level; } static bool eq_cond( const struct _Condition_Control *a, const struct _Condition_Control *b ) { return eq_tq(&a->_Queue, &b->_Queue); } static bool eq_sem( const struct _Semaphore_Control *a, const struct _Semaphore_Control *b ) { return eq_tq(&a->_Queue, &b->_Queue) && a->_count == b->_count; } static bool eq_futex( const struct _Futex_Control *a, const struct _Futex_Control *b ) { return eq_tq(&a->_Queue, &b->_Queue); } static void test_initialization(test_context *ctx) { struct _Mutex_Control mtx = _MUTEX_INITIALIZER; struct _Mutex_recursive_Control rec_mtx = _MUTEX_RECURSIVE_INITIALIZER; struct _Condition_Control cond = _CONDITION_INITIALIZER; struct _Semaphore_Control sem = _SEMAPHORE_INITIALIZER(1); struct _Futex_Control futex = _FUTEX_INITIALIZER; _Mutex_Initialize(&ctx->mtx); _Mutex_recursive_Initialize(&ctx->rec_mtx); _Condition_Initialize(&ctx->cond); _Semaphore_Initialize(&ctx->sem, 1); _Futex_Initialize(&ctx->futex); rtems_test_assert(eq_mtx(&mtx, &ctx->mtx)); rtems_test_assert(eq_rec_mtx(&rec_mtx, &ctx->rec_mtx)); rtems_test_assert(eq_cond(&cond, &ctx->cond)); rtems_test_assert(eq_sem(&sem, &ctx->sem)); rtems_test_assert(eq_futex(&futex, &ctx->futex)); _Mutex_Destroy(&mtx); _Mutex_recursive_Destroy(&rec_mtx); _Condition_Destroy(&cond); _Semaphore_Destroy(&sem); _Futex_Destroy(&futex); } static void test_recursive_acquire_normal(test_context *ctx) { struct _Mutex_Control *mtx = &ctx->mtx; size_t idx = 0; int eno; eno = _Mutex_Try_acquire(mtx); rtems_test_assert(eno == 0); eno = _Mutex_Try_acquire(mtx); rtems_test_assert(eno == EBUSY); _Mutex_Release(mtx); eno = _Mutex_Try_acquire(mtx); rtems_test_assert(eno == 0); _Mutex_Release(mtx); _Mutex_Acquire(mtx); eno = _Mutex_Try_acquire(mtx); rtems_test_assert(eno == EBUSY); _Mutex_Release(mtx); send_event(ctx, idx, EVENT_MTX_ACQUIRE); eno = _Mutex_Try_acquire(mtx); rtems_test_assert(eno == EBUSY); send_event(ctx, idx, EVENT_MTX_RELEASE); } static void test_recursive_acquire_recursive(test_context *ctx) { struct _Mutex_recursive_Control *mtx = &ctx->rec_mtx; size_t idx = 0; int eno; eno = _Mutex_recursive_Try_acquire(mtx); rtems_test_assert(eno == 0); _Mutex_recursive_Acquire(mtx); eno = _Mutex_recursive_Try_acquire(mtx); rtems_test_assert(eno == 0); _Mutex_recursive_Release(mtx); _Mutex_recursive_Release(mtx); _Mutex_recursive_Release(mtx); send_event(ctx, idx, EVENT_REC_MTX_ACQUIRE); eno = _Mutex_recursive_Try_acquire(mtx); rtems_test_assert(eno == EBUSY); send_event(ctx, idx, EVENT_REC_MTX_RELEASE); } static void test_prio_acquire_order(test_context *ctx) { struct _Mutex_Control *mtx = &ctx->mtx; size_t a = 0; size_t b = 1; int gen_a; int gen_b; _Mutex_Acquire(mtx); gen_a = ctx->generation[a]; gen_b = ctx->generation[b]; send_event(ctx, b, EVENT_MTX_ACQUIRE); send_event(ctx, a, EVENT_MTX_ACQUIRE); rtems_test_assert(ctx->generation[a] == gen_a); rtems_test_assert(ctx->generation[b] == gen_b); _Mutex_Release(mtx); rtems_test_assert(ctx->generation[a] == gen_a + 1); rtems_test_assert(ctx->generation[b] == gen_b); send_event(ctx, a, EVENT_MTX_RELEASE); rtems_test_assert(ctx->generation[a] == gen_a + 1); rtems_test_assert(ctx->generation[b] == gen_b + 1); send_event(ctx, b, EVENT_MTX_RELEASE); } static void test_prio_inv_normal(test_context *ctx) { struct _Mutex_Control *mtx = &ctx->mtx; size_t idx = 0; int gen; _Mutex_Acquire(mtx); gen = ctx->generation[idx]; send_event(ctx, idx, EVENT_MTX_PRIO_INV); rtems_test_assert(ctx->generation[idx] == gen); _Mutex_Release(mtx); rtems_test_assert(ctx->generation[idx] == gen + 1); } static void test_prio_inv_recursive(test_context *ctx) { struct _Mutex_recursive_Control *mtx = &ctx->rec_mtx; size_t idx = 0; int gen; _Mutex_recursive_Acquire(mtx); gen = ctx->generation[idx]; send_event(ctx, idx, EVENT_REC_MTX_PRIO_INV); rtems_test_assert(ctx->generation[idx] == gen); _Mutex_recursive_Release(mtx); rtems_test_assert(ctx->generation[idx] == gen + 1); } static void test_mtx_timeout_normal(test_context *ctx) { struct _Mutex_Control *mtx = &ctx->mtx; size_t idx = 0; struct timespec to; int eno; eno = _Mutex_Acquire_timed(mtx, NULL); rtems_test_assert(eno == 0); _Mutex_Release(mtx); send_event(ctx, idx, EVENT_MTX_ACQUIRE); memset(&to, 0x00, sizeof(to)); eno = _Mutex_Acquire_timed(mtx, &to); rtems_test_assert(eno == ETIMEDOUT); memset(&to, 0xff, sizeof(to)); eno = _Mutex_Acquire_timed(mtx, &to); rtems_test_assert(eno == EINVAL); get_abs_timeout(&to); eno = _Mutex_Acquire_timed(mtx, &to); rtems_test_assert(eno == ETIMEDOUT); send_event(ctx, idx, EVENT_MTX_RELEASE); } static void test_mtx_timeout_recursive(test_context *ctx) { struct _Mutex_recursive_Control *mtx = &ctx->rec_mtx; size_t idx = 0; struct timespec to; int eno; eno = _Mutex_recursive_Acquire_timed(mtx, NULL); rtems_test_assert(eno == 0); eno = _Mutex_recursive_Acquire_timed(mtx, NULL); rtems_test_assert(eno == 0); _Mutex_recursive_Release(mtx); _Mutex_recursive_Release(mtx); send_event(ctx, idx, EVENT_REC_MTX_ACQUIRE); memset(&to, 0x00, sizeof(to)); eno = _Mutex_recursive_Acquire_timed(mtx, &to); rtems_test_assert(eno == ETIMEDOUT); memset(&to, 0xff, sizeof(to)); eno = _Mutex_recursive_Acquire_timed(mtx, &to); rtems_test_assert(eno == EINVAL); get_abs_timeout(&to); eno = _Mutex_recursive_Acquire_timed(mtx, &to); rtems_test_assert(eno == ETIMEDOUT); send_event(ctx, idx, EVENT_REC_MTX_RELEASE); } static void test_mtx_deadlock(test_context *ctx) { struct _Mutex_Control *mtx = &ctx->mtx; _Mutex_Acquire(mtx); if (setjmp(ctx->deadlock_return_context) == 0) { _Mutex_Acquire(mtx); } _Mutex_Release(mtx); } static void test_condition(test_context *ctx) { struct _Condition_Control *cond = &ctx->cond; size_t a = 0; size_t b = 1; int gen_a; int gen_b; gen_a = ctx->generation[a]; gen_b = ctx->generation[b]; _Condition_Signal(cond); _Condition_Broadcast(cond); send_event(ctx, a, EVENT_CONDITION_WAIT); send_event(ctx, b, EVENT_CONDITION_WAIT_REC); rtems_test_assert(ctx->generation[a] == gen_a + 1); rtems_test_assert(ctx->generation[b] == gen_b + 1); _Condition_Signal(cond); rtems_test_assert(ctx->generation[a] == gen_a + 2); rtems_test_assert(ctx->generation[b] == gen_b + 1); _Condition_Signal(cond); rtems_test_assert(ctx->generation[a] == gen_a + 2); rtems_test_assert(ctx->generation[b] == gen_b + 2); send_event(ctx, a, EVENT_CONDITION_WAIT); send_event(ctx, b, EVENT_CONDITION_WAIT_REC); rtems_test_assert(ctx->generation[a] == gen_a + 3); rtems_test_assert(ctx->generation[b] == gen_b + 3); _Condition_Broadcast(cond); rtems_test_assert(ctx->generation[a] == gen_a + 4); rtems_test_assert(ctx->generation[b] == gen_b + 4); } static void test_condition_timeout(test_context *ctx) { struct timespec to; int eno; _Mutex_Acquire(&ctx->mtx); memset(&to, 0x00, sizeof(to)); eno = _Condition_Wait_timed(&ctx->cond, &ctx->mtx, &to); rtems_test_assert(eno == ETIMEDOUT); memset(&to, 0xff, sizeof(to)); eno = _Condition_Wait_timed(&ctx->cond, &ctx->mtx, &to); rtems_test_assert(eno == EINVAL); get_abs_timeout(&to); eno = _Condition_Wait_timed(&ctx->cond, &ctx->mtx, &to); rtems_test_assert(eno == ETIMEDOUT); _Mutex_Release(&ctx->mtx); _Mutex_recursive_Acquire(&ctx->rec_mtx); _Mutex_recursive_Acquire(&ctx->rec_mtx); memset(&to, 0x00, sizeof(to)); eno = _Condition_Wait_recursive_timed(&ctx->cond, &ctx->rec_mtx, &to); rtems_test_assert(eno == ETIMEDOUT); memset(&to, 0xff, sizeof(to)); eno = _Condition_Wait_recursive_timed(&ctx->cond, &ctx->rec_mtx, &to); rtems_test_assert(eno == EINVAL); get_abs_timeout(&to); eno = _Condition_Wait_recursive_timed(&ctx->cond, &ctx->rec_mtx, &to); rtems_test_assert(eno == ETIMEDOUT); _Mutex_recursive_Release(&ctx->rec_mtx); _Mutex_recursive_Release(&ctx->rec_mtx); } static void test_sem(test_context *ctx) { struct _Semaphore_Control *sem = &ctx->sem; size_t idx = 0; int gen; _Semaphore_Wait(sem); gen = ctx->generation[idx]; send_event(ctx, idx, EVENT_SEM_WAIT); rtems_test_assert(ctx->generation[idx] == gen); _Semaphore_Post(sem); rtems_test_assert(ctx->generation[idx] == gen + 1); _Semaphore_Post(sem); } static void test_sem_prio_wait_order(test_context *ctx) { struct _Semaphore_Control *sem = &ctx->sem; size_t a = 0; size_t b = 1; int gen_a; int gen_b; _Semaphore_Wait(sem); gen_a = ctx->generation[a]; gen_b = ctx->generation[b]; send_event(ctx, b, EVENT_SEM_WAIT); send_event(ctx, a, EVENT_SEM_WAIT); rtems_test_assert(ctx->generation[a] == gen_a); rtems_test_assert(ctx->generation[b] == gen_b); _Semaphore_Post(sem); rtems_test_assert(ctx->generation[a] == gen_a + 1); rtems_test_assert(ctx->generation[b] == gen_b); _Semaphore_Post(sem); rtems_test_assert(ctx->generation[a] == gen_a + 1); rtems_test_assert(ctx->generation[b] == gen_b + 1); } static void test_futex(test_context *ctx) { struct _Futex_Control *futex = &ctx->futex; size_t a = 0; size_t b = 1; int eno; int woken; eno = _Futex_Wait(futex, &ctx->val, 1); rtems_test_assert(eno == EWOULDBLOCK); woken = _Futex_Wake(futex, 0); rtems_test_assert(woken == 0); woken = _Futex_Wake(futex, 1); rtems_test_assert(woken == 0); ctx->val = 1; ctx->eno[a] = -1; send_event(ctx, a, EVENT_FUTEX_WAIT); rtems_test_assert(ctx->eno[a] == -1); woken = _Futex_Wake(futex, INT_MAX); rtems_test_assert(woken == 1); rtems_test_assert(ctx->eno[a] == 0); ctx->eno[a] = -1; ctx->eno[b] = -1; send_event(ctx, a, EVENT_FUTEX_WAIT); send_event(ctx, b, EVENT_FUTEX_WAIT); rtems_test_assert(ctx->eno[a] == -1); rtems_test_assert(ctx->eno[b] == -1); woken = _Futex_Wake(futex, 1); rtems_test_assert(woken == 1); rtems_test_assert(ctx->eno[a] == 0); rtems_test_assert(ctx->eno[b] == -1); woken = _Futex_Wake(futex, 1); rtems_test_assert(woken == 1); rtems_test_assert(ctx->eno[a] == 0); rtems_test_assert(ctx->eno[b] == 0); ctx->eno[a] = -1; ctx->eno[b] = -1; send_event(ctx, a, EVENT_FUTEX_WAIT); send_event(ctx, b, EVENT_FUTEX_WAIT); rtems_test_assert(ctx->eno[a] == -1); rtems_test_assert(ctx->eno[b] == -1); woken = _Futex_Wake(futex, 2); rtems_test_assert(woken == 2); rtems_test_assert(ctx->eno[a] == 0); rtems_test_assert(ctx->eno[b] == 0); } static void test_sched(void) { rtems_test_assert(_Sched_Index() == 0); rtems_test_assert(_Sched_Name_to_index("", 0) == -1); rtems_test_assert(_Sched_Name_to_index("b", 1) == -1); rtems_test_assert(_Sched_Name_to_index("bl", 2) == -1); rtems_test_assert(_Sched_Name_to_index("blu", 3) == -1); rtems_test_assert(_Sched_Name_to_index("blue", 4) == 0); rtems_test_assert(_Sched_Name_to_index("blueX", 5) == 0); rtems_test_assert(_Sched_Processor_count(-1) == 0); rtems_test_assert(_Sched_Processor_count(0) == 1); rtems_test_assert(_Sched_Processor_count(1) == 0); } static void mid_task(rtems_task_argument arg) { rtems_test_assert(0); } static void high_task(rtems_task_argument idx) { test_context *ctx = &test_instance; rtems_status_code sc; if (idx == 0) { sc = rtems_task_start(ctx->mid, mid_task, 0); rtems_test_assert(sc == RTEMS_SUCCESSFUL); sc = rtems_task_suspend(ctx->mid); rtems_test_assert(sc == RTEMS_SUCCESSFUL); } while (true) { rtems_event_set events; sc = rtems_event_receive( RTEMS_ALL_EVENTS, RTEMS_EVENT_ANY | RTEMS_WAIT, RTEMS_NO_TIMEOUT, &events ); rtems_test_assert(sc == RTEMS_SUCCESSFUL); if ((events & EVENT_MTX_ACQUIRE) != 0) { _Mutex_Acquire(&ctx->mtx); ctx->generation[idx] = generation(ctx, idx); } if ((events & EVENT_MTX_RELEASE) != 0) { _Mutex_Release(&ctx->mtx); } if ((events & EVENT_MTX_PRIO_INV) != 0) { sc = rtems_task_resume(ctx->mid); rtems_test_assert(sc == RTEMS_SUCCESSFUL); _Mutex_Acquire(&ctx->mtx); ctx->generation[idx] = generation(ctx, idx); _Mutex_Release(&ctx->mtx); sc = rtems_task_suspend(ctx->mid); rtems_test_assert(sc == RTEMS_SUCCESSFUL); } if ((events & EVENT_REC_MTX_ACQUIRE) != 0) { _Mutex_recursive_Acquire(&ctx->rec_mtx); } if ((events & EVENT_REC_MTX_RELEASE) != 0) { _Mutex_recursive_Release(&ctx->rec_mtx); } if ((events & EVENT_REC_MTX_PRIO_INV) != 0) { sc = rtems_task_resume(ctx->mid); rtems_test_assert(sc == RTEMS_SUCCESSFUL); _Mutex_recursive_Acquire(&ctx->rec_mtx); ctx->generation[idx] = generation(ctx, idx); _Mutex_recursive_Release(&ctx->rec_mtx); sc = rtems_task_suspend(ctx->mid); rtems_test_assert(sc == RTEMS_SUCCESSFUL); } if ((events & EVENT_SEM_WAIT) != 0) { _Semaphore_Wait(&ctx->sem); ctx->generation[idx] = generation(ctx, idx); } if ((events & EVENT_FUTEX_WAIT) != 0) { ctx->eno[idx] = _Futex_Wait(&ctx->futex, &ctx->val, 1); } if ((events & EVENT_CONDITION_WAIT) != 0) { _Mutex_Acquire(&ctx->mtx); ctx->generation[idx] = generation(ctx, idx); _Condition_Wait(&ctx->cond, &ctx->mtx); ctx->generation[idx] = generation(ctx, idx); _Mutex_Release(&ctx->mtx); } if ((events & EVENT_CONDITION_WAIT_REC) != 0) { _Mutex_recursive_Acquire(&ctx->rec_mtx); _Mutex_recursive_Acquire(&ctx->rec_mtx); ctx->generation[idx] = generation(ctx, idx); _Condition_Wait_recursive(&ctx->cond, &ctx->rec_mtx); ctx->generation[idx] = generation(ctx, idx); _Mutex_recursive_Release(&ctx->rec_mtx); _Mutex_recursive_Release(&ctx->rec_mtx); } } } static void test(void) { test_context *ctx = &test_instance; rtems_status_code sc; test_initialization(ctx); ctx->low = rtems_task_self(); sc = rtems_task_create( rtems_build_name('M', 'I', 'D', ' '), 3, RTEMS_MINIMUM_STACK_SIZE, RTEMS_DEFAULT_MODES, RTEMS_DEFAULT_ATTRIBUTES, &ctx->mid ); rtems_test_assert(sc == RTEMS_SUCCESSFUL); sc = rtems_task_create( rtems_build_name('H', 'I', 'G', '0'), 1, RTEMS_MINIMUM_STACK_SIZE, RTEMS_DEFAULT_MODES, RTEMS_DEFAULT_ATTRIBUTES, &ctx->high[0] ); rtems_test_assert(sc == RTEMS_SUCCESSFUL); sc = rtems_task_start(ctx->high[0], high_task, 0); rtems_test_assert(sc == RTEMS_SUCCESSFUL); sc = rtems_task_create( rtems_build_name('H', 'I', 'G', '1'), 2, RTEMS_MINIMUM_STACK_SIZE, RTEMS_DEFAULT_MODES, RTEMS_DEFAULT_ATTRIBUTES, &ctx->high[1] ); rtems_test_assert(sc == RTEMS_SUCCESSFUL); sc = rtems_task_start(ctx->high[1], high_task, 1); rtems_test_assert(sc == RTEMS_SUCCESSFUL); test_recursive_acquire_normal(ctx); test_recursive_acquire_recursive(ctx); test_prio_acquire_order(ctx); test_prio_inv_normal(ctx); test_prio_inv_recursive(ctx); test_mtx_timeout_normal(ctx); test_mtx_timeout_recursive(ctx); test_mtx_deadlock(ctx); test_condition(ctx); test_condition_timeout(ctx); test_sem(ctx); test_sem_prio_wait_order(ctx); test_futex(ctx); test_sched(); sc = rtems_task_delete(ctx->mid); rtems_test_assert(sc == RTEMS_SUCCESSFUL); sc = rtems_task_delete(ctx->high[0]); rtems_test_assert(sc == RTEMS_SUCCESSFUL); sc = rtems_task_delete(ctx->high[1]); rtems_test_assert(sc == RTEMS_SUCCESSFUL); _Mutex_Destroy(&ctx->mtx); _Mutex_recursive_Destroy(&ctx->rec_mtx); _Condition_Destroy(&ctx->cond); _Semaphore_Destroy(&ctx->sem); _Futex_Destroy(&ctx->futex); } static void Init(rtems_task_argument arg) { TEST_BEGIN(); test(); TEST_END(); rtems_test_exit(0); } static void fatal_extension( rtems_fatal_source source, bool always_set_to_false, rtems_fatal_code error ) { if ( source == INTERNAL_ERROR_CORE && !always_set_to_false && error == INTERNAL_ERROR_THREAD_QUEUE_DEADLOCK ) { test_context *ctx = &test_instance; longjmp(ctx->deadlock_return_context, 1); } } #define CONFIGURE_MICROSECONDS_PER_TICK US_PER_TICK #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER #define CONFIGURE_MAXIMUM_TASKS 4 #define CONFIGURE_INITIAL_EXTENSIONS \ { .fatal = fatal_extension }, \ RTEMS_TEST_INITIAL_EXTENSION #define CONFIGURE_INIT_TASK_PRIORITY 4 #define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES #define CONFIGURE_RTEMS_INIT_TASKS_TABLE #define CONFIGURE_SCHEDULER_NAME rtems_build_name('b', 'l', 'u', 'e') #define CONFIGURE_INIT #include