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 ScoreTqReqTimeoutMrsp
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/smpimpl.h>
0056 #include <rtems/score/threadimpl.h>
0057 
0058 #include "tr-tq-timeout-mrsp.h"
0059 #include "tx-support.h"
0060 
0061 #include <rtems/test.h>
0062 
0063 /**
0064  * @defgroup ScoreTqReqTimeoutMrsp spec:/score/tq/req/timeout-mrsp
0065  *
0066  * @ingroup TestsuitesValidationNoClock0
0067  *
0068  * @{
0069  */
0070 
0071 typedef struct {
0072   uint8_t Skip : 1;
0073   uint8_t Pre_Scheduler_NA : 1;
0074   uint8_t Pre_WaitState_NA : 1;
0075   uint8_t Post_Status : 2;
0076   uint8_t Post_Unblock : 1;
0077 } ScoreTqReqTimeoutMrsp_Entry;
0078 
0079 /**
0080  * @brief Test context for spec:/score/tq/req/timeout-mrsp test case.
0081  */
0082 typedef struct {
0083   /**
0084    * @brief If this member is true, then the enqueued thread shall use a home
0085    *   scheduler other than the home scheduler of the owner.
0086    */
0087   bool other_scheduler;
0088 
0089   /**
0090    * @brief If this member is true, then the processor set of the schedulers
0091    *   shall be restored.
0092    */
0093   bool restore_scheduler;
0094 
0095   /**
0096    * @brief This member contains a copy of the corresponding
0097    *   ScoreTqReqTimeoutMrsp_Run() parameter.
0098    */
0099   TQContext *tq_ctx;
0100 
0101   struct {
0102     /**
0103      * @brief This member defines the pre-condition states for the next action.
0104      */
0105     size_t pcs[ 2 ];
0106 
0107     /**
0108      * @brief If this member is true, then the test action loop is executed.
0109      */
0110     bool in_action_loop;
0111 
0112     /**
0113      * @brief This member contains the next transition map index.
0114      */
0115     size_t index;
0116 
0117     /**
0118      * @brief This member contains the current transition map entry.
0119      */
0120     ScoreTqReqTimeoutMrsp_Entry entry;
0121 
0122     /**
0123      * @brief If this member is true, then the current transition variant
0124      *   should be skipped.
0125      */
0126     bool skip;
0127   } Map;
0128 } ScoreTqReqTimeoutMrsp_Context;
0129 
0130 static ScoreTqReqTimeoutMrsp_Context
0131   ScoreTqReqTimeoutMrsp_Instance;
0132 
0133 static const char * const ScoreTqReqTimeoutMrsp_PreDesc_Scheduler[] = {
0134   "Same",
0135   "Other",
0136   "NA"
0137 };
0138 
0139 static const char * const ScoreTqReqTimeoutMrsp_PreDesc_WaitState[] = {
0140   "IntendToBlock",
0141   "ReadyAgain",
0142   "NA"
0143 };
0144 
0145 static const char * const * const ScoreTqReqTimeoutMrsp_PreDesc[] = {
0146   ScoreTqReqTimeoutMrsp_PreDesc_Scheduler,
0147   ScoreTqReqTimeoutMrsp_PreDesc_WaitState,
0148   NULL
0149 };
0150 
0151 typedef ScoreTqReqTimeoutMrsp_Context Context;
0152 
0153 static const rtems_tcb *GetUnblock( Context *ctx, size_t *index )
0154 {
0155   return TQGetNextUnblock( ctx->tq_ctx, index )->thread;
0156 }
0157 
0158 static void Tick( void *arg )
0159 {
0160   Context *ctx;
0161 
0162   ctx = arg;
0163   TQSchedulerRecordStart( ctx->tq_ctx );
0164   FinalClockTick();
0165   TQSchedulerRecordStop( ctx->tq_ctx );
0166 }
0167 
0168 static void ScoreTqReqTimeoutMrsp_Pre_Scheduler_Prepare(
0169   ScoreTqReqTimeoutMrsp_Context      *ctx,
0170   ScoreTqReqTimeoutMrsp_Pre_Scheduler state
0171 )
0172 {
0173   switch ( state ) {
0174     case ScoreTqReqTimeoutMrsp_Pre_Scheduler_Same: {
0175       /*
0176        * While the home scheduler of the thread is equal to the home scheduler
0177        * of the thread queue owner.
0178        */
0179       ctx->other_scheduler = false;
0180 
0181       TQSetScheduler(
0182         ctx->tq_ctx,
0183         TQ_BLOCKER_A,
0184         SCHEDULER_A_ID,
0185         PRIO_LOW
0186       );
0187       RemoveProcessor( SCHEDULER_B_ID, 1 );
0188       AddProcessor( SCHEDULER_A_ID, 1 );
0189       ctx->restore_scheduler = true;
0190       break;
0191     }
0192 
0193     case ScoreTqReqTimeoutMrsp_Pre_Scheduler_Other: {
0194       /*
0195        * While the home scheduler of the thread is not equal to the home
0196        * scheduler of the thread queue owner.
0197        */
0198       ctx->other_scheduler = true;
0199 
0200       TQSetScheduler(
0201         ctx->tq_ctx,
0202         TQ_BLOCKER_A,
0203         SCHEDULER_B_ID,
0204         PRIO_NORMAL
0205       );
0206       break;
0207     }
0208 
0209     case ScoreTqReqTimeoutMrsp_Pre_Scheduler_NA:
0210       break;
0211   }
0212 }
0213 
0214 static void ScoreTqReqTimeoutMrsp_Pre_WaitState_Prepare(
0215   ScoreTqReqTimeoutMrsp_Context      *ctx,
0216   ScoreTqReqTimeoutMrsp_Pre_WaitState state
0217 )
0218 {
0219   switch ( state ) {
0220     case ScoreTqReqTimeoutMrsp_Pre_WaitState_IntendToBlock: {
0221       /*
0222        * While the thread of the timeout operation is in the intend to block
0223        * wait state.
0224        */
0225       Per_CPU_Control *cpu;
0226 
0227       TQEnqueuePrepare( ctx->tq_ctx );
0228       TQSendAndWaitForIntendToBlock(
0229         ctx->tq_ctx,
0230         TQ_BLOCKER_A,
0231         TQ_EVENT_ENQUEUE
0232       );
0233       cpu = _Thread_Get_CPU( ctx->tq_ctx->worker_tcb[ TQ_BLOCKER_A ] );
0234 
0235       /*
0236        * We have to make sure that the worker thread inserted its thread
0237        * timer.  Checking the intend to block wait state is not enough to
0238        * ensure this.
0239        */
0240       while ( cpu->thread_dispatch_disable_level != 0 ) {
0241         /* Wait */
0242       }
0243 
0244       Tick( ctx );
0245       WaitForExecutionStop( ctx->tq_ctx->worker_id[ TQ_BLOCKER_A ] );
0246       TQEnqueueDone( ctx->tq_ctx );
0247       break;
0248     }
0249 
0250     case ScoreTqReqTimeoutMrsp_Pre_WaitState_ReadyAgain: {
0251       /*
0252        * While the thread of the timeout operation is in the ready again wait
0253        * state.
0254        */
0255       TQEnqueuePrepare( ctx->tq_ctx );
0256       TQSendAndWaitForIntendToBlock(
0257         ctx->tq_ctx,
0258         TQ_BLOCKER_A,
0259         TQ_EVENT_ENQUEUE | TQ_EVENT_TIMEOUT | TQ_EVENT_SURRENDER |
0260           TQ_EVENT_SCHEDULER_RECORD_STOP
0261       );
0262       TQSchedulerRecordStart( ctx->tq_ctx );
0263       TQEnqueueDone( ctx->tq_ctx );
0264       WaitForExecutionStop( ctx->tq_ctx->worker_id[ TQ_BLOCKER_A ] );
0265       break;
0266     }
0267 
0268     case ScoreTqReqTimeoutMrsp_Pre_WaitState_NA:
0269       break;
0270   }
0271 }
0272 
0273 static void ScoreTqReqTimeoutMrsp_Post_Status_Check(
0274   ScoreTqReqTimeoutMrsp_Context    *ctx,
0275   ScoreTqReqTimeoutMrsp_Post_Status state
0276 )
0277 {
0278   switch ( state ) {
0279     case ScoreTqReqTimeoutMrsp_Post_Status_Ok: {
0280       /*
0281        * The return status of the directive call shall be derived from
0282        * STATUS_SUCCESSFUL.
0283        */
0284       T_eq_int(
0285         ctx->tq_ctx->status[ TQ_BLOCKER_A ],
0286         TQConvertStatus( ctx->tq_ctx, STATUS_SUCCESSFUL )
0287       );
0288       break;
0289     }
0290 
0291     case ScoreTqReqTimeoutMrsp_Post_Status_Timeout: {
0292       /*
0293        * The return status of the directive call shall be derived from
0294        * STATUS_TIMEOUT.
0295        */
0296       T_eq_int(
0297         ctx->tq_ctx->status[ TQ_BLOCKER_A ],
0298         TQConvertStatus( ctx->tq_ctx, STATUS_TIMEOUT )
0299       );
0300       break;
0301     }
0302 
0303     case ScoreTqReqTimeoutMrsp_Post_Status_NA:
0304       break;
0305   }
0306 }
0307 
0308 static void ScoreTqReqTimeoutMrsp_Post_Unblock_Check(
0309   ScoreTqReqTimeoutMrsp_Context     *ctx,
0310   ScoreTqReqTimeoutMrsp_Post_Unblock state
0311 )
0312 {
0313   size_t i;
0314 
0315   i = 0;
0316 
0317   switch ( state ) {
0318     case ScoreTqReqTimeoutMrsp_Post_Unblock_No: {
0319       /*
0320        * The thread of the timeout operation shall not be unblocked by the
0321        * timeout operation.
0322        */
0323       T_eq_ptr( GetUnblock( ctx, &i ), NULL );
0324       break;
0325     }
0326 
0327     case ScoreTqReqTimeoutMrsp_Post_Unblock_NA:
0328       break;
0329   }
0330 }
0331 
0332 static void ScoreTqReqTimeoutMrsp_Setup( ScoreTqReqTimeoutMrsp_Context *ctx )
0333 {
0334   TQReset( ctx->tq_ctx );
0335 }
0336 
0337 static void ScoreTqReqTimeoutMrsp_Setup_Wrap( void *arg )
0338 {
0339   ScoreTqReqTimeoutMrsp_Context *ctx;
0340 
0341   ctx = arg;
0342   ctx->Map.in_action_loop = false;
0343   ScoreTqReqTimeoutMrsp_Setup( ctx );
0344 }
0345 
0346 static void ScoreTqReqTimeoutMrsp_Teardown(
0347   ScoreTqReqTimeoutMrsp_Context *ctx
0348 )
0349 {
0350   TQReset( ctx->tq_ctx );
0351 }
0352 
0353 static void ScoreTqReqTimeoutMrsp_Teardown_Wrap( void *arg )
0354 {
0355   ScoreTqReqTimeoutMrsp_Context *ctx;
0356 
0357   ctx = arg;
0358   ctx->Map.in_action_loop = false;
0359   ScoreTqReqTimeoutMrsp_Teardown( ctx );
0360 }
0361 
0362 static void ScoreTqReqTimeoutMrsp_Prepare( ScoreTqReqTimeoutMrsp_Context *ctx )
0363 {
0364   ctx->restore_scheduler = false;
0365 }
0366 
0367 static void ScoreTqReqTimeoutMrsp_Action( ScoreTqReqTimeoutMrsp_Context *ctx )
0368 {
0369   /*
0370    * The action is performed by the ``WaitState`` pre-condition preparation.
0371    */
0372 }
0373 
0374 static void ScoreTqReqTimeoutMrsp_Cleanup( ScoreTqReqTimeoutMrsp_Context *ctx )
0375 {
0376   if ( ctx->restore_scheduler ) {
0377     RemoveProcessor( SCHEDULER_A_ID, 1 );
0378     AddProcessor( SCHEDULER_B_ID, 1 );
0379   }
0380 }
0381 
0382 static const ScoreTqReqTimeoutMrsp_Entry
0383 ScoreTqReqTimeoutMrsp_Entries[] = {
0384   { 0, 0, 0, ScoreTqReqTimeoutMrsp_Post_Status_Timeout,
0385     ScoreTqReqTimeoutMrsp_Post_Unblock_No },
0386   { 0, 0, 0, ScoreTqReqTimeoutMrsp_Post_Status_Ok,
0387     ScoreTqReqTimeoutMrsp_Post_Unblock_No }
0388 };
0389 
0390 static const uint8_t
0391 ScoreTqReqTimeoutMrsp_Map[] = {
0392   0, 1, 0, 1
0393 };
0394 
0395 static size_t ScoreTqReqTimeoutMrsp_Scope( void *arg, char *buf, size_t n )
0396 {
0397   ScoreTqReqTimeoutMrsp_Context *ctx;
0398 
0399   ctx = arg;
0400 
0401   if ( ctx->Map.in_action_loop ) {
0402     return T_get_scope( ScoreTqReqTimeoutMrsp_PreDesc, buf, n, ctx->Map.pcs );
0403   }
0404 
0405   return 0;
0406 }
0407 
0408 static T_fixture ScoreTqReqTimeoutMrsp_Fixture = {
0409   .setup = ScoreTqReqTimeoutMrsp_Setup_Wrap,
0410   .stop = NULL,
0411   .teardown = ScoreTqReqTimeoutMrsp_Teardown_Wrap,
0412   .scope = ScoreTqReqTimeoutMrsp_Scope,
0413   .initial_context = &ScoreTqReqTimeoutMrsp_Instance
0414 };
0415 
0416 static inline ScoreTqReqTimeoutMrsp_Entry ScoreTqReqTimeoutMrsp_PopEntry(
0417   ScoreTqReqTimeoutMrsp_Context *ctx
0418 )
0419 {
0420   size_t index;
0421 
0422   index = ctx->Map.index;
0423   ctx->Map.index = index + 1;
0424   return ScoreTqReqTimeoutMrsp_Entries[
0425     ScoreTqReqTimeoutMrsp_Map[ index ]
0426   ];
0427 }
0428 
0429 static void ScoreTqReqTimeoutMrsp_TestVariant(
0430   ScoreTqReqTimeoutMrsp_Context *ctx
0431 )
0432 {
0433   ScoreTqReqTimeoutMrsp_Pre_Scheduler_Prepare( ctx, ctx->Map.pcs[ 0 ] );
0434   ScoreTqReqTimeoutMrsp_Pre_WaitState_Prepare( ctx, ctx->Map.pcs[ 1 ] );
0435   ScoreTqReqTimeoutMrsp_Action( ctx );
0436   ScoreTqReqTimeoutMrsp_Post_Status_Check( ctx, ctx->Map.entry.Post_Status );
0437   ScoreTqReqTimeoutMrsp_Post_Unblock_Check( ctx, ctx->Map.entry.Post_Unblock );
0438 }
0439 
0440 static T_fixture_node ScoreTqReqTimeoutMrsp_Node;
0441 
0442 static T_remark ScoreTqReqTimeoutMrsp_Remark = {
0443   .next = NULL,
0444   .remark = "ScoreTqReqTimeoutMrsp"
0445 };
0446 
0447 void ScoreTqReqTimeoutMrsp_Run( TQContext *tq_ctx )
0448 {
0449   ScoreTqReqTimeoutMrsp_Context *ctx;
0450 
0451   ctx = &ScoreTqReqTimeoutMrsp_Instance;
0452   ctx->tq_ctx = tq_ctx;
0453 
0454   ctx = T_push_fixture(
0455     &ScoreTqReqTimeoutMrsp_Node,
0456     &ScoreTqReqTimeoutMrsp_Fixture
0457   );
0458   ctx->Map.in_action_loop = true;
0459   ctx->Map.index = 0;
0460 
0461   for (
0462     ctx->Map.pcs[ 0 ] = ScoreTqReqTimeoutMrsp_Pre_Scheduler_Same;
0463     ctx->Map.pcs[ 0 ] < ScoreTqReqTimeoutMrsp_Pre_Scheduler_NA;
0464     ++ctx->Map.pcs[ 0 ]
0465   ) {
0466     for (
0467       ctx->Map.pcs[ 1 ] = ScoreTqReqTimeoutMrsp_Pre_WaitState_IntendToBlock;
0468       ctx->Map.pcs[ 1 ] < ScoreTqReqTimeoutMrsp_Pre_WaitState_NA;
0469       ++ctx->Map.pcs[ 1 ]
0470     ) {
0471       ctx->Map.entry = ScoreTqReqTimeoutMrsp_PopEntry( ctx );
0472       ScoreTqReqTimeoutMrsp_Prepare( ctx );
0473       ScoreTqReqTimeoutMrsp_TestVariant( ctx );
0474       ScoreTqReqTimeoutMrsp_Cleanup( ctx );
0475     }
0476   }
0477 
0478   T_add_remark( &ScoreTqReqTimeoutMrsp_Remark );
0479   T_pop_fixture();
0480 }
0481 
0482 /** @} */