Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup NewlibReqFutexWait
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 <limits.h>
0056 #include <rtems.h>
0057 #include <sys/lock.h>
0058 
0059 #include "tr-tq-enqueue-fifo.h"
0060 #include "tx-thread-queue.h"
0061 
0062 #include <rtems/test.h>
0063 
0064 /**
0065  * @defgroup NewlibReqFutexWait spec:/newlib/req/futex-wait
0066  *
0067  * @ingroup TestsuitesValidationNoClock0
0068  *
0069  * @{
0070  */
0071 
0072 typedef enum {
0073   NewlibReqFutexWait_Pre_State_Equal,
0074   NewlibReqFutexWait_Pre_State_NotEqual,
0075   NewlibReqFutexWait_Pre_State_NA
0076 } NewlibReqFutexWait_Pre_State;
0077 
0078 typedef enum {
0079   NewlibReqFutexWait_Post_Result_Zero,
0080   NewlibReqFutexWait_Post_Result_EAGAIN,
0081   NewlibReqFutexWait_Post_Result_NA
0082 } NewlibReqFutexWait_Post_Result;
0083 
0084 typedef enum {
0085   NewlibReqFutexWait_Post_Enqueue_No,
0086   NewlibReqFutexWait_Post_Enqueue_Yes,
0087   NewlibReqFutexWait_Post_Enqueue_NA
0088 } NewlibReqFutexWait_Post_Enqueue;
0089 
0090 typedef struct {
0091   uint8_t Skip : 1;
0092   uint8_t Pre_State_NA : 1;
0093   uint8_t Post_Result : 2;
0094   uint8_t Post_Enqueue : 2;
0095 } NewlibReqFutexWait_Entry;
0096 
0097 /**
0098  * @brief Test context for spec:/newlib/req/futex-wait test case.
0099  */
0100 typedef struct {
0101   /**
0102    * @brief This member contains the thread queue test context.
0103    */
0104   TQContext tq_ctx;
0105 
0106   /**
0107    * @brief This member specifies the expected futex state value.
0108    */
0109   int expected_value;
0110 
0111   /**
0112    * @brief This member provides the futex object.
0113    */
0114   struct _Futex_Control futex;
0115 
0116   /**
0117    * @brief This member provides the futex state.
0118    */
0119   int state;
0120 
0121   struct {
0122     /**
0123      * @brief This member defines the pre-condition states for the next action.
0124      */
0125     size_t pcs[ 1 ];
0126 
0127     /**
0128      * @brief If this member is true, then the test action loop is executed.
0129      */
0130     bool in_action_loop;
0131 
0132     /**
0133      * @brief This member contains the next transition map index.
0134      */
0135     size_t index;
0136 
0137     /**
0138      * @brief This member contains the current transition map entry.
0139      */
0140     NewlibReqFutexWait_Entry entry;
0141 
0142     /**
0143      * @brief If this member is true, then the current transition variant
0144      *   should be skipped.
0145      */
0146     bool skip;
0147   } Map;
0148 } NewlibReqFutexWait_Context;
0149 
0150 static NewlibReqFutexWait_Context
0151   NewlibReqFutexWait_Instance;
0152 
0153 static const char * const NewlibReqFutexWait_PreDesc_State[] = {
0154   "Equal",
0155   "NotEqual",
0156   "NA"
0157 };
0158 
0159 static const char * const * const NewlibReqFutexWait_PreDesc[] = {
0160   NewlibReqFutexWait_PreDesc_State,
0161   NULL
0162 };
0163 
0164 typedef NewlibReqFutexWait_Context Context;
0165 
0166 static Context *ToContext( TQContext *tq_ctx )
0167 {
0168   return RTEMS_CONTAINER_OF( tq_ctx, Context, tq_ctx );
0169 }
0170 
0171 static Status_Control Enqueue( TQContext *tq_ctx, TQWait wait )
0172 {
0173   Context *ctx;
0174   int      eno;
0175 
0176   ctx = ToContext( tq_ctx );
0177   eno = _Futex_Wait( &ctx->futex, &ctx->state, ctx->expected_value );
0178   T_eq_int( eno, 0 );
0179 
0180   return STATUS_BUILD( 0, eno );
0181 }
0182 
0183 static void EnqueueDone( TQContext *tq_ctx )
0184 {
0185   Context *ctx;
0186   int      count;
0187 
0188   ctx = ToContext( tq_ctx );
0189   count = _Futex_Wake( &ctx->futex, INT_MAX );
0190   T_eq_int( count, (int) ctx->tq_ctx.how_many );
0191 }
0192 
0193 static void NewlibReqFutexWait_Pre_State_Prepare(
0194   NewlibReqFutexWait_Context  *ctx,
0195   NewlibReqFutexWait_Pre_State state
0196 )
0197 {
0198   switch ( state ) {
0199     case NewlibReqFutexWait_Pre_State_Equal: {
0200       /*
0201        * While the expected futex state value is equal to the actual futex
0202        * state value.
0203        */
0204       ctx->expected_value = 0;
0205       break;
0206     }
0207 
0208     case NewlibReqFutexWait_Pre_State_NotEqual: {
0209       /*
0210        * While the expected futex state value is not equal to the actual futex
0211        * state value.
0212        */
0213       ctx->expected_value = 1;
0214       break;
0215     }
0216 
0217     case NewlibReqFutexWait_Pre_State_NA:
0218       break;
0219   }
0220 }
0221 
0222 static void NewlibReqFutexWait_Post_Result_Check(
0223   NewlibReqFutexWait_Context    *ctx,
0224   NewlibReqFutexWait_Post_Result state
0225 )
0226 {
0227   int eno;
0228 
0229   switch ( state ) {
0230     case NewlibReqFutexWait_Post_Result_Zero: {
0231       /*
0232        * The return status of _Futex_Wait() shall be zero.
0233        */
0234       /* This result is checked by Enqueue() */
0235       break;
0236     }
0237 
0238     case NewlibReqFutexWait_Post_Result_EAGAIN: {
0239       /*
0240        * The return status of _Futex_Wait() shall be EAGAIN.
0241        */
0242       eno = _Futex_Wait( &ctx->futex, &ctx->state, ctx->expected_value );
0243       T_eq_int( eno, EAGAIN );
0244       break;
0245     }
0246 
0247     case NewlibReqFutexWait_Post_Result_NA:
0248       break;
0249   }
0250 }
0251 
0252 static void NewlibReqFutexWait_Post_Enqueue_Check(
0253   NewlibReqFutexWait_Context     *ctx,
0254   NewlibReqFutexWait_Post_Enqueue state
0255 )
0256 {
0257   switch ( state ) {
0258     case NewlibReqFutexWait_Post_Enqueue_No: {
0259       /*
0260        * The calling thread shall not be enqueued on the thread queue of the
0261        * futex object.
0262        */
0263       /* The runner would block forever */
0264       break;
0265     }
0266 
0267     case NewlibReqFutexWait_Post_Enqueue_Yes: {
0268       /*
0269        * The calling thread shall be enqueued in FIFO order on the thread queue
0270        * of the futex object.
0271        */
0272       ScoreTqReqEnqueueFifo_Run( &ctx->tq_ctx );
0273       break;
0274     }
0275 
0276     case NewlibReqFutexWait_Post_Enqueue_NA:
0277       break;
0278   }
0279 }
0280 
0281 static void NewlibReqFutexWait_Setup( NewlibReqFutexWait_Context *ctx )
0282 {
0283   memset( ctx, 0, sizeof( *ctx ) );
0284   ctx->tq_ctx.discipline = TQ_FIFO;
0285   ctx->tq_ctx.wait = TQ_WAIT_FOREVER;
0286   ctx->tq_ctx.enqueue_prepare = TQDoNothing;
0287   ctx->tq_ctx.enqueue = Enqueue;
0288   ctx->tq_ctx.enqueue_done = EnqueueDone;
0289   ctx->tq_ctx.surrender = TQDoNothingSuccessfully;
0290   ctx->tq_ctx.convert_status = TQConvertStatusPOSIX;
0291   TQInitialize( &ctx->tq_ctx );
0292 }
0293 
0294 static void NewlibReqFutexWait_Setup_Wrap( void *arg )
0295 {
0296   NewlibReqFutexWait_Context *ctx;
0297 
0298   ctx = arg;
0299   ctx->Map.in_action_loop = false;
0300   NewlibReqFutexWait_Setup( ctx );
0301 }
0302 
0303 static void NewlibReqFutexWait_Teardown( NewlibReqFutexWait_Context *ctx )
0304 {
0305   TQDestroy( &ctx->tq_ctx );
0306 }
0307 
0308 static void NewlibReqFutexWait_Teardown_Wrap( void *arg )
0309 {
0310   NewlibReqFutexWait_Context *ctx;
0311 
0312   ctx = arg;
0313   ctx->Map.in_action_loop = false;
0314   NewlibReqFutexWait_Teardown( ctx );
0315 }
0316 
0317 static void NewlibReqFutexWait_Prepare( NewlibReqFutexWait_Context *ctx )
0318 {
0319   _Futex_Initialize( &ctx->futex );
0320   ctx->state = 0;
0321 }
0322 
0323 static void NewlibReqFutexWait_Action( NewlibReqFutexWait_Context *ctx )
0324 {
0325   /* The action is performed in the post-conditions. */
0326 }
0327 
0328 static void NewlibReqFutexWait_Cleanup( NewlibReqFutexWait_Context *ctx )
0329 {
0330   _Futex_Destroy( &ctx->futex );
0331 }
0332 
0333 static const NewlibReqFutexWait_Entry
0334 NewlibReqFutexWait_Entries[] = {
0335   { 0, 0, NewlibReqFutexWait_Post_Result_Zero,
0336     NewlibReqFutexWait_Post_Enqueue_Yes },
0337   { 0, 0, NewlibReqFutexWait_Post_Result_EAGAIN,
0338     NewlibReqFutexWait_Post_Enqueue_No }
0339 };
0340 
0341 static const uint8_t
0342 NewlibReqFutexWait_Map[] = {
0343   0, 1
0344 };
0345 
0346 static size_t NewlibReqFutexWait_Scope( void *arg, char *buf, size_t n )
0347 {
0348   NewlibReqFutexWait_Context *ctx;
0349 
0350   ctx = arg;
0351 
0352   if ( ctx->Map.in_action_loop ) {
0353     return T_get_scope( NewlibReqFutexWait_PreDesc, buf, n, ctx->Map.pcs );
0354   }
0355 
0356   return 0;
0357 }
0358 
0359 static T_fixture NewlibReqFutexWait_Fixture = {
0360   .setup = NewlibReqFutexWait_Setup_Wrap,
0361   .stop = NULL,
0362   .teardown = NewlibReqFutexWait_Teardown_Wrap,
0363   .scope = NewlibReqFutexWait_Scope,
0364   .initial_context = &NewlibReqFutexWait_Instance
0365 };
0366 
0367 static inline NewlibReqFutexWait_Entry NewlibReqFutexWait_PopEntry(
0368   NewlibReqFutexWait_Context *ctx
0369 )
0370 {
0371   size_t index;
0372 
0373   index = ctx->Map.index;
0374   ctx->Map.index = index + 1;
0375   return NewlibReqFutexWait_Entries[
0376     NewlibReqFutexWait_Map[ index ]
0377   ];
0378 }
0379 
0380 static void NewlibReqFutexWait_TestVariant( NewlibReqFutexWait_Context *ctx )
0381 {
0382   NewlibReqFutexWait_Pre_State_Prepare( ctx, ctx->Map.pcs[ 0 ] );
0383   NewlibReqFutexWait_Action( ctx );
0384   NewlibReqFutexWait_Post_Result_Check( ctx, ctx->Map.entry.Post_Result );
0385   NewlibReqFutexWait_Post_Enqueue_Check( ctx, ctx->Map.entry.Post_Enqueue );
0386 }
0387 
0388 /**
0389  * @fn void T_case_body_NewlibReqFutexWait( void )
0390  */
0391 T_TEST_CASE_FIXTURE( NewlibReqFutexWait, &NewlibReqFutexWait_Fixture )
0392 {
0393   NewlibReqFutexWait_Context *ctx;
0394 
0395   ctx = T_fixture_context();
0396   ctx->Map.in_action_loop = true;
0397   ctx->Map.index = 0;
0398 
0399   for (
0400     ctx->Map.pcs[ 0 ] = NewlibReqFutexWait_Pre_State_Equal;
0401     ctx->Map.pcs[ 0 ] < NewlibReqFutexWait_Pre_State_NA;
0402     ++ctx->Map.pcs[ 0 ]
0403   ) {
0404     ctx->Map.entry = NewlibReqFutexWait_PopEntry( ctx );
0405     NewlibReqFutexWait_Prepare( ctx );
0406     NewlibReqFutexWait_TestVariant( ctx );
0407     NewlibReqFutexWait_Cleanup( ctx );
0408   }
0409 }
0410 
0411 /** @} */