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 ScoreSemReqSurrender
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-sem-surrender.h"
0056 #include "tr-tq-surrender.h"
0057 
0058 #include <rtems/test.h>
0059 
0060 /**
0061  * @defgroup ScoreSemReqSurrender spec:/score/sem/req/surrender
0062  *
0063  * @ingroup TestsuitesValidationNoClock0
0064  *
0065  * @{
0066  */
0067 
0068 typedef struct {
0069   uint16_t Skip : 1;
0070   uint16_t Pre_Variant_NA : 1;
0071   uint16_t Pre_Discipline_NA : 1;
0072   uint16_t Pre_Count_NA : 1;
0073   uint16_t Post_Status : 2;
0074   uint16_t Post_Surrender : 2;
0075   uint16_t Post_Count : 3;
0076 } ScoreSemReqSurrender_Entry;
0077 
0078 /**
0079  * @brief Test context for spec:/score/sem/req/surrender test case.
0080  */
0081 typedef struct {
0082   /**
0083    * @brief This member specifies the semaphore count before the directive
0084    *   call.
0085    */
0086   uint32_t count_before;
0087 
0088   /**
0089    * @brief This member contains the return status of the directive call.
0090    */
0091   Status_Control status;
0092 
0093   /**
0094    * @brief This member contains the semaphore count after the directive call.
0095    */
0096   uint32_t count_after;
0097 
0098   /**
0099    * @brief If this member is true, then there shall be threads blocked on the
0100    *   semaphore.
0101    */
0102   bool blocked;
0103 
0104   /**
0105    * @brief This member contains a copy of the corresponding
0106    *   ScoreSemReqSurrender_Run() parameter.
0107    */
0108   TQSemContext *tq_ctx;
0109 
0110   struct {
0111     /**
0112      * @brief This member defines the pre-condition states for the next action.
0113      */
0114     size_t pcs[ 3 ];
0115 
0116     /**
0117      * @brief If this member is true, then the test action loop is executed.
0118      */
0119     bool in_action_loop;
0120 
0121     /**
0122      * @brief This member contains the next transition map index.
0123      */
0124     size_t index;
0125 
0126     /**
0127      * @brief This member contains the current transition map entry.
0128      */
0129     ScoreSemReqSurrender_Entry entry;
0130 
0131     /**
0132      * @brief If this member is true, then the current transition variant
0133      *   should be skipped.
0134      */
0135     bool skip;
0136   } Map;
0137 } ScoreSemReqSurrender_Context;
0138 
0139 static ScoreSemReqSurrender_Context
0140   ScoreSemReqSurrender_Instance;
0141 
0142 static const char * const ScoreSemReqSurrender_PreDesc_Variant[] = {
0143   "Binary",
0144   "Counting",
0145   "NA"
0146 };
0147 
0148 static const char * const ScoreSemReqSurrender_PreDesc_Discipline[] = {
0149   "FIFO",
0150   "Priority",
0151   "NA"
0152 };
0153 
0154 static const char * const ScoreSemReqSurrender_PreDesc_Count[] = {
0155   "LessMax",
0156   "Max",
0157   "Blocked",
0158   "NA"
0159 };
0160 
0161 static const char * const * const ScoreSemReqSurrender_PreDesc[] = {
0162   ScoreSemReqSurrender_PreDesc_Variant,
0163   ScoreSemReqSurrender_PreDesc_Discipline,
0164   ScoreSemReqSurrender_PreDesc_Count,
0165   NULL
0166 };
0167 
0168 typedef ScoreSemReqSurrender_Context Context;
0169 
0170 static Status_Control Status( const Context *ctx, Status_Control status )
0171 {
0172   return TQConvertStatus( &ctx->tq_ctx->base, status );
0173 }
0174 
0175 static void ScoreSemReqSurrender_Pre_Variant_Prepare(
0176   ScoreSemReqSurrender_Context    *ctx,
0177   ScoreSemReqSurrender_Pre_Variant state
0178 )
0179 {
0180   switch ( state ) {
0181     case ScoreSemReqSurrender_Pre_Variant_Binary: {
0182       /*
0183        * Where the semaphore is a binary semaphore.
0184        */
0185       if ( ctx->tq_ctx->variant != TQ_SEM_BINARY ) {
0186         ctx->Map.skip = true;
0187       }
0188       break;
0189     }
0190 
0191     case ScoreSemReqSurrender_Pre_Variant_Counting: {
0192       /*
0193        * Where the semaphore is a counting semaphore.
0194        */
0195       if ( ctx->tq_ctx->variant != TQ_SEM_COUNTING ) {
0196         ctx->Map.skip = true;
0197       }
0198       break;
0199     }
0200 
0201     case ScoreSemReqSurrender_Pre_Variant_NA:
0202       break;
0203   }
0204 }
0205 
0206 static void ScoreSemReqSurrender_Pre_Discipline_Prepare(
0207   ScoreSemReqSurrender_Context       *ctx,
0208   ScoreSemReqSurrender_Pre_Discipline state
0209 )
0210 {
0211   switch ( state ) {
0212     case ScoreSemReqSurrender_Pre_Discipline_FIFO: {
0213       /*
0214        * Where the thread queue of the semaphore uses the FIFO discipline.
0215        */
0216       if ( ctx->tq_ctx->base.discipline != TQ_FIFO ) {
0217         ctx->Map.skip = true;
0218       }
0219       break;
0220     }
0221 
0222     case ScoreSemReqSurrender_Pre_Discipline_Priority: {
0223       /*
0224        * Where the thread queue of the semaphore uses the priority discipline.
0225        */
0226       if ( ctx->tq_ctx->base.discipline != TQ_PRIORITY ) {
0227         ctx->Map.skip = true;
0228       }
0229       break;
0230     }
0231 
0232     case ScoreSemReqSurrender_Pre_Discipline_NA:
0233       break;
0234   }
0235 }
0236 
0237 static void ScoreSemReqSurrender_Pre_Count_Prepare(
0238   ScoreSemReqSurrender_Context  *ctx,
0239   ScoreSemReqSurrender_Pre_Count state
0240 )
0241 {
0242   switch ( state ) {
0243     case ScoreSemReqSurrender_Pre_Count_LessMax: {
0244       /*
0245        * While the count of the semaphore is less than the maximum count.
0246        */
0247       ctx->blocked = false;
0248 
0249       if ( ctx->tq_ctx->variant == TQ_SEM_BINARY ) {
0250         ctx->count_before = 0;
0251       } else {
0252         ctx->count_before = UINT32_MAX - 1;
0253       }
0254       break;
0255     }
0256 
0257     case ScoreSemReqSurrender_Pre_Count_Max: {
0258       /*
0259        * While the count of the semaphore is equal to the maximum count.
0260        */
0261       ctx->blocked = false;
0262 
0263       if ( ctx->tq_ctx->variant == TQ_SEM_BINARY ) {
0264         ctx->count_before = 1;
0265       } else {
0266         ctx->count_before = UINT32_MAX;
0267       }
0268       break;
0269     }
0270 
0271     case ScoreSemReqSurrender_Pre_Count_Blocked: {
0272       /*
0273        * While the semaphore has threads blocked on the semaphore.
0274        */
0275       ctx->blocked = true;
0276       ctx->count_before = 0;
0277       break;
0278     }
0279 
0280     case ScoreSemReqSurrender_Pre_Count_NA:
0281       break;
0282   }
0283 }
0284 
0285 static void ScoreSemReqSurrender_Post_Status_Check(
0286   ScoreSemReqSurrender_Context    *ctx,
0287   ScoreSemReqSurrender_Post_Status state
0288 )
0289 {
0290   switch ( state ) {
0291     case ScoreSemReqSurrender_Post_Status_Ok: {
0292       /*
0293        * The return status of the directive call shall be derived from
0294        * STATUS_SUCCESSFUL.
0295        */
0296       T_eq_int( ctx->status, Status( ctx, STATUS_SUCCESSFUL ) );
0297       break;
0298     }
0299 
0300     case ScoreSemReqSurrender_Post_Status_MaxCountExceeded: {
0301       /*
0302        * The return status of the directive call shall be derived from
0303        * STATUS_MAXIMUM_COUNT_EXCEEDED.
0304        */
0305       T_eq_int( ctx->status, Status( ctx, STATUS_MAXIMUM_COUNT_EXCEEDED ) );
0306       break;
0307     }
0308 
0309     case ScoreSemReqSurrender_Post_Status_NA:
0310       break;
0311   }
0312 }
0313 
0314 static void ScoreSemReqSurrender_Post_Surrender_Check(
0315   ScoreSemReqSurrender_Context       *ctx,
0316   ScoreSemReqSurrender_Post_Surrender state
0317 )
0318 {
0319   switch ( state ) {
0320     case ScoreSemReqSurrender_Post_Surrender_FIFO: {
0321       /*
0322        * The thread queue of the semaphore shall be surrendered in FIFO order.
0323        */
0324       ScoreTqReqSurrender_Run( &ctx->tq_ctx->base );
0325       break;
0326     }
0327 
0328     case ScoreSemReqSurrender_Post_Surrender_Priority: {
0329       /*
0330        * The thread queue of the semaphore shall be surrendered in priority
0331        * order.
0332        */
0333       ScoreTqReqSurrender_Run( &ctx->tq_ctx->base );
0334       break;
0335     }
0336 
0337     case ScoreSemReqSurrender_Post_Surrender_NA:
0338       break;
0339   }
0340 }
0341 
0342 static void ScoreSemReqSurrender_Post_Count_Check(
0343   ScoreSemReqSurrender_Context   *ctx,
0344   ScoreSemReqSurrender_Post_Count state
0345 )
0346 {
0347   switch ( state ) {
0348     case ScoreSemReqSurrender_Post_Count_Zero: {
0349       /*
0350        * The count of the semaphore shall be zero.
0351        */
0352       T_eq_u32( ctx->count_after, 0 );
0353       break;
0354     }
0355 
0356     case ScoreSemReqSurrender_Post_Count_One: {
0357       /*
0358        * The count of the semaphore shall be one.
0359        */
0360       T_eq_u32( ctx->count_after, 1 );
0361       break;
0362     }
0363 
0364     case ScoreSemReqSurrender_Post_Count_PlusOne: {
0365       /*
0366        * The count of the semaphore shall be incremented by one.
0367        */
0368       T_eq_u32( ctx->count_after, ctx->count_before + 1 );
0369       break;
0370     }
0371 
0372     case ScoreSemReqSurrender_Post_Count_Nop: {
0373       /*
0374        * The count of the semaphore shall not be modified.
0375        */
0376       T_eq_u32( ctx->count_after, ctx->count_before );
0377       break;
0378     }
0379 
0380     case ScoreSemReqSurrender_Post_Count_NA:
0381       break;
0382   }
0383 }
0384 
0385 static void ScoreSemReqSurrender_Setup( ScoreSemReqSurrender_Context *ctx )
0386 {
0387   ctx->tq_ctx->base.wait = TQ_WAIT_FOREVER;
0388   TQReset( &ctx->tq_ctx->base );
0389 }
0390 
0391 static void ScoreSemReqSurrender_Setup_Wrap( void *arg )
0392 {
0393   ScoreSemReqSurrender_Context *ctx;
0394 
0395   ctx = arg;
0396   ctx->Map.in_action_loop = false;
0397   ScoreSemReqSurrender_Setup( ctx );
0398 }
0399 
0400 static void ScoreSemReqSurrender_Action( ScoreSemReqSurrender_Context *ctx )
0401 {
0402   TQSemSetCount( ctx->tq_ctx, ctx->count_before );
0403 
0404   if ( ctx->blocked ) {
0405     TQSend( &ctx->tq_ctx->base, TQ_BLOCKER_A, TQ_EVENT_ENQUEUE );
0406   }
0407 
0408   ctx->status = TQSurrender( &ctx->tq_ctx->base );
0409   ctx->count_after = TQSemGetCount( ctx->tq_ctx );
0410   TQSemSetCount( ctx->tq_ctx, 1 );
0411 }
0412 
0413 static const ScoreSemReqSurrender_Entry
0414 ScoreSemReqSurrender_Entries[] = {
0415   { 0, 0, 0, 0, ScoreSemReqSurrender_Post_Status_Ok,
0416     ScoreSemReqSurrender_Post_Surrender_NA, ScoreSemReqSurrender_Post_Count_One },
0417   { 0, 0, 0, 0, ScoreSemReqSurrender_Post_Status_Ok,
0418     ScoreSemReqSurrender_Post_Surrender_FIFO,
0419     ScoreSemReqSurrender_Post_Count_Zero },
0420   { 0, 0, 0, 0, ScoreSemReqSurrender_Post_Status_Ok,
0421     ScoreSemReqSurrender_Post_Surrender_Priority,
0422     ScoreSemReqSurrender_Post_Count_Zero },
0423   { 0, 0, 0, 0, ScoreSemReqSurrender_Post_Status_Ok,
0424     ScoreSemReqSurrender_Post_Surrender_NA,
0425     ScoreSemReqSurrender_Post_Count_PlusOne },
0426   { 0, 0, 0, 0, ScoreSemReqSurrender_Post_Status_MaxCountExceeded,
0427     ScoreSemReqSurrender_Post_Surrender_NA, ScoreSemReqSurrender_Post_Count_Nop }
0428 };
0429 
0430 static const uint8_t
0431 ScoreSemReqSurrender_Map[] = {
0432   0, 0, 1, 0, 0, 2, 3, 4, 1, 3, 4, 2
0433 };
0434 
0435 static size_t ScoreSemReqSurrender_Scope( void *arg, char *buf, size_t n )
0436 {
0437   ScoreSemReqSurrender_Context *ctx;
0438 
0439   ctx = arg;
0440 
0441   if ( ctx->Map.in_action_loop ) {
0442     return T_get_scope( ScoreSemReqSurrender_PreDesc, buf, n, ctx->Map.pcs );
0443   }
0444 
0445   return 0;
0446 }
0447 
0448 static T_fixture ScoreSemReqSurrender_Fixture = {
0449   .setup = ScoreSemReqSurrender_Setup_Wrap,
0450   .stop = NULL,
0451   .teardown = NULL,
0452   .scope = ScoreSemReqSurrender_Scope,
0453   .initial_context = &ScoreSemReqSurrender_Instance
0454 };
0455 
0456 static const uint8_t ScoreSemReqSurrender_Weights[] = {
0457   6, 3, 1
0458 };
0459 
0460 static void ScoreSemReqSurrender_Skip(
0461   ScoreSemReqSurrender_Context *ctx,
0462   size_t                        index
0463 )
0464 {
0465   switch ( index + 1 ) {
0466     case 1:
0467       ctx->Map.pcs[ 1 ] = ScoreSemReqSurrender_Pre_Discipline_NA - 1;
0468       /* Fall through */
0469     case 2:
0470       ctx->Map.pcs[ 2 ] = ScoreSemReqSurrender_Pre_Count_NA - 1;
0471       break;
0472   }
0473 }
0474 
0475 static inline ScoreSemReqSurrender_Entry ScoreSemReqSurrender_PopEntry(
0476   ScoreSemReqSurrender_Context *ctx
0477 )
0478 {
0479   size_t index;
0480 
0481   if ( ctx->Map.skip ) {
0482     size_t i;
0483 
0484     ctx->Map.skip = false;
0485     index = 0;
0486 
0487     for ( i = 0; i < 3; ++i ) {
0488       index += ScoreSemReqSurrender_Weights[ i ] * ctx->Map.pcs[ i ];
0489     }
0490   } else {
0491     index = ctx->Map.index;
0492   }
0493 
0494   ctx->Map.index = index + 1;
0495 
0496   return ScoreSemReqSurrender_Entries[
0497     ScoreSemReqSurrender_Map[ index ]
0498   ];
0499 }
0500 
0501 static void ScoreSemReqSurrender_TestVariant(
0502   ScoreSemReqSurrender_Context *ctx
0503 )
0504 {
0505   ScoreSemReqSurrender_Pre_Variant_Prepare( ctx, ctx->Map.pcs[ 0 ] );
0506 
0507   if ( ctx->Map.skip ) {
0508     ScoreSemReqSurrender_Skip( ctx, 0 );
0509     return;
0510   }
0511 
0512   ScoreSemReqSurrender_Pre_Discipline_Prepare( ctx, ctx->Map.pcs[ 1 ] );
0513 
0514   if ( ctx->Map.skip ) {
0515     ScoreSemReqSurrender_Skip( ctx, 1 );
0516     return;
0517   }
0518 
0519   ScoreSemReqSurrender_Pre_Count_Prepare( ctx, ctx->Map.pcs[ 2 ] );
0520   ScoreSemReqSurrender_Action( ctx );
0521   ScoreSemReqSurrender_Post_Status_Check( ctx, ctx->Map.entry.Post_Status );
0522   ScoreSemReqSurrender_Post_Surrender_Check(
0523     ctx,
0524     ctx->Map.entry.Post_Surrender
0525   );
0526   ScoreSemReqSurrender_Post_Count_Check( ctx, ctx->Map.entry.Post_Count );
0527 }
0528 
0529 static T_fixture_node ScoreSemReqSurrender_Node;
0530 
0531 static T_remark ScoreSemReqSurrender_Remark = {
0532   .next = NULL,
0533   .remark = "ScoreSemReqSurrender"
0534 };
0535 
0536 void ScoreSemReqSurrender_Run( TQSemContext *tq_ctx )
0537 {
0538   ScoreSemReqSurrender_Context *ctx;
0539 
0540   ctx = &ScoreSemReqSurrender_Instance;
0541   ctx->tq_ctx = tq_ctx;
0542 
0543   ctx = T_push_fixture(
0544     &ScoreSemReqSurrender_Node,
0545     &ScoreSemReqSurrender_Fixture
0546   );
0547   ctx->Map.in_action_loop = true;
0548   ctx->Map.index = 0;
0549   ctx->Map.skip = false;
0550 
0551   for (
0552     ctx->Map.pcs[ 0 ] = ScoreSemReqSurrender_Pre_Variant_Binary;
0553     ctx->Map.pcs[ 0 ] < ScoreSemReqSurrender_Pre_Variant_NA;
0554     ++ctx->Map.pcs[ 0 ]
0555   ) {
0556     for (
0557       ctx->Map.pcs[ 1 ] = ScoreSemReqSurrender_Pre_Discipline_FIFO;
0558       ctx->Map.pcs[ 1 ] < ScoreSemReqSurrender_Pre_Discipline_NA;
0559       ++ctx->Map.pcs[ 1 ]
0560     ) {
0561       for (
0562         ctx->Map.pcs[ 2 ] = ScoreSemReqSurrender_Pre_Count_LessMax;
0563         ctx->Map.pcs[ 2 ] < ScoreSemReqSurrender_Pre_Count_NA;
0564         ++ctx->Map.pcs[ 2 ]
0565       ) {
0566         ctx->Map.entry = ScoreSemReqSurrender_PopEntry( ctx );
0567         ScoreSemReqSurrender_TestVariant( ctx );
0568       }
0569     }
0570   }
0571 
0572   T_add_remark( &ScoreSemReqSurrender_Remark );
0573   T_pop_fixture();
0574 }
0575 
0576 /** @} */