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 ScoreTqReqSurrenderMrsp
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 <rtems/score/threadimpl.h>
0056 
0057 #include "tr-tq-surrender-mrsp.h"
0058 #include "tx-support.h"
0059 
0060 #include <rtems/test.h>
0061 
0062 /**
0063  * @defgroup ScoreTqReqSurrenderMrsp spec:/score/tq/req/surrender-mrsp
0064  *
0065  * @ingroup TestsuitesValidationNoClock0
0066  *
0067  * @{
0068  */
0069 
0070 typedef struct {
0071   uint32_t Skip : 1;
0072   uint32_t Pre_InheritedPriority_NA : 1;
0073   uint32_t Pre_PreviousHelping_NA : 1;
0074   uint32_t Pre_Scheduler_NA : 1;
0075   uint32_t Pre_NewHelping_NA : 1;
0076   uint32_t Pre_Suspended_NA : 1;
0077   uint32_t Pre_WaitState_NA : 1;
0078   uint32_t Post_Dequeue : 1;
0079   uint32_t Post_Unblock : 1;
0080   uint32_t Post_PreviousOwnerPriority : 2;
0081   uint32_t Post_RemoveHelper : 2;
0082   uint32_t Post_AddHelper : 2;
0083   uint32_t Post_Suspended : 2;
0084 } ScoreTqReqSurrenderMrsp_Entry;
0085 
0086 /**
0087  * @brief Test context for spec:/score/tq/req/surrender-mrsp test case.
0088  */
0089 typedef struct {
0090   /**
0091    * @brief If this member is true, then all priorities of the previous owner
0092    *   inherited from the thread queue thread shall be dispensable.
0093    */
0094   bool inherited_priorities_are_dispensible;
0095 
0096   /**
0097    * @brief If this member is true, then all helping schedulers of the previous
0098    *   owner thread gained through the thread queue shall be dispensable.
0099    */
0100   bool helping_schedules_are_dispensible;
0101 
0102   /**
0103    * @brief If this member is true, then the previous owner thread shall use
0104    *   helping scheduler.
0105    */
0106   bool use_helping_scheduler;
0107 
0108   /**
0109    * @brief If this member is true, then the new owner thread shall gain a
0110    *   vital helping scheduler.
0111    */
0112   bool gains_new_helping_scheduler;
0113 
0114   /**
0115    * @brief If this member is true, then the new owner thread shall be
0116    *   suspended.
0117    */
0118   bool suspended;
0119 
0120   /**
0121    * @brief If this member is true, then the new owner thread shall be in the
0122    *   intend to block wait state.
0123    */
0124   bool intend_to_block;
0125 
0126   /**
0127    * @brief This member contains the current priority of the previous owner
0128    *   thread before the thread queue surrender operation.
0129    */
0130   rtems_task_priority priority_before;
0131 
0132   /**
0133    * @brief This member contains the current priority of the previous owner
0134    *   thread after the thread queue surrender operation.
0135    */
0136   rtems_task_priority priority_after;
0137 
0138   /**
0139    * @brief This member contains the identifier of the previous owner thread.
0140    */
0141   rtems_id previous_owner;
0142 
0143   /**
0144    * @brief This member contains a copy of the corresponding
0145    *   ScoreTqReqSurrenderMrsp_Run() parameter.
0146    */
0147   TQContext *tq_ctx;
0148 
0149   struct {
0150     /**
0151      * @brief This member defines the pre-condition states for the next action.
0152      */
0153     size_t pcs[ 6 ];
0154 
0155     /**
0156      * @brief If this member is true, then the test action loop is executed.
0157      */
0158     bool in_action_loop;
0159 
0160     /**
0161      * @brief This member contains the next transition map index.
0162      */
0163     size_t index;
0164 
0165     /**
0166      * @brief This member contains the current transition map entry.
0167      */
0168     ScoreTqReqSurrenderMrsp_Entry entry;
0169 
0170     /**
0171      * @brief If this member is true, then the current transition variant
0172      *   should be skipped.
0173      */
0174     bool skip;
0175   } Map;
0176 } ScoreTqReqSurrenderMrsp_Context;
0177 
0178 static ScoreTqReqSurrenderMrsp_Context
0179   ScoreTqReqSurrenderMrsp_Instance;
0180 
0181 static const char * const ScoreTqReqSurrenderMrsp_PreDesc_InheritedPriority[] = {
0182   "Vital",
0183   "Dispensable",
0184   "NA"
0185 };
0186 
0187 static const char * const ScoreTqReqSurrenderMrsp_PreDesc_PreviousHelping[] = {
0188   "Vital",
0189   "Dispensable",
0190   "NA"
0191 };
0192 
0193 static const char * const ScoreTqReqSurrenderMrsp_PreDesc_Scheduler[] = {
0194   "Home",
0195   "Helping",
0196   "NA"
0197 };
0198 
0199 static const char * const ScoreTqReqSurrenderMrsp_PreDesc_NewHelping[] = {
0200   "Vital",
0201   "Dispensable",
0202   "NA"
0203 };
0204 
0205 static const char * const ScoreTqReqSurrenderMrsp_PreDesc_Suspended[] = {
0206   "Yes",
0207   "No",
0208   "NA"
0209 };
0210 
0211 static const char * const ScoreTqReqSurrenderMrsp_PreDesc_WaitState[] = {
0212   "IntendToBlock",
0213   "NA"
0214 };
0215 
0216 static const char * const * const ScoreTqReqSurrenderMrsp_PreDesc[] = {
0217   ScoreTqReqSurrenderMrsp_PreDesc_InheritedPriority,
0218   ScoreTqReqSurrenderMrsp_PreDesc_PreviousHelping,
0219   ScoreTqReqSurrenderMrsp_PreDesc_Scheduler,
0220   ScoreTqReqSurrenderMrsp_PreDesc_NewHelping,
0221   ScoreTqReqSurrenderMrsp_PreDesc_Suspended,
0222   ScoreTqReqSurrenderMrsp_PreDesc_WaitState,
0223   NULL
0224 };
0225 
0226 typedef ScoreTqReqSurrenderMrsp_Context Context;
0227 
0228 static const rtems_tcb *GetUnblock( Context *ctx, size_t *index )
0229 {
0230   return TQGetNextUnblock( ctx->tq_ctx, index )->thread;
0231 }
0232 
0233 static void ScoreTqReqSurrenderMrsp_Pre_InheritedPriority_Prepare(
0234   ScoreTqReqSurrenderMrsp_Context              *ctx,
0235   ScoreTqReqSurrenderMrsp_Pre_InheritedPriority state
0236 )
0237 {
0238   switch ( state ) {
0239     case ScoreTqReqSurrenderMrsp_Pre_InheritedPriority_Vital: {
0240       /*
0241        * While at least one priority inherited through the thread queue for the
0242        * previous owner is the highest priority of the previous owner.
0243        */
0244       ctx->inherited_priorities_are_dispensible = false;
0245       break;
0246     }
0247 
0248     case ScoreTqReqSurrenderMrsp_Pre_InheritedPriority_Dispensable: {
0249       /*
0250        * While all priorities inherited through the thread queue for the
0251        * previous owner are not the highest priority of the previous owner.
0252        */
0253       ctx->inherited_priorities_are_dispensible = true;
0254       break;
0255     }
0256 
0257     case ScoreTqReqSurrenderMrsp_Pre_InheritedPriority_NA:
0258       break;
0259   }
0260 }
0261 
0262 static void ScoreTqReqSurrenderMrsp_Pre_PreviousHelping_Prepare(
0263   ScoreTqReqSurrenderMrsp_Context            *ctx,
0264   ScoreTqReqSurrenderMrsp_Pre_PreviousHelping state
0265 )
0266 {
0267   switch ( state ) {
0268     case ScoreTqReqSurrenderMrsp_Pre_PreviousHelping_Vital: {
0269       /*
0270        * While at least one helping scheduler of the previous owner is only
0271        * available due to a priority inherited through the thread queue.
0272        */
0273       ctx->helping_schedules_are_dispensible = false;
0274       break;
0275     }
0276 
0277     case ScoreTqReqSurrenderMrsp_Pre_PreviousHelping_Dispensable: {
0278       /*
0279        * While all helping scheduler of the previous owner are not only
0280        * available due to a priority inherited through the thread queue.
0281        */
0282       ctx->helping_schedules_are_dispensible = true;
0283       break;
0284     }
0285 
0286     case ScoreTqReqSurrenderMrsp_Pre_PreviousHelping_NA:
0287       break;
0288   }
0289 }
0290 
0291 static void ScoreTqReqSurrenderMrsp_Pre_Scheduler_Prepare(
0292   ScoreTqReqSurrenderMrsp_Context      *ctx,
0293   ScoreTqReqSurrenderMrsp_Pre_Scheduler state
0294 )
0295 {
0296   switch ( state ) {
0297     case ScoreTqReqSurrenderMrsp_Pre_Scheduler_Home: {
0298       /*
0299        * While the previous owner executes in its home scheduler.
0300        */
0301       ctx->use_helping_scheduler = false;
0302       break;
0303     }
0304 
0305     case ScoreTqReqSurrenderMrsp_Pre_Scheduler_Helping: {
0306       /*
0307        * While the previous owner executes in a helping scheduler which is
0308        * available due to a priority inherited through the thread queue.
0309        */
0310       ctx->use_helping_scheduler = true;
0311       break;
0312     }
0313 
0314     case ScoreTqReqSurrenderMrsp_Pre_Scheduler_NA:
0315       break;
0316   }
0317 }
0318 
0319 static void ScoreTqReqSurrenderMrsp_Pre_NewHelping_Prepare(
0320   ScoreTqReqSurrenderMrsp_Context       *ctx,
0321   ScoreTqReqSurrenderMrsp_Pre_NewHelping state
0322 )
0323 {
0324   switch ( state ) {
0325     case ScoreTqReqSurrenderMrsp_Pre_NewHelping_Vital: {
0326       /*
0327        * While at least one helping scheduler of the new owner is only
0328        * available due to a priority inherited through the thread queue.
0329        */
0330       ctx->gains_new_helping_scheduler = true;
0331       break;
0332     }
0333 
0334     case ScoreTqReqSurrenderMrsp_Pre_NewHelping_Dispensable: {
0335       /*
0336        * While all helping scheduler of the new owner are not only available
0337        * due to a priority inherited through the thread queue.
0338        */
0339       ctx->gains_new_helping_scheduler = false;
0340       break;
0341     }
0342 
0343     case ScoreTqReqSurrenderMrsp_Pre_NewHelping_NA:
0344       break;
0345   }
0346 }
0347 
0348 static void ScoreTqReqSurrenderMrsp_Pre_Suspended_Prepare(
0349   ScoreTqReqSurrenderMrsp_Context      *ctx,
0350   ScoreTqReqSurrenderMrsp_Pre_Suspended state
0351 )
0352 {
0353   switch ( state ) {
0354     case ScoreTqReqSurrenderMrsp_Pre_Suspended_Yes: {
0355       /*
0356        * While the new owner is suspended.
0357        */
0358       ctx->suspended = true;
0359       break;
0360     }
0361 
0362     case ScoreTqReqSurrenderMrsp_Pre_Suspended_No: {
0363       /*
0364        * While the new owner is not suspended.
0365        */
0366       ctx->suspended = false;
0367       break;
0368     }
0369 
0370     case ScoreTqReqSurrenderMrsp_Pre_Suspended_NA:
0371       break;
0372   }
0373 }
0374 
0375 static void ScoreTqReqSurrenderMrsp_Pre_WaitState_Prepare(
0376   ScoreTqReqSurrenderMrsp_Context      *ctx,
0377   ScoreTqReqSurrenderMrsp_Pre_WaitState state
0378 )
0379 {
0380   switch ( state ) {
0381     case ScoreTqReqSurrenderMrsp_Pre_WaitState_IntendToBlock: {
0382       /*
0383        * While the new owner is in the intend to block wait state.
0384        */
0385       ctx->intend_to_block = true;
0386       break;
0387     }
0388 
0389     case ScoreTqReqSurrenderMrsp_Pre_WaitState_NA:
0390       break;
0391   }
0392 }
0393 
0394 static void ScoreTqReqSurrenderMrsp_Post_Dequeue_Check(
0395   ScoreTqReqSurrenderMrsp_Context     *ctx,
0396   ScoreTqReqSurrenderMrsp_Post_Dequeue state
0397 )
0398 {
0399   switch ( state ) {
0400     case ScoreTqReqSurrenderMrsp_Post_Dequeue_Priority: {
0401       /*
0402        * The first thread in priority order shall be dequeued from the thread
0403        * queue.
0404        */
0405       /* Validation is done by spec:/score/tq/req/enqueue-priority */
0406       break;
0407     }
0408 
0409     case ScoreTqReqSurrenderMrsp_Post_Dequeue_NA:
0410       break;
0411   }
0412 }
0413 
0414 static void ScoreTqReqSurrenderMrsp_Post_Unblock_Check(
0415   ScoreTqReqSurrenderMrsp_Context     *ctx,
0416   ScoreTqReqSurrenderMrsp_Post_Unblock state
0417 )
0418 {
0419   size_t i;
0420 
0421   i = 0;
0422 
0423   switch ( state ) {
0424     case ScoreTqReqSurrenderMrsp_Post_Unblock_No: {
0425       /*
0426        * The dequeued thread shall not be unblocked by the thread queue
0427        * surrender operation.
0428        */
0429       T_eq_ptr( GetUnblock( ctx, &i ), NULL );
0430       break;
0431     }
0432 
0433     case ScoreTqReqSurrenderMrsp_Post_Unblock_NA:
0434       break;
0435   }
0436 }
0437 
0438 static void ScoreTqReqSurrenderMrsp_Post_PreviousOwnerPriority_Check(
0439   ScoreTqReqSurrenderMrsp_Context                   *ctx,
0440   ScoreTqReqSurrenderMrsp_Post_PreviousOwnerPriority state
0441 )
0442 {
0443   switch ( state ) {
0444     case ScoreTqReqSurrenderMrsp_Post_PreviousOwnerPriority_Drop: {
0445       /*
0446        * Each eligible priority of the previous owner which had the highest
0447        * priority inherited through the thread queue shall be updated.
0448        */
0449       T_eq_u32( ctx->priority_after, PRIO_NORMAL );
0450       break;
0451     }
0452 
0453     case ScoreTqReqSurrenderMrsp_Post_PreviousOwnerPriority_Nop: {
0454       /*
0455        * No eligible priority of the previous owner shall be updated.
0456        */
0457       T_eq_u32( ctx->priority_after, ctx->priority_before );
0458       break;
0459     }
0460 
0461     case ScoreTqReqSurrenderMrsp_Post_PreviousOwnerPriority_NA:
0462       break;
0463   }
0464 }
0465 
0466 static void ScoreTqReqSurrenderMrsp_Post_RemoveHelper_Check(
0467   ScoreTqReqSurrenderMrsp_Context          *ctx,
0468   ScoreTqReqSurrenderMrsp_Post_RemoveHelper state
0469 )
0470 {
0471   rtems_status_code   sc;
0472   rtems_task_priority priority;
0473 
0474   switch ( state ) {
0475     case ScoreTqReqSurrenderMrsp_Post_RemoveHelper_Yes: {
0476       /*
0477        * Each helping scheduler of the previous owner which was only available
0478        * due to a priority inherited through the thread queue shall be removed
0479        * from the previous owner.
0480        */
0481       sc = rtems_task_get_priority(
0482         ctx->previous_owner,
0483         SCHEDULER_B_ID,
0484         &priority
0485       );
0486       T_rsc( sc, RTEMS_NOT_DEFINED );
0487       break;
0488     }
0489 
0490     case ScoreTqReqSurrenderMrsp_Post_RemoveHelper_No: {
0491       /*
0492        * No helping scheduler shall be removed from the previous owner.
0493        */
0494       sc = rtems_task_get_priority(
0495         ctx->previous_owner,
0496         SCHEDULER_B_ID,
0497         &priority
0498       );
0499       #if defined(RTEMS_SMP)
0500       T_rsc_success( sc );
0501 
0502       if ( ctx->tq_ctx->enqueue_variant == TQ_ENQUEUE_STICKY ) {
0503         T_eq_u32( priority, PRIO_LOW );
0504       } else {
0505         T_eq_u32( priority, PRIO_HIGH );
0506       }
0507       #else
0508       T_rsc( sc, RTEMS_INVALID_ID );
0509       #endif
0510       break;
0511     }
0512 
0513     case ScoreTqReqSurrenderMrsp_Post_RemoveHelper_NA:
0514       break;
0515   }
0516 }
0517 
0518 static void ScoreTqReqSurrenderMrsp_Post_AddHelper_Check(
0519   ScoreTqReqSurrenderMrsp_Context       *ctx,
0520   ScoreTqReqSurrenderMrsp_Post_AddHelper state
0521 )
0522 {
0523   rtems_status_code   sc;
0524   rtems_task_priority priority;
0525 
0526   switch ( state ) {
0527     case ScoreTqReqSurrenderMrsp_Post_AddHelper_Yes: {
0528       /*
0529        * Each helping scheduler of the new owner which is only available due to
0530        * a priority inherited through the thread queue shall be added to the
0531        * new owner.
0532        */
0533       sc = rtems_task_get_priority(
0534         ctx->tq_ctx->worker_id[ TQ_BLOCKER_A ],
0535         SCHEDULER_A_ID,
0536         &priority
0537       );
0538       T_rsc_success( sc );
0539 
0540       if ( ctx->tq_ctx->enqueue_variant == TQ_ENQUEUE_STICKY ) {
0541         T_eq_u32( priority, PRIO_VERY_HIGH );
0542       } else {
0543         T_eq_u32( priority, PRIO_LOW );
0544       }
0545       break;
0546     }
0547 
0548     case ScoreTqReqSurrenderMrsp_Post_AddHelper_No: {
0549       /*
0550        * No helping scheduler shall added to the new owner.
0551        */
0552       sc = rtems_task_get_priority(
0553         ctx->tq_ctx->worker_id[ TQ_BLOCKER_A ],
0554         SCHEDULER_A_ID,
0555         &priority
0556       );
0557       #if defined(RTEMS_SMP)
0558       T_rsc( sc, RTEMS_NOT_DEFINED );
0559       #else
0560       T_rsc_success( sc );
0561       T_eq_u32( priority, PRIO_HIGH );
0562       #endif
0563       break;
0564     }
0565 
0566     case ScoreTqReqSurrenderMrsp_Post_AddHelper_NA:
0567       break;
0568   }
0569 }
0570 
0571 static void ScoreTqReqSurrenderMrsp_Post_Suspended_Check(
0572   ScoreTqReqSurrenderMrsp_Context       *ctx,
0573   ScoreTqReqSurrenderMrsp_Post_Suspended state
0574 )
0575 {
0576   switch ( state ) {
0577     case ScoreTqReqSurrenderMrsp_Post_Suspended_Yes: {
0578       /*
0579        * The new owner shall be suspended.
0580        */
0581       T_true( IsTaskSuspended( ctx->tq_ctx->worker_id[ TQ_BLOCKER_A ] ) );
0582       break;
0583     }
0584 
0585     case ScoreTqReqSurrenderMrsp_Post_Suspended_No: {
0586       /*
0587        * The new owner shall be not suspended.
0588        */
0589       T_false( IsTaskSuspended( ctx->tq_ctx->worker_id[ TQ_BLOCKER_A ] ) );
0590       break;
0591     }
0592 
0593     case ScoreTqReqSurrenderMrsp_Post_Suspended_NA:
0594       break;
0595   }
0596 }
0597 
0598 static void ScoreTqReqSurrenderMrsp_Setup(
0599   ScoreTqReqSurrenderMrsp_Context *ctx
0600 )
0601 {
0602   TQReset( ctx->tq_ctx );
0603   TQSetScheduler( ctx->tq_ctx, TQ_BLOCKER_A, SCHEDULER_B_ID, PRIO_NORMAL );
0604   TQSetPriority( ctx->tq_ctx, TQ_BLOCKER_B, PRIO_VERY_HIGH );
0605   TQSetScheduler( ctx->tq_ctx, TQ_BLOCKER_C, SCHEDULER_B_ID, PRIO_LOW );
0606   TQSetPriority( ctx->tq_ctx, TQ_BLOCKER_D, PRIO_VERY_HIGH );
0607   TQSetPriority( ctx->tq_ctx, TQ_HELPER_A, PRIO_NORMAL );
0608 }
0609 
0610 static void ScoreTqReqSurrenderMrsp_Setup_Wrap( void *arg )
0611 {
0612   ScoreTqReqSurrenderMrsp_Context *ctx;
0613 
0614   ctx = arg;
0615   ctx->Map.in_action_loop = false;
0616   ScoreTqReqSurrenderMrsp_Setup( ctx );
0617 }
0618 
0619 static void ScoreTqReqSurrenderMrsp_Teardown(
0620   ScoreTqReqSurrenderMrsp_Context *ctx
0621 )
0622 {
0623   SetSelfScheduler( SCHEDULER_A_ID, PRIO_NORMAL );
0624 }
0625 
0626 static void ScoreTqReqSurrenderMrsp_Teardown_Wrap( void *arg )
0627 {
0628   ScoreTqReqSurrenderMrsp_Context *ctx;
0629 
0630   ctx = arg;
0631   ctx->Map.in_action_loop = false;
0632   ScoreTqReqSurrenderMrsp_Teardown( ctx );
0633 }
0634 
0635 static void ScoreTqReqSurrenderMrsp_Prepare(
0636   ScoreTqReqSurrenderMrsp_Context *ctx
0637 )
0638 {
0639   ctx->inherited_priorities_are_dispensible = true;
0640   ctx->helping_schedules_are_dispensible = true;
0641   ctx->use_helping_scheduler = false;
0642   ctx->gains_new_helping_scheduler = false;
0643   ctx->intend_to_block = false;
0644 }
0645 
0646 static void ScoreTqReqSurrenderMrsp_Action(
0647   ScoreTqReqSurrenderMrsp_Context *ctx
0648 )
0649 {
0650   ctx->previous_owner = ctx->tq_ctx->worker_id[ TQ_HELPER_A ];
0651 
0652   SetSelfPriority( PRIO_LOW );
0653 
0654   if (
0655     ctx->inherited_priorities_are_dispensible ||
0656     ctx->helping_schedules_are_dispensible
0657   ) {
0658     TQSend( ctx->tq_ctx, TQ_HELPER_A, TQ_EVENT_MUTEX_A_OBTAIN );
0659 
0660     if ( ctx->inherited_priorities_are_dispensible ) {
0661       TQSend( ctx->tq_ctx, TQ_BLOCKER_B, TQ_EVENT_MUTEX_A_OBTAIN );
0662     }
0663 
0664     if ( ctx->helping_schedules_are_dispensible ) {
0665       TQSendAndWaitForExecutionStop(
0666         ctx->tq_ctx,
0667         TQ_BLOCKER_C,
0668         TQ_EVENT_MUTEX_A_OBTAIN
0669       );
0670     }
0671   }
0672 
0673   /*
0674    * Take only the priorities into account which are inherited from the
0675    * priority inheritance mutex.  This avoids having to deal with the ceiling
0676    * priority.
0677    */
0678   ctx->priority_before = TQGetPriority( ctx->tq_ctx, TQ_HELPER_A );
0679 
0680   SetSelfScheduler( SCHEDULER_B_ID, PRIO_ULTRA_HIGH );
0681   ctx->tq_ctx->busy_wait[ TQ_HELPER_A ] = true;
0682   TQSendAndSynchronizeRunner(
0683     ctx->tq_ctx,
0684     TQ_HELPER_A,
0685     TQ_EVENT_ENQUEUE | TQ_EVENT_BUSY_WAIT
0686   );
0687   SetSelfScheduler( SCHEDULER_A_ID, PRIO_ULTRA_HIGH );
0688 
0689   TQSendAndWaitForIntendToBlock(
0690     ctx->tq_ctx,
0691     TQ_BLOCKER_A,
0692     TQ_EVENT_ENQUEUE
0693   );
0694 
0695   SetSelfScheduler( SCHEDULER_B_ID, PRIO_ULTRA_HIGH );
0696 
0697   if ( ctx->gains_new_helping_scheduler ) {
0698     TQSend(
0699       ctx->tq_ctx,
0700       TQ_BLOCKER_D,
0701       TQ_EVENT_ENQUEUE
0702     );
0703     YieldTask( ctx->tq_ctx->worker_id[ TQ_HELPER_A ] );
0704     TQWaitForEventsReceived( ctx->tq_ctx, TQ_BLOCKER_D );
0705     TQWaitForIntendToBlock( ctx->tq_ctx, TQ_BLOCKER_D );
0706     YieldTask( ctx->tq_ctx->worker_id[ TQ_BLOCKER_D ] );
0707   }
0708 
0709   if ( ctx->use_helping_scheduler ) {
0710     SetSelfScheduler( SCHEDULER_A_ID, PRIO_ULTRA_HIGH );
0711     WaitForHeir( 1, ctx->tq_ctx->worker_id[ TQ_HELPER_A ] );
0712   }
0713 
0714   if ( ctx->suspended ) {
0715     SuspendTask( ctx->tq_ctx->worker_id[ TQ_BLOCKER_A ] );
0716   }
0717 
0718   ctx->tq_ctx->busy_wait[ TQ_HELPER_A ] = false;
0719   TQSendAndWaitForExecutionStop(
0720     ctx->tq_ctx,
0721     TQ_HELPER_A,
0722     TQ_EVENT_SCHEDULER_RECORD_START |
0723       TQ_EVENT_SURRENDER
0724   );
0725   TQSchedulerRecordStop( ctx->tq_ctx );
0726   T_eq_ptr(
0727     TQGetOwner( ctx->tq_ctx ),
0728     ctx->tq_ctx->worker_tcb[ TQ_BLOCKER_A ]
0729   );
0730   ctx->priority_after = TQGetPriority( ctx->tq_ctx, TQ_HELPER_A );
0731 }
0732 
0733 static void ScoreTqReqSurrenderMrsp_Cleanup(
0734   ScoreTqReqSurrenderMrsp_Context *ctx
0735 )
0736 {
0737   SetSelfScheduler( SCHEDULER_A_ID, PRIO_ULTRA_HIGH );
0738 
0739   if ( ctx->suspended ) {
0740     ResumeTask( ctx->tq_ctx->worker_id[ TQ_BLOCKER_A ] );
0741   }
0742 
0743   TQSendAndSynchronizeRunner(
0744     ctx->tq_ctx,
0745     TQ_BLOCKER_A,
0746     TQ_EVENT_SURRENDER
0747   );
0748 
0749   if ( ctx->gains_new_helping_scheduler ) {
0750     TQSendAndSynchronizeRunner(
0751       ctx->tq_ctx,
0752       TQ_BLOCKER_D,
0753       TQ_EVENT_SURRENDER
0754     );
0755   }
0756 
0757   if (
0758     ctx->inherited_priorities_are_dispensible ||
0759     ctx->helping_schedules_are_dispensible
0760   ) {
0761     TQSendAndSynchronizeRunner(
0762       ctx->tq_ctx,
0763       TQ_HELPER_A,
0764       TQ_EVENT_MUTEX_A_RELEASE
0765     );
0766 
0767     if ( ctx->inherited_priorities_are_dispensible ) {
0768       TQSendAndSynchronizeRunner(
0769         ctx->tq_ctx,
0770         TQ_BLOCKER_B,
0771         TQ_EVENT_MUTEX_A_RELEASE
0772       );
0773     }
0774 
0775     if ( ctx->helping_schedules_are_dispensible ) {
0776       TQSendAndSynchronizeRunner(
0777         ctx->tq_ctx,
0778         TQ_BLOCKER_C,
0779         TQ_EVENT_MUTEX_A_RELEASE
0780       );
0781     }
0782   }
0783 
0784   T_eq_u32( rtems_scheduler_get_processor(), 0 );
0785 }
0786 
0787 static const ScoreTqReqSurrenderMrsp_Entry
0788 ScoreTqReqSurrenderMrsp_Entries[] = {
0789   { 0, 0, 0, 0, 0, 0, 0, ScoreTqReqSurrenderMrsp_Post_Dequeue_Priority,
0790     ScoreTqReqSurrenderMrsp_Post_Unblock_No,
0791     ScoreTqReqSurrenderMrsp_Post_PreviousOwnerPriority_Drop,
0792     ScoreTqReqSurrenderMrsp_Post_RemoveHelper_Yes,
0793     ScoreTqReqSurrenderMrsp_Post_AddHelper_Yes,
0794     ScoreTqReqSurrenderMrsp_Post_Suspended_Yes },
0795   { 0, 0, 0, 0, 0, 0, 0, ScoreTqReqSurrenderMrsp_Post_Dequeue_Priority,
0796     ScoreTqReqSurrenderMrsp_Post_Unblock_No,
0797     ScoreTqReqSurrenderMrsp_Post_PreviousOwnerPriority_Drop,
0798     ScoreTqReqSurrenderMrsp_Post_RemoveHelper_Yes,
0799     ScoreTqReqSurrenderMrsp_Post_AddHelper_Yes,
0800     ScoreTqReqSurrenderMrsp_Post_Suspended_No },
0801   { 0, 0, 0, 0, 0, 0, 0, ScoreTqReqSurrenderMrsp_Post_Dequeue_Priority,
0802     ScoreTqReqSurrenderMrsp_Post_Unblock_No,
0803     ScoreTqReqSurrenderMrsp_Post_PreviousOwnerPriority_Drop,
0804     ScoreTqReqSurrenderMrsp_Post_RemoveHelper_Yes,
0805     ScoreTqReqSurrenderMrsp_Post_AddHelper_No,
0806     ScoreTqReqSurrenderMrsp_Post_Suspended_Yes },
0807   { 0, 0, 0, 0, 0, 0, 0, ScoreTqReqSurrenderMrsp_Post_Dequeue_Priority,
0808     ScoreTqReqSurrenderMrsp_Post_Unblock_No,
0809     ScoreTqReqSurrenderMrsp_Post_PreviousOwnerPriority_Drop,
0810     ScoreTqReqSurrenderMrsp_Post_RemoveHelper_Yes,
0811     ScoreTqReqSurrenderMrsp_Post_AddHelper_No,
0812     ScoreTqReqSurrenderMrsp_Post_Suspended_No },
0813   { 0, 0, 0, 0, 0, 0, 0, ScoreTqReqSurrenderMrsp_Post_Dequeue_Priority,
0814     ScoreTqReqSurrenderMrsp_Post_Unblock_No,
0815     ScoreTqReqSurrenderMrsp_Post_PreviousOwnerPriority_Drop,
0816     ScoreTqReqSurrenderMrsp_Post_RemoveHelper_No,
0817     ScoreTqReqSurrenderMrsp_Post_AddHelper_Yes,
0818     ScoreTqReqSurrenderMrsp_Post_Suspended_Yes },
0819   { 0, 0, 0, 0, 0, 0, 0, ScoreTqReqSurrenderMrsp_Post_Dequeue_Priority,
0820     ScoreTqReqSurrenderMrsp_Post_Unblock_No,
0821     ScoreTqReqSurrenderMrsp_Post_PreviousOwnerPriority_Drop,
0822     ScoreTqReqSurrenderMrsp_Post_RemoveHelper_No,
0823     ScoreTqReqSurrenderMrsp_Post_AddHelper_Yes,
0824     ScoreTqReqSurrenderMrsp_Post_Suspended_No },
0825   { 0, 0, 0, 0, 0, 0, 0, ScoreTqReqSurrenderMrsp_Post_Dequeue_Priority,
0826     ScoreTqReqSurrenderMrsp_Post_Unblock_No,
0827     ScoreTqReqSurrenderMrsp_Post_PreviousOwnerPriority_Drop,
0828     ScoreTqReqSurrenderMrsp_Post_RemoveHelper_No,
0829     ScoreTqReqSurrenderMrsp_Post_AddHelper_No,
0830     ScoreTqReqSurrenderMrsp_Post_Suspended_Yes },
0831   { 0, 0, 0, 0, 0, 0, 0, ScoreTqReqSurrenderMrsp_Post_Dequeue_Priority,
0832     ScoreTqReqSurrenderMrsp_Post_Unblock_No,
0833     ScoreTqReqSurrenderMrsp_Post_PreviousOwnerPriority_Drop,
0834     ScoreTqReqSurrenderMrsp_Post_RemoveHelper_No,
0835     ScoreTqReqSurrenderMrsp_Post_AddHelper_No,
0836     ScoreTqReqSurrenderMrsp_Post_Suspended_No },
0837   { 0, 0, 0, 0, 0, 0, 0, ScoreTqReqSurrenderMrsp_Post_Dequeue_Priority,
0838     ScoreTqReqSurrenderMrsp_Post_Unblock_No,
0839     ScoreTqReqSurrenderMrsp_Post_PreviousOwnerPriority_Nop,
0840     ScoreTqReqSurrenderMrsp_Post_RemoveHelper_Yes,
0841     ScoreTqReqSurrenderMrsp_Post_AddHelper_Yes,
0842     ScoreTqReqSurrenderMrsp_Post_Suspended_Yes },
0843   { 0, 0, 0, 0, 0, 0, 0, ScoreTqReqSurrenderMrsp_Post_Dequeue_Priority,
0844     ScoreTqReqSurrenderMrsp_Post_Unblock_No,
0845     ScoreTqReqSurrenderMrsp_Post_PreviousOwnerPriority_Nop,
0846     ScoreTqReqSurrenderMrsp_Post_RemoveHelper_Yes,
0847     ScoreTqReqSurrenderMrsp_Post_AddHelper_Yes,
0848     ScoreTqReqSurrenderMrsp_Post_Suspended_No },
0849   { 0, 0, 0, 0, 0, 0, 0, ScoreTqReqSurrenderMrsp_Post_Dequeue_Priority,
0850     ScoreTqReqSurrenderMrsp_Post_Unblock_No,
0851     ScoreTqReqSurrenderMrsp_Post_PreviousOwnerPriority_Nop,
0852     ScoreTqReqSurrenderMrsp_Post_RemoveHelper_Yes,
0853     ScoreTqReqSurrenderMrsp_Post_AddHelper_No,
0854     ScoreTqReqSurrenderMrsp_Post_Suspended_Yes },
0855   { 0, 0, 0, 0, 0, 0, 0, ScoreTqReqSurrenderMrsp_Post_Dequeue_Priority,
0856     ScoreTqReqSurrenderMrsp_Post_Unblock_No,
0857     ScoreTqReqSurrenderMrsp_Post_PreviousOwnerPriority_Nop,
0858     ScoreTqReqSurrenderMrsp_Post_RemoveHelper_Yes,
0859     ScoreTqReqSurrenderMrsp_Post_AddHelper_No,
0860     ScoreTqReqSurrenderMrsp_Post_Suspended_No },
0861   { 0, 0, 0, 0, 0, 0, 0, ScoreTqReqSurrenderMrsp_Post_Dequeue_Priority,
0862     ScoreTqReqSurrenderMrsp_Post_Unblock_No,
0863     ScoreTqReqSurrenderMrsp_Post_PreviousOwnerPriority_Nop,
0864     ScoreTqReqSurrenderMrsp_Post_RemoveHelper_No,
0865     ScoreTqReqSurrenderMrsp_Post_AddHelper_Yes,
0866     ScoreTqReqSurrenderMrsp_Post_Suspended_Yes },
0867   { 0, 0, 0, 0, 0, 0, 0, ScoreTqReqSurrenderMrsp_Post_Dequeue_Priority,
0868     ScoreTqReqSurrenderMrsp_Post_Unblock_No,
0869     ScoreTqReqSurrenderMrsp_Post_PreviousOwnerPriority_Nop,
0870     ScoreTqReqSurrenderMrsp_Post_RemoveHelper_No,
0871     ScoreTqReqSurrenderMrsp_Post_AddHelper_Yes,
0872     ScoreTqReqSurrenderMrsp_Post_Suspended_No },
0873   { 0, 0, 0, 0, 0, 0, 0, ScoreTqReqSurrenderMrsp_Post_Dequeue_Priority,
0874     ScoreTqReqSurrenderMrsp_Post_Unblock_No,
0875     ScoreTqReqSurrenderMrsp_Post_PreviousOwnerPriority_Nop,
0876     ScoreTqReqSurrenderMrsp_Post_RemoveHelper_No,
0877     ScoreTqReqSurrenderMrsp_Post_AddHelper_No,
0878     ScoreTqReqSurrenderMrsp_Post_Suspended_Yes },
0879   { 0, 0, 0, 0, 0, 0, 0, ScoreTqReqSurrenderMrsp_Post_Dequeue_Priority,
0880     ScoreTqReqSurrenderMrsp_Post_Unblock_No,
0881     ScoreTqReqSurrenderMrsp_Post_PreviousOwnerPriority_Nop,
0882     ScoreTqReqSurrenderMrsp_Post_RemoveHelper_No,
0883     ScoreTqReqSurrenderMrsp_Post_AddHelper_No,
0884     ScoreTqReqSurrenderMrsp_Post_Suspended_No }
0885 };
0886 
0887 static const uint8_t
0888 ScoreTqReqSurrenderMrsp_Map[] = {
0889   0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 4, 5, 6, 7, 8, 9, 10, 11, 8, 9, 10, 11,
0890   12, 13, 14, 15, 12, 13, 14, 15
0891 };
0892 
0893 static size_t ScoreTqReqSurrenderMrsp_Scope( void *arg, char *buf, size_t n )
0894 {
0895   ScoreTqReqSurrenderMrsp_Context *ctx;
0896 
0897   ctx = arg;
0898 
0899   if ( ctx->Map.in_action_loop ) {
0900     return T_get_scope(
0901       ScoreTqReqSurrenderMrsp_PreDesc,
0902       buf,
0903       n,
0904       ctx->Map.pcs
0905     );
0906   }
0907 
0908   return 0;
0909 }
0910 
0911 static T_fixture ScoreTqReqSurrenderMrsp_Fixture = {
0912   .setup = ScoreTqReqSurrenderMrsp_Setup_Wrap,
0913   .stop = NULL,
0914   .teardown = ScoreTqReqSurrenderMrsp_Teardown_Wrap,
0915   .scope = ScoreTqReqSurrenderMrsp_Scope,
0916   .initial_context = &ScoreTqReqSurrenderMrsp_Instance
0917 };
0918 
0919 static inline ScoreTqReqSurrenderMrsp_Entry ScoreTqReqSurrenderMrsp_PopEntry(
0920   ScoreTqReqSurrenderMrsp_Context *ctx
0921 )
0922 {
0923   size_t index;
0924 
0925   index = ctx->Map.index;
0926   ctx->Map.index = index + 1;
0927   return ScoreTqReqSurrenderMrsp_Entries[
0928     ScoreTqReqSurrenderMrsp_Map[ index ]
0929   ];
0930 }
0931 
0932 static void ScoreTqReqSurrenderMrsp_TestVariant(
0933   ScoreTqReqSurrenderMrsp_Context *ctx
0934 )
0935 {
0936   ScoreTqReqSurrenderMrsp_Pre_InheritedPriority_Prepare(
0937     ctx,
0938     ctx->Map.pcs[ 0 ]
0939   );
0940   ScoreTqReqSurrenderMrsp_Pre_PreviousHelping_Prepare(
0941     ctx,
0942     ctx->Map.pcs[ 1 ]
0943   );
0944   ScoreTqReqSurrenderMrsp_Pre_Scheduler_Prepare( ctx, ctx->Map.pcs[ 2 ] );
0945   ScoreTqReqSurrenderMrsp_Pre_NewHelping_Prepare( ctx, ctx->Map.pcs[ 3 ] );
0946   ScoreTqReqSurrenderMrsp_Pre_Suspended_Prepare( ctx, ctx->Map.pcs[ 4 ] );
0947   ScoreTqReqSurrenderMrsp_Pre_WaitState_Prepare( ctx, ctx->Map.pcs[ 5 ] );
0948   ScoreTqReqSurrenderMrsp_Action( ctx );
0949   ScoreTqReqSurrenderMrsp_Post_Dequeue_Check(
0950     ctx,
0951     ctx->Map.entry.Post_Dequeue
0952   );
0953   ScoreTqReqSurrenderMrsp_Post_Unblock_Check(
0954     ctx,
0955     ctx->Map.entry.Post_Unblock
0956   );
0957   ScoreTqReqSurrenderMrsp_Post_PreviousOwnerPriority_Check(
0958     ctx,
0959     ctx->Map.entry.Post_PreviousOwnerPriority
0960   );
0961   ScoreTqReqSurrenderMrsp_Post_RemoveHelper_Check(
0962     ctx,
0963     ctx->Map.entry.Post_RemoveHelper
0964   );
0965   ScoreTqReqSurrenderMrsp_Post_AddHelper_Check(
0966     ctx,
0967     ctx->Map.entry.Post_AddHelper
0968   );
0969   ScoreTqReqSurrenderMrsp_Post_Suspended_Check(
0970     ctx,
0971     ctx->Map.entry.Post_Suspended
0972   );
0973 }
0974 
0975 static T_fixture_node ScoreTqReqSurrenderMrsp_Node;
0976 
0977 static T_remark ScoreTqReqSurrenderMrsp_Remark = {
0978   .next = NULL,
0979   .remark = "ScoreTqReqSurrenderMrsp"
0980 };
0981 
0982 void ScoreTqReqSurrenderMrsp_Run( TQContext *tq_ctx )
0983 {
0984   ScoreTqReqSurrenderMrsp_Context *ctx;
0985 
0986   ctx = &ScoreTqReqSurrenderMrsp_Instance;
0987   ctx->tq_ctx = tq_ctx;
0988 
0989   ctx = T_push_fixture(
0990     &ScoreTqReqSurrenderMrsp_Node,
0991     &ScoreTqReqSurrenderMrsp_Fixture
0992   );
0993   ctx->Map.in_action_loop = true;
0994   ctx->Map.index = 0;
0995 
0996   for (
0997     ctx->Map.pcs[ 0 ] = ScoreTqReqSurrenderMrsp_Pre_InheritedPriority_Vital;
0998     ctx->Map.pcs[ 0 ] < ScoreTqReqSurrenderMrsp_Pre_InheritedPriority_NA;
0999     ++ctx->Map.pcs[ 0 ]
1000   ) {
1001     for (
1002       ctx->Map.pcs[ 1 ] = ScoreTqReqSurrenderMrsp_Pre_PreviousHelping_Vital;
1003       ctx->Map.pcs[ 1 ] < ScoreTqReqSurrenderMrsp_Pre_PreviousHelping_NA;
1004       ++ctx->Map.pcs[ 1 ]
1005     ) {
1006       for (
1007         ctx->Map.pcs[ 2 ] = ScoreTqReqSurrenderMrsp_Pre_Scheduler_Home;
1008         ctx->Map.pcs[ 2 ] < ScoreTqReqSurrenderMrsp_Pre_Scheduler_NA;
1009         ++ctx->Map.pcs[ 2 ]
1010       ) {
1011         for (
1012           ctx->Map.pcs[ 3 ] = ScoreTqReqSurrenderMrsp_Pre_NewHelping_Vital;
1013           ctx->Map.pcs[ 3 ] < ScoreTqReqSurrenderMrsp_Pre_NewHelping_NA;
1014           ++ctx->Map.pcs[ 3 ]
1015         ) {
1016           for (
1017             ctx->Map.pcs[ 4 ] = ScoreTqReqSurrenderMrsp_Pre_Suspended_Yes;
1018             ctx->Map.pcs[ 4 ] < ScoreTqReqSurrenderMrsp_Pre_Suspended_NA;
1019             ++ctx->Map.pcs[ 4 ]
1020           ) {
1021             for (
1022               ctx->Map.pcs[ 5 ] = ScoreTqReqSurrenderMrsp_Pre_WaitState_IntendToBlock;
1023               ctx->Map.pcs[ 5 ] < ScoreTqReqSurrenderMrsp_Pre_WaitState_NA;
1024               ++ctx->Map.pcs[ 5 ]
1025             ) {
1026               ctx->Map.entry = ScoreTqReqSurrenderMrsp_PopEntry( ctx );
1027               ScoreTqReqSurrenderMrsp_Prepare( ctx );
1028               ScoreTqReqSurrenderMrsp_TestVariant( ctx );
1029               ScoreTqReqSurrenderMrsp_Cleanup( ctx );
1030             }
1031           }
1032         }
1033       }
1034     }
1035   }
1036 
1037   T_add_remark( &ScoreTqReqSurrenderMrsp_Remark );
1038   T_pop_fixture();
1039 }
1040 
1041 /** @} */