Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup ScoreTqReqEnqueueCeiling
0007  */
0008 
0009 /*
0010  * Copyright (C) 2021 embedded brains GmbH & Co. KG
0011  *
0012  * Redistribution and use in source and binary forms, with or without
0013  * modification, are permitted provided that the following conditions
0014  * are met:
0015  * 1. Redistributions of source code must retain the above copyright
0016  *    notice, this list of conditions and the following disclaimer.
0017  * 2. Redistributions in binary form must reproduce the above copyright
0018  *    notice, this list of conditions and the following disclaimer in the
0019  *    documentation and/or other materials provided with the distribution.
0020  *
0021  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0022  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0023  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0024  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0025  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0026  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0027  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0028  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0029  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0030  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0031  * POSSIBILITY OF SUCH DAMAGE.
0032  */
0033 
0034 /*
0035  * This file is part of the RTEMS quality process and was automatically
0036  * generated.  If you find something that needs to be fixed or
0037  * worded better please post a report or patch to an RTEMS mailing list
0038  * or raise a bug report:
0039  *
0040  * https://www.rtems.org/bugs.html
0041  *
0042  * For information on updating and regenerating please refer to the How-To
0043  * section in the Software Requirements Engineering chapter of the
0044  * RTEMS Software Engineering manual.  The manual is provided as a part of
0045  * a release.  For development sources please refer to the online
0046  * documentation at:
0047  *
0048  * https://docs.rtems.org
0049  */
0050 
0051 #ifdef HAVE_CONFIG_H
0052 #include "config.h"
0053 #endif
0054 
0055 #include "tr-tq-enqueue-ceiling.h"
0056 
0057 #include <rtems/test.h>
0058 
0059 /**
0060  * @defgroup ScoreTqReqEnqueueCeiling spec:/score/tq/req/enqueue-ceiling
0061  *
0062  * @ingroup TestsuitesValidationNoClock0
0063  *
0064  * @{
0065  */
0066 
0067 typedef struct {
0068   uint8_t Skip : 1;
0069   uint8_t Pre_EligibleScheduler_NA : 1;
0070   uint8_t Pre_QueueEligible_NA : 1;
0071   uint8_t Pre_QueueIneligible_NA : 1;
0072   uint8_t Post_Position : 3;
0073 } ScoreTqReqEnqueueCeiling_Entry;
0074 
0075 /**
0076  * @brief Test context for spec:/score/tq/req/enqueue-ceiling test case.
0077  */
0078 typedef struct {
0079   /**
0080    * @brief This this member is true, then the enqueueing thread shall have at
0081    *   least one helping scheduler.
0082    */
0083   bool helping;
0084 
0085   /**
0086    * @brief This member specifies the priority of a thread with an eligible
0087    *   scheduler equal to an eligible scheduler of the enqueueing thread.
0088    */
0089   rtems_task_priority priority;
0090 
0091   /**
0092    * @brief If this member is true, then a thread those eligible schedulers are
0093    *   ineligible scheduler to the enqueueing task should be enqueued before a
0094    *   thread with an eligible scheduler equal to an eligible scheduler of the
0095    *   enqueueing thread.
0096    */
0097   size_t other_before;
0098 
0099   /**
0100    * @brief If this member is true, then a thread those eligible schedulers are
0101    *   ineligible scheduler to the enqueueing task should be enqueued after a
0102    *   thread with an eligible scheduler equal to an eligible scheduler of the
0103    *   enqueueing thread.
0104    */
0105   size_t other_after;
0106 
0107   /**
0108    * @brief This member contains a copy of the corresponding
0109    *   ScoreTqReqEnqueueCeiling_Run() parameter.
0110    */
0111   TQContext *tq_ctx;
0112 
0113   struct {
0114     /**
0115      * @brief This member defines the pre-condition states for the next action.
0116      */
0117     size_t pcs[ 3 ];
0118 
0119     /**
0120      * @brief If this member is true, then the test action loop is executed.
0121      */
0122     bool in_action_loop;
0123 
0124     /**
0125      * @brief This member contains the next transition map index.
0126      */
0127     size_t index;
0128 
0129     /**
0130      * @brief This member contains the current transition map entry.
0131      */
0132     ScoreTqReqEnqueueCeiling_Entry entry;
0133 
0134     /**
0135      * @brief If this member is true, then the current transition variant
0136      *   should be skipped.
0137      */
0138     bool skip;
0139   } Map;
0140 } ScoreTqReqEnqueueCeiling_Context;
0141 
0142 static ScoreTqReqEnqueueCeiling_Context
0143   ScoreTqReqEnqueueCeiling_Instance;
0144 
0145 static const char * const ScoreTqReqEnqueueCeiling_PreDesc_EligibleScheduler[] = {
0146   "Home",
0147   "Helping",
0148   "NA"
0149 };
0150 
0151 static const char * const ScoreTqReqEnqueueCeiling_PreDesc_QueueEligible[] = {
0152   "None",
0153   "Equal",
0154   "Low",
0155   "NA"
0156 };
0157 
0158 static const char * const ScoreTqReqEnqueueCeiling_PreDesc_QueueIneligible[] = {
0159   "None",
0160   "Before",
0161   "After",
0162   "NA"
0163 };
0164 
0165 static const char * const * const ScoreTqReqEnqueueCeiling_PreDesc[] = {
0166   ScoreTqReqEnqueueCeiling_PreDesc_EligibleScheduler,
0167   ScoreTqReqEnqueueCeiling_PreDesc_QueueEligible,
0168   ScoreTqReqEnqueueCeiling_PreDesc_QueueIneligible,
0169   NULL
0170 };
0171 
0172 typedef ScoreTqReqEnqueueCeiling_Context Context;
0173 
0174 static const rtems_tcb *GetUnblock( Context *ctx, size_t *index )
0175 {
0176   const rtems_tcb *thread;
0177 
0178   do {
0179     thread = TQGetNextUnblock( ctx->tq_ctx, index )->thread;
0180   } while ( thread == ctx->tq_ctx->runner_tcb );
0181 
0182   return thread;
0183 }
0184 
0185 static const rtems_tcb *GetTCB( Context *ctx, TQWorkerKind worker )
0186 {
0187   return ctx->tq_ctx->worker_tcb[ worker ];
0188 }
0189 
0190 static void AddHelper( TQContext *tq_ctx, rtems_id scheduler_id )
0191 {
0192   TQSend( tq_ctx, TQ_BLOCKER_C, TQ_EVENT_MUTEX_A_OBTAIN );
0193   TQSetScheduler( tq_ctx, TQ_BLOCKER_E, scheduler_id, PRIO_LOW );
0194   TQSendAndWaitForExecutionStop(
0195     tq_ctx,
0196     TQ_BLOCKER_E,
0197     TQ_EVENT_MUTEX_A_OBTAIN | TQ_EVENT_MUTEX_A_RELEASE
0198   );
0199 }
0200 
0201 static void RemoveHelper( TQContext *tq_ctx )
0202 {
0203   TQSend( tq_ctx, TQ_BLOCKER_C, TQ_EVENT_MUTEX_A_RELEASE );
0204   TQMutexObtain( tq_ctx, TQ_MUTEX_A );
0205   TQMutexRelease( tq_ctx, TQ_MUTEX_A );
0206 }
0207 
0208 static void ScoreTqReqEnqueueCeiling_Pre_EligibleScheduler_Prepare(
0209   ScoreTqReqEnqueueCeiling_Context              *ctx,
0210   ScoreTqReqEnqueueCeiling_Pre_EligibleScheduler state
0211 )
0212 {
0213   switch ( state ) {
0214     case ScoreTqReqEnqueueCeiling_Pre_EligibleScheduler_Home: {
0215       /*
0216        * While the enqueueing thread has no helping scheduler.
0217        */
0218       ctx->helping = false;
0219       break;
0220     }
0221 
0222     case ScoreTqReqEnqueueCeiling_Pre_EligibleScheduler_Helping: {
0223       /*
0224        * While the enqueueing thread has at least one helping scheduler.
0225        */
0226       ctx->helping = true;
0227       break;
0228     }
0229 
0230     case ScoreTqReqEnqueueCeiling_Pre_EligibleScheduler_NA:
0231       break;
0232   }
0233 }
0234 
0235 static void ScoreTqReqEnqueueCeiling_Pre_QueueEligible_Prepare(
0236   ScoreTqReqEnqueueCeiling_Context          *ctx,
0237   ScoreTqReqEnqueueCeiling_Pre_QueueEligible state
0238 )
0239 {
0240   switch ( state ) {
0241     case ScoreTqReqEnqueueCeiling_Pre_QueueEligible_None: {
0242       /*
0243        * While all priority queues of the thread queue associated with eligible
0244        * schedulers of the enqueueing thread are empty.
0245        */
0246       /* This is the default */
0247       break;
0248     }
0249 
0250     case ScoreTqReqEnqueueCeiling_Pre_QueueEligible_Equal: {
0251       /*
0252        * While a priority queue of the thread queue associated with an eligible
0253        * scheduler of the enqueueing thread is non-empty, while the highest
0254        * priority of the priority queue is equal to the priority of the
0255        * enqueueing thread with respect to the eligible scheduler.
0256        */
0257       ctx->priority = PRIO_VERY_HIGH;
0258       break;
0259     }
0260 
0261     case ScoreTqReqEnqueueCeiling_Pre_QueueEligible_Low: {
0262       /*
0263        * While a priority queue of the thread queue associated with an eligible
0264        * scheduler of the enqueueing thread is non-empty, while the highest
0265        * priority of the priority queue is lower than the priority of the
0266        * enqueueing thread with respect to the eligible scheduler.
0267        */
0268       ctx->priority = PRIO_HIGH;
0269       break;
0270     }
0271 
0272     case ScoreTqReqEnqueueCeiling_Pre_QueueEligible_NA:
0273       break;
0274   }
0275 }
0276 
0277 static void ScoreTqReqEnqueueCeiling_Pre_QueueIneligible_Prepare(
0278   ScoreTqReqEnqueueCeiling_Context            *ctx,
0279   ScoreTqReqEnqueueCeiling_Pre_QueueIneligible state
0280 )
0281 {
0282   switch ( state ) {
0283     case ScoreTqReqEnqueueCeiling_Pre_QueueIneligible_None: {
0284       /*
0285        * While no priority queue of the thread queue exists which is not
0286        * associated with an eligible scheduler of the enqueueing thread.
0287        */
0288       /* This is the default */
0289       break;
0290     }
0291 
0292     case ScoreTqReqEnqueueCeiling_Pre_QueueIneligible_Before: {
0293       /*
0294        * While a priority queue of the thread queue exists which is not
0295        * associated with an eligible scheduler of the enqueueing thread, while
0296        * this priority queue is positioned before all priority queues which are
0297        * associated with eligible schedulers of the enqueueing thread.
0298        */
0299       ctx->other_before = true;
0300       break;
0301     }
0302 
0303     case ScoreTqReqEnqueueCeiling_Pre_QueueIneligible_After: {
0304       /*
0305        * While a priority queue of the thread queue exists which is not
0306        * associated with an eligible scheduler of the enqueueing thread, while
0307        * this priority queue is positioned after all priority queues which are
0308        * associated with eligible schedulers of the enqueueing thread.
0309        */
0310       ctx->other_after = true;
0311       break;
0312     }
0313 
0314     case ScoreTqReqEnqueueCeiling_Pre_QueueIneligible_NA:
0315       break;
0316   }
0317 }
0318 
0319 static void ScoreTqReqEnqueueCeiling_Post_Position_Check(
0320   ScoreTqReqEnqueueCeiling_Context      *ctx,
0321   ScoreTqReqEnqueueCeiling_Post_Position state
0322 )
0323 {
0324   size_t i;
0325 
0326   i = 0;
0327 
0328   /* Event receives */
0329   T_eq_ptr( GetUnblock( ctx, &i ), GetTCB( ctx, TQ_BLOCKER_C ) );
0330   T_eq_ptr( GetUnblock( ctx, &i ), GetTCB( ctx, TQ_BLOCKER_A ) );
0331 
0332   switch ( state ) {
0333     case ScoreTqReqEnqueueCeiling_Post_Position_InitialFirst: {
0334       /*
0335        * A priority queue associated with the scheduler which contains exactly
0336        * the enqueueing thread shall be created as the first priority queue of
0337        * the thread queue.
0338        */
0339       T_eq_ptr( GetUnblock( ctx, &i ), GetTCB( ctx, TQ_BLOCKER_C ) );
0340       T_eq_ptr( GetUnblock( ctx, &i ), NULL );
0341       break;
0342     }
0343 
0344     case ScoreTqReqEnqueueCeiling_Post_Position_First: {
0345       /*
0346        * The enqueueing thread shall be enqueued in the priority queue
0347        * associated with the scheduler.
0348        */
0349       T_eq_ptr( GetUnblock( ctx, &i ), GetTCB( ctx, TQ_BLOCKER_C ) );
0350       T_eq_ptr( GetUnblock( ctx, &i ), GetTCB( ctx, TQ_BLOCKER_B ) );
0351       T_eq_ptr( GetUnblock( ctx, &i ), NULL );
0352       break;
0353     }
0354 
0355     case ScoreTqReqEnqueueCeiling_Post_Position_Second: {
0356       /*
0357        * The enqueueing thread shall be enqueued in the priority queue
0358        * associated with the scheduler.
0359        */
0360       T_eq_ptr( GetUnblock( ctx, &i ), GetTCB( ctx, TQ_BLOCKER_B ) );
0361       T_eq_ptr( GetUnblock( ctx, &i ), GetTCB( ctx, TQ_BLOCKER_C ) );
0362       T_eq_ptr( GetUnblock( ctx, &i ), NULL );
0363       break;
0364     }
0365 
0366     case ScoreTqReqEnqueueCeiling_Post_Position_FirstFirst: {
0367       /*
0368        * The enqueueing thread shall be enqueued in the priority queue
0369        * associated with the scheduler.
0370        *
0371        * The position of the priority queue in the thread queue shall not
0372        * change.
0373        */
0374       T_eq_ptr( GetUnblock( ctx, &i ), GetTCB( ctx, TQ_BLOCKER_C ) );
0375       T_eq_ptr( GetUnblock( ctx, &i ), GetTCB( ctx, TQ_BLOCKER_B ) );
0376       T_eq_ptr( GetUnblock( ctx, &i ), NULL );
0377       break;
0378     }
0379 
0380     case ScoreTqReqEnqueueCeiling_Post_Position_SecondFirst: {
0381       /*
0382        * The enqueueing thread shall be enqueued in the priority queue
0383        * associated with the scheduler.
0384        *
0385        * The position of the priority queue in the thread queue shall not
0386        * change.
0387        */
0388       T_eq_ptr( GetUnblock( ctx, &i ), GetTCB( ctx, TQ_BLOCKER_B ) );
0389       T_eq_ptr( GetUnblock( ctx, &i ), GetTCB( ctx, TQ_BLOCKER_C ) );
0390       T_eq_ptr( GetUnblock( ctx, &i ), NULL );
0391       break;
0392     }
0393 
0394     case ScoreTqReqEnqueueCeiling_Post_Position_SecondQueue: {
0395       /*
0396        * The enqueueing thread shall be enqueued in the priority queue
0397        * associated with the scheduler.
0398        *
0399        * The position of the priority queue in the thread queue shall not
0400        * change.
0401        */
0402       T_eq_ptr( GetUnblock( ctx, &i ), GetTCB( ctx, TQ_BLOCKER_B ) );
0403       T_eq_ptr( GetUnblock( ctx, &i ), GetTCB( ctx, TQ_BLOCKER_C ) );
0404       T_eq_ptr( GetUnblock( ctx, &i ), NULL );
0405       break;
0406     }
0407 
0408     case ScoreTqReqEnqueueCeiling_Post_Position_NA:
0409       break;
0410   }
0411 }
0412 
0413 static void ScoreTqReqEnqueueCeiling_Setup(
0414   ScoreTqReqEnqueueCeiling_Context *ctx
0415 )
0416 {
0417   rtems_id scheduler_id;
0418 
0419   scheduler_id = SCHEDULER_A_ID;
0420   TQSetScheduler( ctx->tq_ctx, TQ_BLOCKER_A, scheduler_id, PRIO_VERY_HIGH );
0421   TQSetScheduler( ctx->tq_ctx, TQ_BLOCKER_B, scheduler_id, PRIO_VERY_HIGH );
0422   TQSetScheduler( ctx->tq_ctx, TQ_BLOCKER_C, scheduler_id, PRIO_VERY_HIGH );
0423   #if defined( RTEMS_SMP )
0424   TQSetScheduler( ctx->tq_ctx, TQ_BLOCKER_D, SCHEDULER_B_ID, PRIO_LOW );
0425   #endif
0426 }
0427 
0428 static void ScoreTqReqEnqueueCeiling_Setup_Wrap( void *arg )
0429 {
0430   ScoreTqReqEnqueueCeiling_Context *ctx;
0431 
0432   ctx = arg;
0433   ctx->Map.in_action_loop = false;
0434   ScoreTqReqEnqueueCeiling_Setup( ctx );
0435 }
0436 
0437 static void ScoreTqReqEnqueueCeiling_Teardown(
0438   ScoreTqReqEnqueueCeiling_Context *ctx
0439 )
0440 {
0441   TQReset( ctx->tq_ctx );
0442 }
0443 
0444 static void ScoreTqReqEnqueueCeiling_Teardown_Wrap( void *arg )
0445 {
0446   ScoreTqReqEnqueueCeiling_Context *ctx;
0447 
0448   ctx = arg;
0449   ctx->Map.in_action_loop = false;
0450   ScoreTqReqEnqueueCeiling_Teardown( ctx );
0451 }
0452 
0453 static void ScoreTqReqEnqueueCeiling_Prepare(
0454   ScoreTqReqEnqueueCeiling_Context *ctx
0455 )
0456 {
0457   ctx->priority = PRIO_PSEUDO_ISR;
0458   ctx->other_before = false;
0459   ctx->other_after = false;
0460 }
0461 
0462 static void ScoreTqReqEnqueueCeiling_Action(
0463   ScoreTqReqEnqueueCeiling_Context *ctx
0464 )
0465 {
0466   Status_Control status;
0467 
0468   if ( ctx->priority == PRIO_PSEUDO_ISR ) {
0469     TQSend( ctx->tq_ctx, TQ_BLOCKER_A, TQ_EVENT_ENQUEUE );
0470   } else {
0471     TQSetPriority( ctx->tq_ctx, TQ_BLOCKER_B , ctx->priority );
0472 
0473     if ( ctx->other_before || ctx->other_after ) {
0474       TQSend( ctx->tq_ctx, TQ_BLOCKER_B, TQ_EVENT_MUTEX_B_OBTAIN );
0475       TQSendAndWaitForExecutionStop(
0476         ctx->tq_ctx,
0477         TQ_BLOCKER_D,
0478         TQ_EVENT_MUTEX_B_OBTAIN | TQ_EVENT_MUTEX_B_RELEASE |
0479           TQ_EVENT_RUNNER_SYNC
0480       );
0481 
0482       if ( ctx->other_before ) {
0483         TQSend( ctx->tq_ctx, TQ_BLOCKER_C, TQ_EVENT_ENQUEUE );
0484       }
0485 
0486       TQSend( ctx->tq_ctx, TQ_BLOCKER_A, TQ_EVENT_ENQUEUE );
0487       TQSend(
0488         ctx->tq_ctx,
0489         TQ_BLOCKER_B,
0490         TQ_EVENT_ENQUEUE | TQ_EVENT_SURRENDER
0491       );
0492 
0493       if ( ctx->other_before ) {
0494         TQSend( ctx->tq_ctx, TQ_BLOCKER_C, TQ_EVENT_SURRENDER );
0495       }
0496     } else {
0497       TQSend( ctx->tq_ctx, TQ_BLOCKER_A, TQ_EVENT_ENQUEUE );
0498       TQSend(
0499         ctx->tq_ctx,
0500         TQ_BLOCKER_B,
0501         TQ_EVENT_ENQUEUE | TQ_EVENT_SURRENDER
0502       );
0503     }
0504   }
0505 
0506   if ( ctx->helping ) {
0507     if ( ctx->other_before || ctx->other_after ) {
0508       if ( rtems_scheduler_get_processor_maximum() > 2 ) {
0509         AddHelper( ctx->tq_ctx, SCHEDULER_C_ID );
0510       }
0511     } else {
0512       AddHelper( ctx->tq_ctx, SCHEDULER_B_ID );
0513     }
0514   }
0515 
0516   TQSchedulerRecordStart( ctx->tq_ctx );
0517   TQSend( ctx->tq_ctx, TQ_BLOCKER_C, TQ_EVENT_ENQUEUE | TQ_EVENT_SURRENDER );
0518   TQSend( ctx->tq_ctx, TQ_BLOCKER_A, TQ_EVENT_SURRENDER );
0519   status = TQEnqueue( ctx->tq_ctx, TQ_WAIT_FOREVER );
0520   T_eq_int( status, TQConvertStatus( ctx->tq_ctx, STATUS_SUCCESSFUL ) );
0521   TQSchedulerRecordStop( ctx->tq_ctx );
0522   status = TQSurrender( ctx->tq_ctx );
0523   T_eq_int( status, TQConvertStatus( ctx->tq_ctx, STATUS_SUCCESSFUL ) );
0524 
0525   if (
0526     ctx->priority != PRIO_PSEUDO_ISR &&
0527     ( ctx->other_before || ctx->other_after )
0528   ) {
0529     TQSend( ctx->tq_ctx, TQ_BLOCKER_B, TQ_EVENT_MUTEX_B_RELEASE );
0530     TQSynchronizeRunner();
0531   }
0532 
0533   if ( ctx->helping ) {
0534     if ( ctx->other_before || ctx->other_after ) {
0535       if ( rtems_scheduler_get_processor_maximum() > 2 ) {
0536         RemoveHelper( ctx->tq_ctx );
0537       }
0538     } else {
0539       RemoveHelper( ctx->tq_ctx );
0540     }
0541   }
0542 }
0543 
0544 static const ScoreTqReqEnqueueCeiling_Entry
0545 ScoreTqReqEnqueueCeiling_Entries[] = {
0546   { 1, 0, 0, 0, ScoreTqReqEnqueueCeiling_Post_Position_NA },
0547 #if defined(RTEMS_SMP)
0548   { 0, 0, 0, 0, ScoreTqReqEnqueueCeiling_Post_Position_SecondQueue },
0549 #else
0550   { 1, 0, 0, 0, ScoreTqReqEnqueueCeiling_Post_Position_NA },
0551 #endif
0552 #if defined(RTEMS_SMP)
0553   { 0, 0, 0, 0, ScoreTqReqEnqueueCeiling_Post_Position_SecondFirst },
0554 #else
0555   { 1, 0, 0, 0, ScoreTqReqEnqueueCeiling_Post_Position_NA },
0556 #endif
0557 #if defined(RTEMS_SMP)
0558   { 0, 0, 0, 0, ScoreTqReqEnqueueCeiling_Post_Position_FirstFirst },
0559 #else
0560   { 1, 0, 0, 0, ScoreTqReqEnqueueCeiling_Post_Position_NA },
0561 #endif
0562   { 0, 0, 0, 0, ScoreTqReqEnqueueCeiling_Post_Position_InitialFirst },
0563   { 0, 0, 0, 0, ScoreTqReqEnqueueCeiling_Post_Position_Second },
0564   { 0, 0, 0, 0, ScoreTqReqEnqueueCeiling_Post_Position_First },
0565 #if defined(RTEMS_SMP)
0566   { 0, 0, 0, 0, ScoreTqReqEnqueueCeiling_Post_Position_InitialFirst },
0567 #else
0568   { 1, 0, 0, 0, ScoreTqReqEnqueueCeiling_Post_Position_NA },
0569 #endif
0570 #if defined(RTEMS_SMP)
0571   { 0, 0, 0, 0, ScoreTqReqEnqueueCeiling_Post_Position_Second },
0572 #else
0573   { 1, 0, 0, 0, ScoreTqReqEnqueueCeiling_Post_Position_NA },
0574 #endif
0575 #if defined(RTEMS_SMP)
0576   { 0, 0, 0, 0, ScoreTqReqEnqueueCeiling_Post_Position_First }
0577 #else
0578   { 1, 0, 0, 0, ScoreTqReqEnqueueCeiling_Post_Position_NA }
0579 #endif
0580 };
0581 
0582 static const uint8_t
0583 ScoreTqReqEnqueueCeiling_Map[] = {
0584   4, 0, 0, 5, 1, 2, 6, 1, 3, 7, 0, 0, 8, 1, 2, 9, 1, 3
0585 };
0586 
0587 static size_t ScoreTqReqEnqueueCeiling_Scope( void *arg, char *buf, size_t n )
0588 {
0589   ScoreTqReqEnqueueCeiling_Context *ctx;
0590 
0591   ctx = arg;
0592 
0593   if ( ctx->Map.in_action_loop ) {
0594     return T_get_scope(
0595       ScoreTqReqEnqueueCeiling_PreDesc,
0596       buf,
0597       n,
0598       ctx->Map.pcs
0599     );
0600   }
0601 
0602   return 0;
0603 }
0604 
0605 static T_fixture ScoreTqReqEnqueueCeiling_Fixture = {
0606   .setup = ScoreTqReqEnqueueCeiling_Setup_Wrap,
0607   .stop = NULL,
0608   .teardown = ScoreTqReqEnqueueCeiling_Teardown_Wrap,
0609   .scope = ScoreTqReqEnqueueCeiling_Scope,
0610   .initial_context = &ScoreTqReqEnqueueCeiling_Instance
0611 };
0612 
0613 static inline ScoreTqReqEnqueueCeiling_Entry ScoreTqReqEnqueueCeiling_PopEntry(
0614   ScoreTqReqEnqueueCeiling_Context *ctx
0615 )
0616 {
0617   size_t index;
0618 
0619   index = ctx->Map.index;
0620   ctx->Map.index = index + 1;
0621   return ScoreTqReqEnqueueCeiling_Entries[
0622     ScoreTqReqEnqueueCeiling_Map[ index ]
0623   ];
0624 }
0625 
0626 static void ScoreTqReqEnqueueCeiling_TestVariant(
0627   ScoreTqReqEnqueueCeiling_Context *ctx
0628 )
0629 {
0630   ScoreTqReqEnqueueCeiling_Pre_EligibleScheduler_Prepare(
0631     ctx,
0632     ctx->Map.pcs[ 0 ]
0633   );
0634   ScoreTqReqEnqueueCeiling_Pre_QueueEligible_Prepare( ctx, ctx->Map.pcs[ 1 ] );
0635   ScoreTqReqEnqueueCeiling_Pre_QueueIneligible_Prepare(
0636     ctx,
0637     ctx->Map.pcs[ 2 ]
0638   );
0639   ScoreTqReqEnqueueCeiling_Action( ctx );
0640   ScoreTqReqEnqueueCeiling_Post_Position_Check(
0641     ctx,
0642     ctx->Map.entry.Post_Position
0643   );
0644 }
0645 
0646 static T_fixture_node ScoreTqReqEnqueueCeiling_Node;
0647 
0648 static T_remark ScoreTqReqEnqueueCeiling_Remark = {
0649   .next = NULL,
0650   .remark = "ScoreTqReqEnqueueCeiling"
0651 };
0652 
0653 void ScoreTqReqEnqueueCeiling_Run( TQContext *tq_ctx )
0654 {
0655   ScoreTqReqEnqueueCeiling_Context *ctx;
0656 
0657   ctx = &ScoreTqReqEnqueueCeiling_Instance;
0658   ctx->tq_ctx = tq_ctx;
0659 
0660   ctx = T_push_fixture(
0661     &ScoreTqReqEnqueueCeiling_Node,
0662     &ScoreTqReqEnqueueCeiling_Fixture
0663   );
0664   ctx->Map.in_action_loop = true;
0665   ctx->Map.index = 0;
0666 
0667   for (
0668     ctx->Map.pcs[ 0 ] = ScoreTqReqEnqueueCeiling_Pre_EligibleScheduler_Home;
0669     ctx->Map.pcs[ 0 ] < ScoreTqReqEnqueueCeiling_Pre_EligibleScheduler_NA;
0670     ++ctx->Map.pcs[ 0 ]
0671   ) {
0672     for (
0673       ctx->Map.pcs[ 1 ] = ScoreTqReqEnqueueCeiling_Pre_QueueEligible_None;
0674       ctx->Map.pcs[ 1 ] < ScoreTqReqEnqueueCeiling_Pre_QueueEligible_NA;
0675       ++ctx->Map.pcs[ 1 ]
0676     ) {
0677       for (
0678         ctx->Map.pcs[ 2 ] = ScoreTqReqEnqueueCeiling_Pre_QueueIneligible_None;
0679         ctx->Map.pcs[ 2 ] < ScoreTqReqEnqueueCeiling_Pre_QueueIneligible_NA;
0680         ++ctx->Map.pcs[ 2 ]
0681       ) {
0682         ctx->Map.entry = ScoreTqReqEnqueueCeiling_PopEntry( ctx );
0683         ScoreTqReqEnqueueCeiling_Prepare( ctx );
0684         ScoreTqReqEnqueueCeiling_TestVariant( ctx );
0685       }
0686     }
0687   }
0688 
0689   T_add_remark( &ScoreTqReqEnqueueCeiling_Remark );
0690   T_pop_fixture();
0691 }
0692 
0693 /** @} */