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 ScoreTqReqTimeout
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-timeout.h"
0058 #include "tx-support.h"
0059 
0060 #include <rtems/test.h>
0061 
0062 /**
0063  * @defgroup ScoreTqReqTimeout spec:/score/tq/req/timeout
0064  *
0065  * @ingroup TestsuitesValidationNoClock0
0066  *
0067  * @{
0068  */
0069 
0070 typedef struct {
0071   uint8_t Skip : 1;
0072   uint8_t Pre_WaitState_NA : 1;
0073   uint8_t Post_Status : 2;
0074   uint8_t Post_Unblock : 2;
0075 } ScoreTqReqTimeout_Entry;
0076 
0077 /**
0078  * @brief Test context for spec:/score/tq/req/timeout test case.
0079  */
0080 typedef struct {
0081   /**
0082    * @brief This member contains the call within ISR request.
0083    */
0084   CallWithinISRRequest request;
0085 
0086   /**
0087    * @brief This member contains a copy of the corresponding
0088    *   ScoreTqReqTimeout_Run() parameter.
0089    */
0090   TQContext *tq_ctx;
0091 
0092   struct {
0093     /**
0094      * @brief This member defines the pre-condition states for the next action.
0095      */
0096     size_t pcs[ 1 ];
0097 
0098     /**
0099      * @brief If this member is true, then the test action loop is executed.
0100      */
0101     bool in_action_loop;
0102 
0103     /**
0104      * @brief This member contains the next transition map index.
0105      */
0106     size_t index;
0107 
0108     /**
0109      * @brief This member contains the current transition map entry.
0110      */
0111     ScoreTqReqTimeout_Entry entry;
0112 
0113     /**
0114      * @brief If this member is true, then the current transition variant
0115      *   should be skipped.
0116      */
0117     bool skip;
0118   } Map;
0119 } ScoreTqReqTimeout_Context;
0120 
0121 static ScoreTqReqTimeout_Context
0122   ScoreTqReqTimeout_Instance;
0123 
0124 static const char * const ScoreTqReqTimeout_PreDesc_WaitState[] = {
0125   "Blocked",
0126   "IntendToBlock",
0127   "ReadyAgain",
0128   "NA"
0129 };
0130 
0131 static const char * const * const ScoreTqReqTimeout_PreDesc[] = {
0132   ScoreTqReqTimeout_PreDesc_WaitState,
0133   NULL
0134 };
0135 
0136 typedef ScoreTqReqTimeout_Context Context;
0137 
0138 static const rtems_tcb *GetUnblock( Context *ctx, size_t *index )
0139 {
0140   return TQGetNextUnblock( ctx->tq_ctx, index )->thread;
0141 }
0142 
0143 static const rtems_tcb *GetTCB( Context *ctx, TQWorkerKind worker )
0144 {
0145   return ctx->tq_ctx->worker_tcb[ worker ];
0146 }
0147 
0148 static void Tick( void *arg )
0149 {
0150   Context *ctx;
0151 
0152   ctx = arg;
0153   TQSchedulerRecordStart( ctx->tq_ctx );
0154   FinalClockTick();
0155   TQSchedulerRecordStop( ctx->tq_ctx );
0156 }
0157 
0158 static void SchedulerBlock(
0159   void                    *arg,
0160   const T_scheduler_event *event,
0161   T_scheduler_when         when
0162 )
0163 {
0164   Context *ctx;
0165 
0166   ctx = arg;
0167 
0168   if (
0169     when == T_SCHEDULER_BEFORE &&
0170     event->operation == T_SCHEDULER_BLOCK
0171   ) {
0172     T_scheduler_set_event_handler( NULL, NULL );
0173     ctx->request.handler = Tick;
0174     CallWithinISRSubmit( &ctx->request );
0175   }
0176 }
0177 
0178 static void ThreadTimeout( void *arg )
0179 {
0180   Context *ctx;
0181 
0182   ctx = arg;
0183   TQSchedulerRecordStart( ctx->tq_ctx );
0184   _Thread_Timeout(
0185     &ctx->tq_ctx->worker_tcb[ TQ_BLOCKER_A ]->Timer.Watchdog
0186   );
0187   TQSchedulerRecordStop( ctx->tq_ctx );
0188 }
0189 
0190 static void SchedulerUnblock(
0191   void                    *arg,
0192   const T_scheduler_event *event,
0193   T_scheduler_when         when
0194 )
0195 {
0196   Context *ctx;
0197 
0198   ctx = arg;
0199 
0200   if (
0201     when == T_SCHEDULER_BEFORE &&
0202     event->operation == T_SCHEDULER_UNBLOCK
0203   ) {
0204     T_scheduler_set_event_handler( NULL, NULL );
0205     ctx->request.handler = ThreadTimeout;
0206     CallWithinISRSubmit( &ctx->request );
0207   }
0208 }
0209 
0210 static void ScoreTqReqTimeout_Pre_WaitState_Prepare(
0211   ScoreTqReqTimeout_Context      *ctx,
0212   ScoreTqReqTimeout_Pre_WaitState state
0213 )
0214 {
0215   switch ( state ) {
0216     case ScoreTqReqTimeout_Pre_WaitState_Blocked: {
0217       /*
0218        * While the thread of the timeout operation is in the blocked wait
0219        * state.
0220        */
0221       TQEnqueuePrepare( ctx->tq_ctx );
0222       TQSend( ctx->tq_ctx, TQ_BLOCKER_A, TQ_EVENT_ENQUEUE );
0223       Yield();
0224       Tick( ctx );
0225       TQEnqueueDone( ctx->tq_ctx );
0226       break;
0227     }
0228 
0229     case ScoreTqReqTimeout_Pre_WaitState_IntendToBlock: {
0230       /*
0231        * While the thread of the timeout operation is in the intend to block
0232        * wait state.
0233        */
0234       TQEnqueuePrepare( ctx->tq_ctx );
0235       T_scheduler_set_event_handler( SchedulerBlock, ctx );
0236       TQSend( ctx->tq_ctx, TQ_BLOCKER_A, TQ_EVENT_ENQUEUE );
0237       Yield();
0238       TQEnqueueDone( ctx->tq_ctx );
0239       break;
0240     }
0241 
0242     case ScoreTqReqTimeout_Pre_WaitState_ReadyAgain: {
0243       /*
0244        * While the thread of the timeout operation is in the ready again wait
0245        * state.
0246        */
0247       TQEnqueuePrepare( ctx->tq_ctx );
0248       TQSend( ctx->tq_ctx, TQ_BLOCKER_A, TQ_EVENT_ENQUEUE );
0249       Yield();
0250       T_scheduler_set_event_handler( SchedulerUnblock, ctx );
0251       TQEnqueueDone( ctx->tq_ctx );
0252       TQSend( ctx->tq_ctx, TQ_BLOCKER_A, TQ_EVENT_SURRENDER );
0253       break;
0254     }
0255 
0256     case ScoreTqReqTimeout_Pre_WaitState_NA:
0257       break;
0258   }
0259 }
0260 
0261 static void ScoreTqReqTimeout_Post_Status_Check(
0262   ScoreTqReqTimeout_Context    *ctx,
0263   ScoreTqReqTimeout_Post_Status state
0264 )
0265 {
0266   switch ( state ) {
0267     case ScoreTqReqTimeout_Post_Status_Ok: {
0268       /*
0269        * The return status of the directive call shall be derived from
0270        * STATUS_SUCCESSFUL.
0271        */
0272       T_eq_int(
0273         ctx->tq_ctx->status[ TQ_BLOCKER_A ],
0274         TQConvertStatus( ctx->tq_ctx, STATUS_SUCCESSFUL )
0275       );
0276       break;
0277     }
0278 
0279     case ScoreTqReqTimeout_Post_Status_Timeout: {
0280       /*
0281        * The return status of the directive call shall be derived from
0282        * STATUS_TIMEOUT.
0283        */
0284       T_eq_int(
0285         ctx->tq_ctx->status[ TQ_BLOCKER_A ],
0286         TQConvertStatus( ctx->tq_ctx, STATUS_TIMEOUT )
0287       );
0288       break;
0289     }
0290 
0291     case ScoreTqReqTimeout_Post_Status_NA:
0292       break;
0293   }
0294 }
0295 
0296 static void ScoreTqReqTimeout_Post_Unblock_Check(
0297   ScoreTqReqTimeout_Context     *ctx,
0298   ScoreTqReqTimeout_Post_Unblock state
0299 )
0300 {
0301   size_t i;
0302 
0303   i = 0;
0304 
0305   switch ( state ) {
0306     case ScoreTqReqTimeout_Post_Unblock_Yes: {
0307       /*
0308        * The thread of the timeout operation shall be unblocked by the timeout
0309        * operation.
0310        */
0311       T_eq_ptr( GetUnblock( ctx, &i ), GetTCB( ctx, TQ_BLOCKER_A ) );
0312       T_eq_ptr( GetUnblock( ctx, &i ), NULL );
0313       break;
0314     }
0315 
0316     case ScoreTqReqTimeout_Post_Unblock_No: {
0317       /*
0318        * The thread of the timeout operation shall not be unblocked by the
0319        * timeout operation.
0320        */
0321       T_eq_ptr( GetUnblock( ctx, &i ), NULL );
0322       break;
0323     }
0324 
0325     case ScoreTqReqTimeout_Post_Unblock_NA:
0326       break;
0327   }
0328 }
0329 
0330 static void ScoreTqReqTimeout_Setup( ScoreTqReqTimeout_Context *ctx )
0331 {
0332   ctx->request.arg = ctx;
0333   TQReset( ctx->tq_ctx );
0334 
0335   if ( ctx->tq_ctx->enqueue_variant == TQ_ENQUEUE_STICKY ) {
0336     TQSetScheduler( ctx->tq_ctx, TQ_BLOCKER_A, SCHEDULER_B_ID, PRIO_NORMAL );
0337   } else {
0338     TQSetPriority( ctx->tq_ctx, TQ_BLOCKER_A, PRIO_HIGH );
0339   }
0340 }
0341 
0342 static void ScoreTqReqTimeout_Setup_Wrap( void *arg )
0343 {
0344   ScoreTqReqTimeout_Context *ctx;
0345 
0346   ctx = arg;
0347   ctx->Map.in_action_loop = false;
0348   ScoreTqReqTimeout_Setup( ctx );
0349 }
0350 
0351 static void ScoreTqReqTimeout_Teardown( ScoreTqReqTimeout_Context *ctx )
0352 {
0353   TQReset( ctx->tq_ctx );
0354 }
0355 
0356 static void ScoreTqReqTimeout_Teardown_Wrap( void *arg )
0357 {
0358   ScoreTqReqTimeout_Context *ctx;
0359 
0360   ctx = arg;
0361   ctx->Map.in_action_loop = false;
0362   ScoreTqReqTimeout_Teardown( ctx );
0363 }
0364 
0365 static void ScoreTqReqTimeout_Action( ScoreTqReqTimeout_Context *ctx )
0366 {
0367   /*
0368    * The action is performed by the ``WaitState`` pre-condition preparation.
0369    */
0370 }
0371 
0372 static const ScoreTqReqTimeout_Entry
0373 ScoreTqReqTimeout_Entries[] = {
0374   { 0, 0, ScoreTqReqTimeout_Post_Status_Timeout,
0375     ScoreTqReqTimeout_Post_Unblock_Yes },
0376   { 0, 0, ScoreTqReqTimeout_Post_Status_Timeout,
0377     ScoreTqReqTimeout_Post_Unblock_No },
0378   { 0, 0, ScoreTqReqTimeout_Post_Status_Ok, ScoreTqReqTimeout_Post_Unblock_No }
0379 };
0380 
0381 static const uint8_t
0382 ScoreTqReqTimeout_Map[] = {
0383   0, 1, 2
0384 };
0385 
0386 static size_t ScoreTqReqTimeout_Scope( void *arg, char *buf, size_t n )
0387 {
0388   ScoreTqReqTimeout_Context *ctx;
0389 
0390   ctx = arg;
0391 
0392   if ( ctx->Map.in_action_loop ) {
0393     return T_get_scope( ScoreTqReqTimeout_PreDesc, buf, n, ctx->Map.pcs );
0394   }
0395 
0396   return 0;
0397 }
0398 
0399 static T_fixture ScoreTqReqTimeout_Fixture = {
0400   .setup = ScoreTqReqTimeout_Setup_Wrap,
0401   .stop = NULL,
0402   .teardown = ScoreTqReqTimeout_Teardown_Wrap,
0403   .scope = ScoreTqReqTimeout_Scope,
0404   .initial_context = &ScoreTqReqTimeout_Instance
0405 };
0406 
0407 static inline ScoreTqReqTimeout_Entry ScoreTqReqTimeout_PopEntry(
0408   ScoreTqReqTimeout_Context *ctx
0409 )
0410 {
0411   size_t index;
0412 
0413   index = ctx->Map.index;
0414   ctx->Map.index = index + 1;
0415   return ScoreTqReqTimeout_Entries[
0416     ScoreTqReqTimeout_Map[ index ]
0417   ];
0418 }
0419 
0420 static void ScoreTqReqTimeout_TestVariant( ScoreTqReqTimeout_Context *ctx )
0421 {
0422   ScoreTqReqTimeout_Pre_WaitState_Prepare( ctx, ctx->Map.pcs[ 0 ] );
0423   ScoreTqReqTimeout_Action( ctx );
0424   ScoreTqReqTimeout_Post_Status_Check( ctx, ctx->Map.entry.Post_Status );
0425   ScoreTqReqTimeout_Post_Unblock_Check( ctx, ctx->Map.entry.Post_Unblock );
0426 }
0427 
0428 static T_fixture_node ScoreTqReqTimeout_Node;
0429 
0430 static T_remark ScoreTqReqTimeout_Remark = {
0431   .next = NULL,
0432   .remark = "ScoreTqReqTimeout"
0433 };
0434 
0435 void ScoreTqReqTimeout_Run( TQContext *tq_ctx )
0436 {
0437   ScoreTqReqTimeout_Context *ctx;
0438 
0439   ctx = &ScoreTqReqTimeout_Instance;
0440   ctx->tq_ctx = tq_ctx;
0441 
0442   ctx = T_push_fixture( &ScoreTqReqTimeout_Node, &ScoreTqReqTimeout_Fixture );
0443   ctx->Map.in_action_loop = true;
0444   ctx->Map.index = 0;
0445 
0446   for (
0447     ctx->Map.pcs[ 0 ] = ScoreTqReqTimeout_Pre_WaitState_Blocked;
0448     ctx->Map.pcs[ 0 ] < ScoreTqReqTimeout_Pre_WaitState_NA;
0449     ++ctx->Map.pcs[ 0 ]
0450   ) {
0451     ctx->Map.entry = ScoreTqReqTimeout_PopEntry( ctx );
0452     ScoreTqReqTimeout_TestVariant( ctx );
0453   }
0454 
0455   T_add_remark( &ScoreTqReqTimeout_Remark );
0456   T_pop_fixture();
0457 }
0458 
0459 /** @} */