Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RtemsSemReqTimeout
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.h>
0056 #include <string.h>
0057 
0058 #include "tr-tq-timeout-priority-inherit.h"
0059 #include "tr-tq-timeout.h"
0060 #include "tx-support.h"
0061 #include "tx-thread-queue.h"
0062 
0063 #include <rtems/test.h>
0064 
0065 /**
0066  * @defgroup RtemsSemReqTimeout spec:/rtems/sem/req/timeout
0067  *
0068  * @ingroup TestsuitesValidationNoClock0
0069  *
0070  * @{
0071  */
0072 
0073 typedef enum {
0074   RtemsSemReqTimeout_Pre_Class_Counting,
0075   RtemsSemReqTimeout_Pre_Class_Simple,
0076   RtemsSemReqTimeout_Pre_Class_Binary,
0077   RtemsSemReqTimeout_Pre_Class_PrioCeiling,
0078   RtemsSemReqTimeout_Pre_Class_PrioInherit,
0079   RtemsSemReqTimeout_Pre_Class_MrsP,
0080   RtemsSemReqTimeout_Pre_Class_NA
0081 } RtemsSemReqTimeout_Pre_Class;
0082 
0083 typedef enum {
0084   RtemsSemReqTimeout_Pre_Discipline_FIFO,
0085   RtemsSemReqTimeout_Pre_Discipline_Priority,
0086   RtemsSemReqTimeout_Pre_Discipline_NA
0087 } RtemsSemReqTimeout_Pre_Discipline;
0088 
0089 typedef enum {
0090   RtemsSemReqTimeout_Post_Action_Timeout,
0091   RtemsSemReqTimeout_Post_Action_TimeoutMrsP,
0092   RtemsSemReqTimeout_Post_Action_TimeoutPriorityInherit,
0093   RtemsSemReqTimeout_Post_Action_NA
0094 } RtemsSemReqTimeout_Post_Action;
0095 
0096 typedef struct {
0097   uint8_t Skip : 1;
0098   uint8_t Pre_Class_NA : 1;
0099   uint8_t Pre_Discipline_NA : 1;
0100   uint8_t Post_Action : 2;
0101 } RtemsSemReqTimeout_Entry;
0102 
0103 /**
0104  * @brief Test context for spec:/rtems/sem/req/timeout test case.
0105  */
0106 typedef struct {
0107   /**
0108    * @brief This member contains the thread queue test context.
0109    */
0110   TQContext tq_ctx;
0111 
0112   /**
0113    * @brief This member specifies if the attribute set of the semaphore.
0114    */
0115   rtems_attribute attribute_set;
0116 
0117   struct {
0118     /**
0119      * @brief This member defines the pre-condition states for the next action.
0120      */
0121     size_t pcs[ 2 ];
0122 
0123     /**
0124      * @brief If this member is true, then the test action loop is executed.
0125      */
0126     bool in_action_loop;
0127 
0128     /**
0129      * @brief This member contains the next transition map index.
0130      */
0131     size_t index;
0132 
0133     /**
0134      * @brief This member contains the current transition map entry.
0135      */
0136     RtemsSemReqTimeout_Entry entry;
0137 
0138     /**
0139      * @brief If this member is true, then the current transition variant
0140      *   should be skipped.
0141      */
0142     bool skip;
0143   } Map;
0144 } RtemsSemReqTimeout_Context;
0145 
0146 static RtemsSemReqTimeout_Context
0147   RtemsSemReqTimeout_Instance;
0148 
0149 static const char * const RtemsSemReqTimeout_PreDesc_Class[] = {
0150   "Counting",
0151   "Simple",
0152   "Binary",
0153   "PrioCeiling",
0154   "PrioInherit",
0155   "MrsP",
0156   "NA"
0157 };
0158 
0159 static const char * const RtemsSemReqTimeout_PreDesc_Discipline[] = {
0160   "FIFO",
0161   "Priority",
0162   "NA"
0163 };
0164 
0165 static const char * const * const RtemsSemReqTimeout_PreDesc[] = {
0166   RtemsSemReqTimeout_PreDesc_Class,
0167   RtemsSemReqTimeout_PreDesc_Discipline,
0168   NULL
0169 };
0170 
0171 #if defined(RTEMS_SMP)
0172 #include "tr-tq-timeout-mrsp.h"
0173 #endif
0174 
0175 static void RtemsSemReqTimeout_Pre_Class_Prepare(
0176   RtemsSemReqTimeout_Context  *ctx,
0177   RtemsSemReqTimeout_Pre_Class state
0178 )
0179 {
0180   switch ( state ) {
0181     case RtemsSemReqTimeout_Pre_Class_Counting: {
0182       /*
0183        * While the semaphore object is a counting semaphore.
0184        */
0185       ctx->attribute_set |= RTEMS_COUNTING_SEMAPHORE;
0186       ctx->tq_ctx.enqueue_variant = TQ_ENQUEUE_BLOCKS;
0187       break;
0188     }
0189 
0190     case RtemsSemReqTimeout_Pre_Class_Simple: {
0191       /*
0192        * While the semaphore object is a simple binary semaphore.
0193        */
0194       ctx->attribute_set |= RTEMS_SIMPLE_BINARY_SEMAPHORE;
0195       ctx->tq_ctx.enqueue_variant = TQ_ENQUEUE_BLOCKS;
0196       break;
0197     }
0198 
0199     case RtemsSemReqTimeout_Pre_Class_Binary: {
0200       /*
0201        * While the semaphore object is a binary semaphore.
0202        */
0203       ctx->attribute_set |= RTEMS_BINARY_SEMAPHORE;
0204       ctx->tq_ctx.enqueue_variant = TQ_ENQUEUE_BLOCKS;
0205       break;
0206     }
0207 
0208     case RtemsSemReqTimeout_Pre_Class_PrioCeiling: {
0209       /*
0210        * While the semaphore object is a priority ceiling semaphore.
0211        */
0212       ctx->attribute_set |= RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY_CEILING;
0213       ctx->tq_ctx.enqueue_variant = TQ_ENQUEUE_BLOCKS;
0214       break;
0215     }
0216 
0217     case RtemsSemReqTimeout_Pre_Class_PrioInherit: {
0218       /*
0219        * While the semaphore object is a priority inheritance semaphore.
0220        */
0221       ctx->attribute_set |= RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY;
0222       ctx->tq_ctx.enqueue_variant = TQ_ENQUEUE_BLOCKS;
0223       break;
0224     }
0225 
0226     case RtemsSemReqTimeout_Pre_Class_MrsP: {
0227       /*
0228        * While the semaphore object is a MrsP semaphore.
0229        */
0230       ctx->attribute_set |= RTEMS_BINARY_SEMAPHORE |
0231         RTEMS_MULTIPROCESSOR_RESOURCE_SHARING;
0232       #if defined(RTEMS_SMP)
0233       ctx->tq_ctx.enqueue_variant = TQ_ENQUEUE_STICKY;
0234       #else
0235       ctx->tq_ctx.enqueue_variant = TQ_ENQUEUE_BLOCKS;
0236       #endif
0237       break;
0238     }
0239 
0240     case RtemsSemReqTimeout_Pre_Class_NA:
0241       break;
0242   }
0243 }
0244 
0245 static void RtemsSemReqTimeout_Pre_Discipline_Prepare(
0246   RtemsSemReqTimeout_Context       *ctx,
0247   RtemsSemReqTimeout_Pre_Discipline state
0248 )
0249 {
0250   switch ( state ) {
0251     case RtemsSemReqTimeout_Pre_Discipline_FIFO: {
0252       /*
0253        * While the semaphore uses the FIFO task wait queue discipline.
0254        */
0255       ctx->attribute_set |= RTEMS_FIFO;
0256       ctx->tq_ctx.discipline = TQ_FIFO;
0257       break;
0258     }
0259 
0260     case RtemsSemReqTimeout_Pre_Discipline_Priority: {
0261       /*
0262        * While the semaphore uses the priority task wait queue discipline.
0263        */
0264       ctx->attribute_set |= RTEMS_PRIORITY;
0265       ctx->tq_ctx.discipline = TQ_PRIORITY;
0266       break;
0267     }
0268 
0269     case RtemsSemReqTimeout_Pre_Discipline_NA:
0270       break;
0271   }
0272 }
0273 
0274 static void RtemsSemReqTimeout_Post_Action_Check(
0275   RtemsSemReqTimeout_Context    *ctx,
0276   RtemsSemReqTimeout_Post_Action state
0277 )
0278 {
0279   switch ( state ) {
0280     case RtemsSemReqTimeout_Post_Action_Timeout: {
0281       /*
0282        * The semaphore obtain timeout actions shall be done as specified by
0283        * spec:/score/tq/req/timeout.
0284        */
0285       ctx->tq_ctx.wait = TQ_WAIT_TIMED;
0286       ScoreTqReqTimeout_Run( &ctx->tq_ctx );
0287       break;
0288     }
0289 
0290     case RtemsSemReqTimeout_Post_Action_TimeoutMrsP: {
0291       /*
0292        * The semaphore obtain timeout actions shall be done as specified by
0293        * spec:/score/tq/req/timeout-mrsp.
0294        */
0295       #if defined(RTEMS_SMP)
0296       ctx->tq_ctx.wait = TQ_WAIT_TIMED;
0297       ScoreTqReqTimeoutMrsp_Run( &ctx->tq_ctx );
0298       #else
0299       T_unreachable();
0300       #endif
0301       break;
0302     }
0303 
0304     case RtemsSemReqTimeout_Post_Action_TimeoutPriorityInherit: {
0305       /*
0306        * The semaphore obtain timeout actions shall be done as specified by
0307        * spec:/score/tq/req/timeout-priority-inherit.
0308        */
0309       ctx->tq_ctx.wait = TQ_WAIT_FOREVER;
0310       ScoreTqReqTimeoutPriorityInherit_Run( &ctx->tq_ctx );
0311       break;
0312     }
0313 
0314     case RtemsSemReqTimeout_Post_Action_NA:
0315       break;
0316   }
0317 }
0318 
0319 static void RtemsSemReqTimeout_Setup( RtemsSemReqTimeout_Context *ctx )
0320 {
0321   memset( ctx, 0, sizeof( *ctx ) );
0322   ctx->tq_ctx.enqueue_prepare = TQEnqueuePrepareDefault;
0323   ctx->tq_ctx.enqueue_done = TQEnqueueDoneDefault;
0324   ctx->tq_ctx.enqueue = TQEnqueueClassicSem;
0325   ctx->tq_ctx.surrender = TQSurrenderClassicSem;
0326   ctx->tq_ctx.convert_status = TQConvertStatusClassic;
0327   TQInitialize( &ctx->tq_ctx );
0328 }
0329 
0330 static void RtemsSemReqTimeout_Setup_Wrap( void *arg )
0331 {
0332   RtemsSemReqTimeout_Context *ctx;
0333 
0334   ctx = arg;
0335   ctx->Map.in_action_loop = false;
0336   RtemsSemReqTimeout_Setup( ctx );
0337 }
0338 
0339 static void RtemsSemReqTimeout_Teardown( RtemsSemReqTimeout_Context *ctx )
0340 {
0341   TQDestroy( &ctx->tq_ctx );
0342 }
0343 
0344 static void RtemsSemReqTimeout_Teardown_Wrap( void *arg )
0345 {
0346   RtemsSemReqTimeout_Context *ctx;
0347 
0348   ctx = arg;
0349   ctx->Map.in_action_loop = false;
0350   RtemsSemReqTimeout_Teardown( ctx );
0351 }
0352 
0353 static void RtemsSemReqTimeout_Prepare( RtemsSemReqTimeout_Context *ctx )
0354 {
0355   ctx->attribute_set = RTEMS_DEFAULT_ATTRIBUTES;
0356   ctx->tq_ctx.thread_queue_id = 0;
0357 }
0358 
0359 static void RtemsSemReqTimeout_Action( RtemsSemReqTimeout_Context *ctx )
0360 {
0361   rtems_status_code sc;
0362 
0363   sc = rtems_semaphore_create(
0364     OBJECT_NAME,
0365     1,
0366     ctx->attribute_set,
0367     PRIO_HIGH,
0368     &ctx->tq_ctx.thread_queue_id
0369   );
0370   T_rsc_success( sc );
0371 }
0372 
0373 static void RtemsSemReqTimeout_Cleanup( RtemsSemReqTimeout_Context *ctx )
0374 {
0375   if ( ctx->tq_ctx.thread_queue_id != 0 ) {
0376     rtems_status_code sc;
0377 
0378     sc = rtems_semaphore_delete( ctx->tq_ctx.thread_queue_id );
0379     T_rsc_success( sc );
0380   }
0381 }
0382 
0383 static const RtemsSemReqTimeout_Entry
0384 RtemsSemReqTimeout_Entries[] = {
0385   { 0, 0, 0, RtemsSemReqTimeout_Post_Action_Timeout },
0386   { 1, 0, 0, RtemsSemReqTimeout_Post_Action_NA },
0387   { 0, 0, 0, RtemsSemReqTimeout_Post_Action_TimeoutPriorityInherit },
0388 #if defined(RTEMS_SMP)
0389   { 0, 0, 0, RtemsSemReqTimeout_Post_Action_TimeoutMrsP }
0390 #else
0391   { 0, 0, 0, RtemsSemReqTimeout_Post_Action_Timeout }
0392 #endif
0393 };
0394 
0395 static const uint8_t
0396 RtemsSemReqTimeout_Map[] = {
0397   0, 0, 0, 0, 0, 0, 1, 0, 1, 2, 1, 3
0398 };
0399 
0400 static size_t RtemsSemReqTimeout_Scope( void *arg, char *buf, size_t n )
0401 {
0402   RtemsSemReqTimeout_Context *ctx;
0403 
0404   ctx = arg;
0405 
0406   if ( ctx->Map.in_action_loop ) {
0407     return T_get_scope( RtemsSemReqTimeout_PreDesc, buf, n, ctx->Map.pcs );
0408   }
0409 
0410   return 0;
0411 }
0412 
0413 static T_fixture RtemsSemReqTimeout_Fixture = {
0414   .setup = RtemsSemReqTimeout_Setup_Wrap,
0415   .stop = NULL,
0416   .teardown = RtemsSemReqTimeout_Teardown_Wrap,
0417   .scope = RtemsSemReqTimeout_Scope,
0418   .initial_context = &RtemsSemReqTimeout_Instance
0419 };
0420 
0421 static inline RtemsSemReqTimeout_Entry RtemsSemReqTimeout_PopEntry(
0422   RtemsSemReqTimeout_Context *ctx
0423 )
0424 {
0425   size_t index;
0426 
0427   index = ctx->Map.index;
0428   ctx->Map.index = index + 1;
0429   return RtemsSemReqTimeout_Entries[
0430     RtemsSemReqTimeout_Map[ index ]
0431   ];
0432 }
0433 
0434 static void RtemsSemReqTimeout_TestVariant( RtemsSemReqTimeout_Context *ctx )
0435 {
0436   RtemsSemReqTimeout_Pre_Class_Prepare( ctx, ctx->Map.pcs[ 0 ] );
0437   RtemsSemReqTimeout_Pre_Discipline_Prepare( ctx, ctx->Map.pcs[ 1 ] );
0438   RtemsSemReqTimeout_Action( ctx );
0439   RtemsSemReqTimeout_Post_Action_Check( ctx, ctx->Map.entry.Post_Action );
0440 }
0441 
0442 /**
0443  * @fn void T_case_body_RtemsSemReqTimeout( void )
0444  */
0445 T_TEST_CASE_FIXTURE( RtemsSemReqTimeout, &RtemsSemReqTimeout_Fixture )
0446 {
0447   RtemsSemReqTimeout_Context *ctx;
0448 
0449   ctx = T_fixture_context();
0450   ctx->Map.in_action_loop = true;
0451   ctx->Map.index = 0;
0452 
0453   for (
0454     ctx->Map.pcs[ 0 ] = RtemsSemReqTimeout_Pre_Class_Counting;
0455     ctx->Map.pcs[ 0 ] < RtemsSemReqTimeout_Pre_Class_NA;
0456     ++ctx->Map.pcs[ 0 ]
0457   ) {
0458     for (
0459       ctx->Map.pcs[ 1 ] = RtemsSemReqTimeout_Pre_Discipline_FIFO;
0460       ctx->Map.pcs[ 1 ] < RtemsSemReqTimeout_Pre_Discipline_NA;
0461       ++ctx->Map.pcs[ 1 ]
0462     ) {
0463       ctx->Map.entry = RtemsSemReqTimeout_PopEntry( ctx );
0464 
0465       if ( ctx->Map.entry.Skip ) {
0466         continue;
0467       }
0468 
0469       RtemsSemReqTimeout_Prepare( ctx );
0470       RtemsSemReqTimeout_TestVariant( ctx );
0471       RtemsSemReqTimeout_Cleanup( ctx );
0472     }
0473   }
0474 }
0475 
0476 /** @} */