diff options
Diffstat (limited to 'testsuites/validation/tc-sched-yield.c')
-rw-r--r-- | testsuites/validation/tc-sched-yield.c | 845 |
1 files changed, 845 insertions, 0 deletions
diff --git a/testsuites/validation/tc-sched-yield.c b/testsuites/validation/tc-sched-yield.c new file mode 100644 index 0000000000..057579fd1c --- /dev/null +++ b/testsuites/validation/tc-sched-yield.c @@ -0,0 +1,845 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup ScoreSchedReqYield + */ + +/* + * Copyright (C) 2021 embedded brains GmbH & Co. KG + * + * 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. + */ + +/* + * This file is part of the RTEMS quality process and was automatically + * generated. If you find something that needs to be fixed or + * worded better please post a report or patch to an RTEMS mailing list + * or raise a bug report: + * + * https://www.rtems.org/bugs.html + * + * For information on updating and regenerating please refer to the How-To + * section in the Software Requirements Engineering chapter of the + * RTEMS Software Engineering manual. The manual is provided as a part of + * a release. For development sources please refer to the online + * documentation at: + * + * https://docs.rtems.org + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems.h> +#include <rtems/test-scheduler.h> +#include <rtems/score/percpu.h> + +#include "tx-support.h" +#include "tx-thread-queue.h" + +#include <rtems/test.h> + +/** + * @defgroup ScoreSchedReqYield spec:/score/sched/req/yield + * + * @ingroup TestsuitesValidationNoClock0 + * + * @{ + */ + +typedef enum { + ScoreSchedReqYield_Pre_EligibleScheduler_Home, + ScoreSchedReqYield_Pre_EligibleScheduler_Helping, + ScoreSchedReqYield_Pre_EligibleScheduler_NA +} ScoreSchedReqYield_Pre_EligibleScheduler; + +typedef enum { + ScoreSchedReqYield_Pre_UsedScheduler_Home, + ScoreSchedReqYield_Pre_UsedScheduler_Helping, + ScoreSchedReqYield_Pre_UsedScheduler_NA +} ScoreSchedReqYield_Pre_UsedScheduler; + +typedef enum { + ScoreSchedReqYield_Pre_HomeSchedulerState_Blocked, + ScoreSchedReqYield_Pre_HomeSchedulerState_Scheduled, + ScoreSchedReqYield_Pre_HomeSchedulerState_Ready, + ScoreSchedReqYield_Pre_HomeSchedulerState_NA +} ScoreSchedReqYield_Pre_HomeSchedulerState; + +typedef enum { + ScoreSchedReqYield_Pre_Sticky_Yes, + ScoreSchedReqYield_Pre_Sticky_No, + ScoreSchedReqYield_Pre_Sticky_NA +} ScoreSchedReqYield_Pre_Sticky; + +typedef enum { + ScoreSchedReqYield_Pre_Other_Yes, + ScoreSchedReqYield_Pre_Other_No, + ScoreSchedReqYield_Pre_Other_NA +} ScoreSchedReqYield_Pre_Other; + +typedef enum { + ScoreSchedReqYield_Post_HomeSchedulerState_Blocked, + ScoreSchedReqYield_Post_HomeSchedulerState_Scheduled, + ScoreSchedReqYield_Post_HomeSchedulerState_Ready, + ScoreSchedReqYield_Post_HomeSchedulerState_Idle, + ScoreSchedReqYield_Post_HomeSchedulerState_NA +} ScoreSchedReqYield_Post_HomeSchedulerState; + +typedef enum { + ScoreSchedReqYield_Post_AskForHelp_Yes, + ScoreSchedReqYield_Post_AskForHelp_No, + ScoreSchedReqYield_Post_AskForHelp_NA +} ScoreSchedReqYield_Post_AskForHelp; + +typedef struct { + uint16_t Skip : 1; + uint16_t Pre_EligibleScheduler_NA : 1; + uint16_t Pre_UsedScheduler_NA : 1; + uint16_t Pre_HomeSchedulerState_NA : 1; + uint16_t Pre_Sticky_NA : 1; + uint16_t Pre_Other_NA : 1; + uint16_t Post_HomeSchedulerState : 3; + uint16_t Post_AskForHelp : 2; +} ScoreSchedReqYield_Entry; + +/** + * @brief Test context for spec:/score/sched/req/yield test case. + */ +typedef struct { + /** + * @brief This member contains the thread queue test context. + */ + TQContext tq_ctx; + + /** + * @brief This member contains the identifier of a sticky mutex. + */ + rtems_id sticky_mutex; + + /** + * @brief This member contains the processor index after yielding. + */ + uint32_t cpu_after_yield; + + /** + * @brief If this member is true, then the runner shall have a helping + * scheduler. + */ + bool has_helping; + + /** + * @brief If this member is true, then the runner shall use a helping + * scheduler. + */ + bool use_helping; + + /** + * @brief If this member is true, then the runner shall be ready in its home + * scheduler. + */ + bool ready; + + /** + * @brief If this member is true, then the runner shall be sticky. + */ + bool sticky; + + /** + * @brief If this member is true, then another ready task in the home + * scheduler of the runner shall be ready with an equal priority. + */ + bool other_ready; + + /** + * @brief If this member is true, then the processor zero was idle before + * yielding. + */ + bool is_idle_before_yield; + + /** + * @brief If this member is true, then the processor zero was idle after + * yielding. + */ + bool is_idle_after_yield; + + struct { + /** + * @brief This member defines the pre-condition states for the next action. + */ + size_t pcs[ 5 ]; + + /** + * @brief If this member is true, then the test action loop is executed. + */ + bool in_action_loop; + + /** + * @brief This member contains the next transition map index. + */ + size_t index; + + /** + * @brief This member contains the current transition map entry. + */ + ScoreSchedReqYield_Entry entry; + + /** + * @brief If this member is true, then the current transition variant + * should be skipped. + */ + bool skip; + } Map; +} ScoreSchedReqYield_Context; + +static ScoreSchedReqYield_Context + ScoreSchedReqYield_Instance; + +static const char * const ScoreSchedReqYield_PreDesc_EligibleScheduler[] = { + "Home", + "Helping", + "NA" +}; + +static const char * const ScoreSchedReqYield_PreDesc_UsedScheduler[] = { + "Home", + "Helping", + "NA" +}; + +static const char * const ScoreSchedReqYield_PreDesc_HomeSchedulerState[] = { + "Blocked", + "Scheduled", + "Ready", + "NA" +}; + +static const char * const ScoreSchedReqYield_PreDesc_Sticky[] = { + "Yes", + "No", + "NA" +}; + +static const char * const ScoreSchedReqYield_PreDesc_Other[] = { + "Yes", + "No", + "NA" +}; + +static const char * const * const ScoreSchedReqYield_PreDesc[] = { + ScoreSchedReqYield_PreDesc_EligibleScheduler, + ScoreSchedReqYield_PreDesc_UsedScheduler, + ScoreSchedReqYield_PreDesc_HomeSchedulerState, + ScoreSchedReqYield_PreDesc_Sticky, + ScoreSchedReqYield_PreDesc_Other, + NULL +}; + +#define COUNTER TQ_BLOCKER_A + +#define HELPER TQ_BLOCKER_B + +#define MOVER TQ_BLOCKER_C + +typedef ScoreSchedReqYield_Context Context; + +static void MoveToHelping( Context *ctx ) +{ + ctx->tq_ctx.busy_wait[ MOVER ] = true; + TQSend( &ctx->tq_ctx, MOVER, TQ_EVENT_BUSY_WAIT ); + TQWaitForEventsReceived( &ctx->tq_ctx, MOVER ); + T_eq_u32( rtems_scheduler_get_processor(), 1 ); + ctx->tq_ctx.busy_wait[ MOVER ] = false; + TQWaitForExecutionStop( &ctx->tq_ctx, MOVER ); +} + +static uint32_t GetCounter( const Context *ctx ) +{ + return TQGetWorkerCounter( &ctx->tq_ctx, COUNTER ); +} + +static void ScoreSchedReqYield_Pre_EligibleScheduler_Prepare( + ScoreSchedReqYield_Context *ctx, + ScoreSchedReqYield_Pre_EligibleScheduler state +) +{ + switch ( state ) { + case ScoreSchedReqYield_Pre_EligibleScheduler_Home: { + /* + * While the only eligible scheduler of the thread is the home scheduler. + */ + ctx->has_helping = false; + break; + } + + case ScoreSchedReqYield_Pre_EligibleScheduler_Helping: { + /* + * While the thread has at least one helping scheduler. + */ + ctx->has_helping = true; + break; + } + + case ScoreSchedReqYield_Pre_EligibleScheduler_NA: + break; + } +} + +static void ScoreSchedReqYield_Pre_UsedScheduler_Prepare( + ScoreSchedReqYield_Context *ctx, + ScoreSchedReqYield_Pre_UsedScheduler state +) +{ + switch ( state ) { + case ScoreSchedReqYield_Pre_UsedScheduler_Home: { + /* + * While the thread is scheduled on the home scheduler. + */ + ctx->use_helping = false; + break; + } + + case ScoreSchedReqYield_Pre_UsedScheduler_Helping: { + /* + * While the thread is scheduled on a helping scheduler. + */ + ctx->use_helping = true; + break; + } + + case ScoreSchedReqYield_Pre_UsedScheduler_NA: + break; + } +} + +static void ScoreSchedReqYield_Pre_HomeSchedulerState_Prepare( + ScoreSchedReqYield_Context *ctx, + ScoreSchedReqYield_Pre_HomeSchedulerState state +) +{ + switch ( state ) { + case ScoreSchedReqYield_Pre_HomeSchedulerState_Blocked: { + /* + * The thread shall be blocked in its home scheduler. + */ + ctx->ready = false; + break; + } + + case ScoreSchedReqYield_Pre_HomeSchedulerState_Scheduled: { + /* + * The thread shall be scheduled in its home scheduler. + */ + ctx->ready = false; + break; + } + + case ScoreSchedReqYield_Pre_HomeSchedulerState_Ready: { + /* + * The thread shall be ready in its home scheduler. + */ + ctx->ready = true; + break; + } + + case ScoreSchedReqYield_Pre_HomeSchedulerState_NA: + break; + } +} + +static void ScoreSchedReqYield_Pre_Sticky_Prepare( + ScoreSchedReqYield_Context *ctx, + ScoreSchedReqYield_Pre_Sticky state +) +{ + switch ( state ) { + case ScoreSchedReqYield_Pre_Sticky_Yes: { + /* + * While the thread is sticky. + */ + ctx->sticky = true; + break; + } + + case ScoreSchedReqYield_Pre_Sticky_No: { + /* + * While the thread not sticky. + */ + ctx->sticky = false; + break; + } + + case ScoreSchedReqYield_Pre_Sticky_NA: + break; + } +} + +static void ScoreSchedReqYield_Pre_Other_Prepare( + ScoreSchedReqYield_Context *ctx, + ScoreSchedReqYield_Pre_Other state +) +{ + switch ( state ) { + case ScoreSchedReqYield_Pre_Other_Yes: { + /* + * While at least one ready thread with a priority equal to the priority + * of the thread exists in the home scheduler of the thread. + */ + ctx->other_ready = true; + break; + } + + case ScoreSchedReqYield_Pre_Other_No: { + /* + * While no ready thread with a priority equal to the priority of the + * thread exists in the home scheduler of the thread. + */ + ctx->other_ready = false; + break; + } + + case ScoreSchedReqYield_Pre_Other_NA: + break; + } +} + +static void ScoreSchedReqYield_Post_HomeSchedulerState_Check( + ScoreSchedReqYield_Context *ctx, + ScoreSchedReqYield_Post_HomeSchedulerState state +) +{ + switch ( state ) { + case ScoreSchedReqYield_Post_HomeSchedulerState_Blocked: { + /* + * The thread shall be blocked in its home scheduler. + */ + T_true( ctx->is_idle_after_yield ); + T_eq_u32( ctx->cpu_after_yield, 1 ); + break; + } + + case ScoreSchedReqYield_Post_HomeSchedulerState_Scheduled: { + /* + * The thread shall be scheduled in its home scheduler. + */ + T_false( ctx->is_idle_before_yield ); + T_false( ctx->is_idle_after_yield ); + T_eq_u32( GetCounter( ctx ), 0 ); + T_eq_u32( ctx->cpu_after_yield, 0 ); + break; + } + + case ScoreSchedReqYield_Post_HomeSchedulerState_Ready: { + /* + * The thread shall be ready in its home scheduler. + */ + T_eq_u32( GetCounter( ctx ), 1 ); + break; + } + + case ScoreSchedReqYield_Post_HomeSchedulerState_Idle: { + /* + * An idle thread shall execute on behalf of the thread in its home + * scheduler. + */ + T_true( ctx->is_idle_before_yield ); + T_true( ctx->is_idle_after_yield ); + T_eq_u32( GetCounter( ctx ), 0 ); + T_eq_u32( ctx->cpu_after_yield, 1 ); + break; + } + + case ScoreSchedReqYield_Post_HomeSchedulerState_NA: + break; + } +} + +static void ScoreSchedReqYield_Post_AskForHelp_Check( + ScoreSchedReqYield_Context *ctx, + ScoreSchedReqYield_Post_AskForHelp state +) +{ + size_t index; + const T_scheduler_event *event; + + index = 0; + + switch ( state ) { + case ScoreSchedReqYield_Post_AskForHelp_Yes: { + /* + * The thread shall ask all its eligible scheduler for help. + */ + event = TQGetNextAskForHelp( &ctx->tq_ctx, &index ); + T_eq_ptr( event->thread, ctx->tq_ctx.runner_tcb ); + + event = TQGetNextAskForHelp( &ctx->tq_ctx, &index ); + T_eq_ptr( event->thread, ctx->tq_ctx.runner_tcb ); + + event = TQGetNextAskForHelp( &ctx->tq_ctx, &index ); + T_eq_ptr( event, &T_scheduler_event_null ); + break; + } + + case ScoreSchedReqYield_Post_AskForHelp_No: { + /* + * The thread shall not ask for help. + */ + event = TQGetNextAskForHelp( &ctx->tq_ctx, &index ); + T_eq_ptr( event, &T_scheduler_event_null ); + break; + } + + case ScoreSchedReqYield_Post_AskForHelp_NA: + break; + } +} + +static void ScoreSchedReqYield_Setup( ScoreSchedReqYield_Context *ctx ) +{ + rtems_status_code sc; + + memset( ctx, 0, sizeof( *ctx ) ); + ctx->tq_ctx.enqueue_prepare = TQEnqueuePrepareDefault; + ctx->tq_ctx.enqueue_done = TQEnqueueDoneDefault; + ctx->tq_ctx.enqueue = TQEnqueueClassicSem; + ctx->tq_ctx.surrender = TQSurrenderClassicSem; + ctx->tq_ctx.convert_status = TQConvertStatusClassic; + TQInitialize( &ctx->tq_ctx ); + + sc = rtems_semaphore_create( + rtems_build_name( 'M', 'U', 'T', 'X' ), + 1, + RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | + RTEMS_MULTIPROCESSOR_RESOURCE_SHARING, + PRIO_NORMAL, + &ctx->sticky_mutex + ); + T_rsc_success( sc ); + + TQSetPriority( &ctx->tq_ctx, COUNTER, PRIO_NORMAL ); + + #if defined(RTEMS_SMP) + TQSetScheduler( &ctx->tq_ctx, HELPER, SCHEDULER_B_ID, PRIO_NORMAL ); + TQSetPriority( &ctx->tq_ctx, MOVER, PRIO_HIGH ); + #endif +} + +static void ScoreSchedReqYield_Setup_Wrap( void *arg ) +{ + ScoreSchedReqYield_Context *ctx; + + ctx = arg; + ctx->Map.in_action_loop = false; + ScoreSchedReqYield_Setup( ctx ); +} + +static void ScoreSchedReqYield_Teardown( ScoreSchedReqYield_Context *ctx ) +{ + TQDestroy( &ctx->tq_ctx ); + DeleteMutex( ctx->sticky_mutex ); +} + +static void ScoreSchedReqYield_Teardown_Wrap( void *arg ) +{ + ScoreSchedReqYield_Context *ctx; + + ctx = arg; + ctx->Map.in_action_loop = false; + ScoreSchedReqYield_Teardown( ctx ); +} + +static void ScoreSchedReqYield_Action( ScoreSchedReqYield_Context *ctx ) +{ + const Per_CPU_Control *cpu; + bool other_busy; + + if ( ctx->has_helping ) { + TQMutexObtain( &ctx->tq_ctx, TQ_MUTEX_A ); + TQSendAndWaitForExecutionStop( + &ctx->tq_ctx, + HELPER, + TQ_EVENT_MUTEX_A_OBTAIN + ); + } + + if ( ctx->use_helping ) { + MoveToHelping( ctx ); + } + + TQResetCounter( &ctx->tq_ctx ); + + if ( ctx->use_helping && ctx->ready ) { + ctx->tq_ctx.busy_wait[ COUNTER ] = true; + TQSend( &ctx->tq_ctx, COUNTER, TQ_EVENT_COUNT | TQ_EVENT_BUSY_WAIT ); + other_busy = true; + } else { + other_busy = false; + } + + if ( ctx->sticky ) { + ObtainMutex( ctx->sticky_mutex ); + } + + if ( ctx->other_ready && !other_busy ) { + TQSend( &ctx->tq_ctx, COUNTER, TQ_EVENT_COUNT ); + } + + cpu = _Per_CPU_Get_by_index( 0 ); + ctx->is_idle_before_yield = cpu->heir->is_idle; + + TQSchedulerRecordStart( &ctx->tq_ctx ); + Yield(); + TQSchedulerRecordStop( &ctx->tq_ctx ); + + #if defined(RTEMS_SMP) + ctx->tq_ctx.busy_wait[ COUNTER ] = false; + + while ( cpu->heir == ctx->tq_ctx.worker_tcb[ COUNTER ] ) { + RTEMS_COMPILER_MEMORY_BARRIER(); + } + #endif + + ctx->is_idle_after_yield = cpu->heir->is_idle; + ctx->cpu_after_yield = rtems_scheduler_get_processor(); + + if ( ctx->sticky ) { + ReleaseMutex( ctx->sticky_mutex ); + } + + if ( ctx->has_helping ) { + TQMutexRelease( &ctx->tq_ctx, TQ_MUTEX_A ); + TQSendAndWaitForExecutionStop( + &ctx->tq_ctx, + HELPER, + TQ_EVENT_MUTEX_A_RELEASE + ); + } +} + +static const ScoreSchedReqYield_Entry +ScoreSchedReqYield_Entries[] = { +#if !defined(RTEMS_SMP) + { 1, 0, 0, 0, 0, 0, ScoreSchedReqYield_Post_HomeSchedulerState_NA, + ScoreSchedReqYield_Post_AskForHelp_NA }, +#else + { 1, 0, 0, 0, 0, 0, ScoreSchedReqYield_Post_HomeSchedulerState_NA, + ScoreSchedReqYield_Post_AskForHelp_NA }, +#endif + { 1, 0, 0, 0, 0, 0, ScoreSchedReqYield_Post_HomeSchedulerState_NA, + ScoreSchedReqYield_Post_AskForHelp_NA }, + { 1, 0, 0, 0, 0, 0, ScoreSchedReqYield_Post_HomeSchedulerState_NA, + ScoreSchedReqYield_Post_AskForHelp_NA }, +#if !defined(RTEMS_SMP) + { 1, 0, 0, 0, 0, 0, ScoreSchedReqYield_Post_HomeSchedulerState_NA, + ScoreSchedReqYield_Post_AskForHelp_NA }, +#else + { 0, 0, 0, 0, 0, 0, ScoreSchedReqYield_Post_HomeSchedulerState_Ready, + ScoreSchedReqYield_Post_AskForHelp_No }, +#endif +#if !defined(RTEMS_SMP) + { 1, 0, 0, 0, 0, 0, ScoreSchedReqYield_Post_HomeSchedulerState_NA, + ScoreSchedReqYield_Post_AskForHelp_NA }, +#else + { 1, 0, 0, 0, 0, 0, ScoreSchedReqYield_Post_HomeSchedulerState_NA, + ScoreSchedReqYield_Post_AskForHelp_NA }, +#endif +#if !defined(RTEMS_SMP) + { 1, 0, 0, 0, 0, 0, ScoreSchedReqYield_Post_HomeSchedulerState_NA, + ScoreSchedReqYield_Post_AskForHelp_NA }, +#else + { 1, 0, 0, 0, 0, 0, ScoreSchedReqYield_Post_HomeSchedulerState_NA, + ScoreSchedReqYield_Post_AskForHelp_NA }, +#endif +#if !defined(RTEMS_SMP) + { 1, 0, 0, 0, 0, 0, ScoreSchedReqYield_Post_HomeSchedulerState_NA, + ScoreSchedReqYield_Post_AskForHelp_NA }, +#else + { 1, 0, 0, 0, 0, 0, ScoreSchedReqYield_Post_HomeSchedulerState_NA, + ScoreSchedReqYield_Post_AskForHelp_NA }, +#endif +#if !defined(RTEMS_SMP) + { 1, 0, 0, 0, 0, 0, ScoreSchedReqYield_Post_HomeSchedulerState_NA, + ScoreSchedReqYield_Post_AskForHelp_NA }, +#else + { 1, 0, 0, 0, 0, 0, ScoreSchedReqYield_Post_HomeSchedulerState_NA, + ScoreSchedReqYield_Post_AskForHelp_NA }, +#endif +#if !defined(RTEMS_SMP) + { 1, 0, 0, 0, 0, 0, ScoreSchedReqYield_Post_HomeSchedulerState_NA, + ScoreSchedReqYield_Post_AskForHelp_NA }, +#else + { 0, 0, 0, 0, 0, 0, ScoreSchedReqYield_Post_HomeSchedulerState_Scheduled, + ScoreSchedReqYield_Post_AskForHelp_No }, +#endif +#if !defined(RTEMS_SMP) + { 1, 0, 0, 0, 0, 0, ScoreSchedReqYield_Post_HomeSchedulerState_NA, + ScoreSchedReqYield_Post_AskForHelp_NA }, +#else + { 0, 0, 0, 0, 0, 0, ScoreSchedReqYield_Post_HomeSchedulerState_Blocked, + ScoreSchedReqYield_Post_AskForHelp_No }, +#endif + { 0, 0, 0, 0, 0, 0, ScoreSchedReqYield_Post_HomeSchedulerState_Ready, + ScoreSchedReqYield_Post_AskForHelp_No }, + { 0, 0, 0, 0, 0, 0, ScoreSchedReqYield_Post_HomeSchedulerState_Scheduled, + ScoreSchedReqYield_Post_AskForHelp_No }, +#if !defined(RTEMS_SMP) + { 1, 0, 0, 0, 0, 0, ScoreSchedReqYield_Post_HomeSchedulerState_NA, + ScoreSchedReqYield_Post_AskForHelp_NA }, +#else + { 0, 0, 0, 0, 0, 0, ScoreSchedReqYield_Post_HomeSchedulerState_Ready, + ScoreSchedReqYield_Post_AskForHelp_Yes }, +#endif +#if !defined(RTEMS_SMP) + { 1, 0, 0, 0, 0, 0, ScoreSchedReqYield_Post_HomeSchedulerState_NA, + ScoreSchedReqYield_Post_AskForHelp_NA }, +#else + { 0, 0, 0, 0, 0, 0, ScoreSchedReqYield_Post_HomeSchedulerState_Ready, + ScoreSchedReqYield_Post_AskForHelp_Yes }, +#endif +#if !defined(RTEMS_SMP) + { 1, 0, 0, 0, 0, 0, ScoreSchedReqYield_Post_HomeSchedulerState_NA, + ScoreSchedReqYield_Post_AskForHelp_NA }, +#else + { 0, 0, 0, 0, 0, 0, ScoreSchedReqYield_Post_HomeSchedulerState_Scheduled, + ScoreSchedReqYield_Post_AskForHelp_No }, +#endif +#if !defined(RTEMS_SMP) + { 1, 0, 0, 0, 0, 0, ScoreSchedReqYield_Post_HomeSchedulerState_NA, + ScoreSchedReqYield_Post_AskForHelp_NA } +#else + { 0, 0, 0, 0, 0, 0, ScoreSchedReqYield_Post_HomeSchedulerState_Idle, + ScoreSchedReqYield_Post_AskForHelp_No } +#endif +}; + +static const uint8_t +ScoreSchedReqYield_Map[] = { + 0, 0, 2, 2, 3, 8, 10, 11, 0, 0, 2, 2, 4, 4, 1, 1, 5, 5, 1, 1, 5, 5, 1, 1, 0, + 0, 6, 6, 12, 8, 13, 14, 0, 0, 6, 6, 4, 4, 9, 9, 3, 15, 7, 7, 3, 3, 7, 7 +}; + +static size_t ScoreSchedReqYield_Scope( void *arg, char *buf, size_t n ) +{ + ScoreSchedReqYield_Context *ctx; + + ctx = arg; + + if ( ctx->Map.in_action_loop ) { + return T_get_scope( ScoreSchedReqYield_PreDesc, buf, n, ctx->Map.pcs ); + } + + return 0; +} + +static T_fixture ScoreSchedReqYield_Fixture = { + .setup = ScoreSchedReqYield_Setup_Wrap, + .stop = NULL, + .teardown = ScoreSchedReqYield_Teardown_Wrap, + .scope = ScoreSchedReqYield_Scope, + .initial_context = &ScoreSchedReqYield_Instance +}; + +static inline ScoreSchedReqYield_Entry ScoreSchedReqYield_PopEntry( + ScoreSchedReqYield_Context *ctx +) +{ + size_t index; + + index = ctx->Map.index; + ctx->Map.index = index + 1; + return ScoreSchedReqYield_Entries[ + ScoreSchedReqYield_Map[ index ] + ]; +} + +static void ScoreSchedReqYield_TestVariant( ScoreSchedReqYield_Context *ctx ) +{ + ScoreSchedReqYield_Pre_EligibleScheduler_Prepare( ctx, ctx->Map.pcs[ 0 ] ); + ScoreSchedReqYield_Pre_UsedScheduler_Prepare( ctx, ctx->Map.pcs[ 1 ] ); + ScoreSchedReqYield_Pre_HomeSchedulerState_Prepare( ctx, ctx->Map.pcs[ 2 ] ); + ScoreSchedReqYield_Pre_Sticky_Prepare( ctx, ctx->Map.pcs[ 3 ] ); + ScoreSchedReqYield_Pre_Other_Prepare( ctx, ctx->Map.pcs[ 4 ] ); + ScoreSchedReqYield_Action( ctx ); + ScoreSchedReqYield_Post_HomeSchedulerState_Check( + ctx, + ctx->Map.entry.Post_HomeSchedulerState + ); + ScoreSchedReqYield_Post_AskForHelp_Check( + ctx, + ctx->Map.entry.Post_AskForHelp + ); +} + +/** + * @fn void T_case_body_ScoreSchedReqYield( void ) + */ +T_TEST_CASE_FIXTURE( ScoreSchedReqYield, &ScoreSchedReqYield_Fixture ) +{ + ScoreSchedReqYield_Context *ctx; + + ctx = T_fixture_context(); + ctx->Map.in_action_loop = true; + ctx->Map.index = 0; + + for ( + ctx->Map.pcs[ 0 ] = ScoreSchedReqYield_Pre_EligibleScheduler_Home; + ctx->Map.pcs[ 0 ] < ScoreSchedReqYield_Pre_EligibleScheduler_NA; + ++ctx->Map.pcs[ 0 ] + ) { + for ( + ctx->Map.pcs[ 1 ] = ScoreSchedReqYield_Pre_UsedScheduler_Home; + ctx->Map.pcs[ 1 ] < ScoreSchedReqYield_Pre_UsedScheduler_NA; + ++ctx->Map.pcs[ 1 ] + ) { + for ( + ctx->Map.pcs[ 2 ] = ScoreSchedReqYield_Pre_HomeSchedulerState_Blocked; + ctx->Map.pcs[ 2 ] < ScoreSchedReqYield_Pre_HomeSchedulerState_NA; + ++ctx->Map.pcs[ 2 ] + ) { + for ( + ctx->Map.pcs[ 3 ] = ScoreSchedReqYield_Pre_Sticky_Yes; + ctx->Map.pcs[ 3 ] < ScoreSchedReqYield_Pre_Sticky_NA; + ++ctx->Map.pcs[ 3 ] + ) { + for ( + ctx->Map.pcs[ 4 ] = ScoreSchedReqYield_Pre_Other_Yes; + ctx->Map.pcs[ 4 ] < ScoreSchedReqYield_Pre_Other_NA; + ++ctx->Map.pcs[ 4 ] + ) { + ctx->Map.entry = ScoreSchedReqYield_PopEntry( ctx ); + + if ( ctx->Map.entry.Skip ) { + continue; + } + + ScoreSchedReqYield_TestVariant( ctx ); + } + } + } + } + } +} + +/** @} */ |