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 NewlibReqFutexWake
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-flush-fifo.h"
0060 #include "tx-thread-queue.h"
0061 
0062 #include <rtems/test.h>
0063 
0064 /**
0065  * @defgroup NewlibReqFutexWake spec:/newlib/req/futex-wake
0066  *
0067  * @ingroup TestsuitesValidationNoClock0
0068  *
0069  * @{
0070  */
0071 
0072 typedef enum {
0073   NewlibReqFutexWake_Pre_Count_NegativeOrZero,
0074   NewlibReqFutexWake_Pre_Count_Positive,
0075   NewlibReqFutexWake_Pre_Count_NA
0076 } NewlibReqFutexWake_Pre_Count;
0077 
0078 typedef enum {
0079   NewlibReqFutexWake_Post_Result_Count,
0080   NewlibReqFutexWake_Post_Result_NA
0081 } NewlibReqFutexWake_Post_Result;
0082 
0083 typedef enum {
0084   NewlibReqFutexWake_Post_Flush_No,
0085   NewlibReqFutexWake_Post_Flush_Yes,
0086   NewlibReqFutexWake_Post_Flush_NA
0087 } NewlibReqFutexWake_Post_Flush;
0088 
0089 typedef struct {
0090   uint8_t Skip : 1;
0091   uint8_t Pre_Count_NA : 1;
0092   uint8_t Post_Result : 1;
0093   uint8_t Post_Flush : 2;
0094 } NewlibReqFutexWake_Entry;
0095 
0096 /**
0097  * @brief Test context for spec:/newlib/req/futex-wake test case.
0098  */
0099 typedef struct {
0100   /**
0101    * @brief This member contains the thread queue test context.
0102    */
0103   TQContext tq_ctx;
0104 
0105   /**
0106    * @brief This member provides the futex object.
0107    */
0108   struct _Futex_Control futex;
0109 
0110   /**
0111    * @brief This member provides the futex state.
0112    */
0113   int state;
0114 
0115   struct {
0116     /**
0117      * @brief This member defines the pre-condition states for the next action.
0118      */
0119     size_t pcs[ 1 ];
0120 
0121     /**
0122      * @brief If this member is true, then the test action loop is executed.
0123      */
0124     bool in_action_loop;
0125 
0126     /**
0127      * @brief This member contains the next transition map index.
0128      */
0129     size_t index;
0130 
0131     /**
0132      * @brief This member contains the current transition map entry.
0133      */
0134     NewlibReqFutexWake_Entry entry;
0135 
0136     /**
0137      * @brief If this member is true, then the current transition variant
0138      *   should be skipped.
0139      */
0140     bool skip;
0141   } Map;
0142 } NewlibReqFutexWake_Context;
0143 
0144 static NewlibReqFutexWake_Context
0145   NewlibReqFutexWake_Instance;
0146 
0147 static const char * const NewlibReqFutexWake_PreDesc_Count[] = {
0148   "NegativeOrZero",
0149   "Positive",
0150   "NA"
0151 };
0152 
0153 static const char * const * const NewlibReqFutexWake_PreDesc[] = {
0154   NewlibReqFutexWake_PreDesc_Count,
0155   NULL
0156 };
0157 
0158 typedef NewlibReqFutexWake_Context Context;
0159 
0160 static Context *ToContext( TQContext *tq_ctx )
0161 {
0162   return RTEMS_CONTAINER_OF( tq_ctx, Context, tq_ctx );
0163 }
0164 
0165 static Status_Control Enqueue( TQContext *tq_ctx, TQWait wait )
0166 {
0167   Context *ctx;
0168   int      count;
0169   int      eno;
0170 
0171   ctx = ToContext( tq_ctx );
0172 
0173   count = _Futex_Wake( &ctx->futex, -1 );
0174   T_eq_int( count, 0 );
0175 
0176   count = _Futex_Wake( &ctx->futex, 0 );
0177   T_eq_int( count, 0 );
0178 
0179   eno = _Futex_Wait( &ctx->futex, &ctx->state, 0 );
0180   T_eq_int( eno, 0 );
0181 
0182   return STATUS_BUILD( 0, eno );
0183 }
0184 
0185 static uint32_t Flush( TQContext *tq_ctx, uint32_t thread_count, bool all )
0186 {
0187   Context *ctx;
0188   int      count;
0189 
0190   (void) thread_count;
0191 
0192   ctx = ToContext( tq_ctx );
0193 
0194   if ( all ) {
0195     count = _Futex_Wake( &ctx->futex, INT_MAX );
0196   } else {
0197     count = _Futex_Wake( &ctx->futex, 1 );
0198   }
0199 
0200   return (uint32_t) count;
0201 }
0202 
0203 static void NewlibReqFutexWake_Pre_Count_Prepare(
0204   NewlibReqFutexWake_Context  *ctx,
0205   NewlibReqFutexWake_Pre_Count state
0206 )
0207 {
0208   switch ( state ) {
0209     case NewlibReqFutexWake_Pre_Count_NegativeOrZero: {
0210       /*
0211        * While the ``count`` parameter is less or equal to than zero.
0212        */
0213       /* This state is prepared by Enqueue() */
0214       break;
0215     }
0216 
0217     case NewlibReqFutexWake_Pre_Count_Positive: {
0218       /*
0219        * While the ``count`` parameter is greater than zero.
0220        */
0221       /* This state is prepared by Flush() */
0222       break;
0223     }
0224 
0225     case NewlibReqFutexWake_Pre_Count_NA:
0226       break;
0227   }
0228 }
0229 
0230 static void NewlibReqFutexWake_Post_Result_Check(
0231   NewlibReqFutexWake_Context    *ctx,
0232   NewlibReqFutexWake_Post_Result state
0233 )
0234 {
0235   switch ( state ) {
0236     case NewlibReqFutexWake_Post_Result_Count: {
0237       /*
0238        * The return status of _Futex_Wake() shall be the count of threads
0239        * extracted from the thread queue of the futex object.
0240        */
0241       /* This result is checked by Flush() */
0242       break;
0243     }
0244 
0245     case NewlibReqFutexWake_Post_Result_NA:
0246       break;
0247   }
0248 }
0249 
0250 static void NewlibReqFutexWake_Post_Flush_Check(
0251   NewlibReqFutexWake_Context   *ctx,
0252   NewlibReqFutexWake_Post_Flush state
0253 )
0254 {
0255   switch ( state ) {
0256     case NewlibReqFutexWake_Post_Flush_No: {
0257       /*
0258        * No thread shall be extracted from the thread queue of the futex
0259        * object.
0260        */
0261       /* This state is checked by Enqueue() */
0262       break;
0263     }
0264 
0265     case NewlibReqFutexWake_Post_Flush_Yes: {
0266       /*
0267        * The first count threads specified by the ``count`` parameter shall be
0268        * extracted from the thread queue of the futex object in FIFO order.
0269        */
0270       ScoreTqReqFlushFifo_Run( &ctx->tq_ctx, true );
0271       break;
0272     }
0273 
0274     case NewlibReqFutexWake_Post_Flush_NA:
0275       break;
0276   }
0277 }
0278 
0279 static void NewlibReqFutexWake_Setup( NewlibReqFutexWake_Context *ctx )
0280 {
0281   memset( ctx, 0, sizeof( *ctx ) );
0282   ctx->tq_ctx.discipline = TQ_FIFO;
0283   ctx->tq_ctx.wait = TQ_WAIT_FOREVER;
0284   ctx->tq_ctx.enqueue_prepare = TQDoNothing;
0285   ctx->tq_ctx.enqueue = Enqueue;
0286   ctx->tq_ctx.enqueue_done = TQDoNothing;
0287   ctx->tq_ctx.flush = Flush;
0288   ctx->tq_ctx.surrender = TQDoNothingSuccessfully;
0289   ctx->tq_ctx.convert_status = TQConvertStatusPOSIX;
0290   TQInitialize( &ctx->tq_ctx );
0291 }
0292 
0293 static void NewlibReqFutexWake_Setup_Wrap( void *arg )
0294 {
0295   NewlibReqFutexWake_Context *ctx;
0296 
0297   ctx = arg;
0298   ctx->Map.in_action_loop = false;
0299   NewlibReqFutexWake_Setup( ctx );
0300 }
0301 
0302 static void NewlibReqFutexWake_Teardown( NewlibReqFutexWake_Context *ctx )
0303 {
0304   TQDestroy( &ctx->tq_ctx );
0305 }
0306 
0307 static void NewlibReqFutexWake_Teardown_Wrap( void *arg )
0308 {
0309   NewlibReqFutexWake_Context *ctx;
0310 
0311   ctx = arg;
0312   ctx->Map.in_action_loop = false;
0313   NewlibReqFutexWake_Teardown( ctx );
0314 }
0315 
0316 static void NewlibReqFutexWake_Prepare( NewlibReqFutexWake_Context *ctx )
0317 {
0318   _Futex_Initialize( &ctx->futex );
0319 }
0320 
0321 static void NewlibReqFutexWake_Action( NewlibReqFutexWake_Context *ctx )
0322 {
0323   /* The action is performed in the ``Flush`` post-condition ``All`` state. */
0324 }
0325 
0326 static void NewlibReqFutexWake_Cleanup( NewlibReqFutexWake_Context *ctx )
0327 {
0328   _Futex_Destroy( &ctx->futex );
0329 }
0330 
0331 static const NewlibReqFutexWake_Entry
0332 NewlibReqFutexWake_Entries[] = {
0333   { 0, 0, NewlibReqFutexWake_Post_Result_Count,
0334     NewlibReqFutexWake_Post_Flush_No },
0335   { 0, 0, NewlibReqFutexWake_Post_Result_Count,
0336     NewlibReqFutexWake_Post_Flush_Yes }
0337 };
0338 
0339 static const uint8_t
0340 NewlibReqFutexWake_Map[] = {
0341   0, 1
0342 };
0343 
0344 static size_t NewlibReqFutexWake_Scope( void *arg, char *buf, size_t n )
0345 {
0346   NewlibReqFutexWake_Context *ctx;
0347 
0348   ctx = arg;
0349 
0350   if ( ctx->Map.in_action_loop ) {
0351     return T_get_scope( NewlibReqFutexWake_PreDesc, buf, n, ctx->Map.pcs );
0352   }
0353 
0354   return 0;
0355 }
0356 
0357 static T_fixture NewlibReqFutexWake_Fixture = {
0358   .setup = NewlibReqFutexWake_Setup_Wrap,
0359   .stop = NULL,
0360   .teardown = NewlibReqFutexWake_Teardown_Wrap,
0361   .scope = NewlibReqFutexWake_Scope,
0362   .initial_context = &NewlibReqFutexWake_Instance
0363 };
0364 
0365 static inline NewlibReqFutexWake_Entry NewlibReqFutexWake_PopEntry(
0366   NewlibReqFutexWake_Context *ctx
0367 )
0368 {
0369   size_t index;
0370 
0371   index = ctx->Map.index;
0372   ctx->Map.index = index + 1;
0373   return NewlibReqFutexWake_Entries[
0374     NewlibReqFutexWake_Map[ index ]
0375   ];
0376 }
0377 
0378 static void NewlibReqFutexWake_TestVariant( NewlibReqFutexWake_Context *ctx )
0379 {
0380   NewlibReqFutexWake_Pre_Count_Prepare( ctx, ctx->Map.pcs[ 0 ] );
0381   NewlibReqFutexWake_Action( ctx );
0382   NewlibReqFutexWake_Post_Result_Check( ctx, ctx->Map.entry.Post_Result );
0383   NewlibReqFutexWake_Post_Flush_Check( ctx, ctx->Map.entry.Post_Flush );
0384 }
0385 
0386 /**
0387  * @fn void T_case_body_NewlibReqFutexWake( void )
0388  */
0389 T_TEST_CASE_FIXTURE( NewlibReqFutexWake, &NewlibReqFutexWake_Fixture )
0390 {
0391   NewlibReqFutexWake_Context *ctx;
0392 
0393   ctx = T_fixture_context();
0394   ctx->Map.in_action_loop = true;
0395   ctx->Map.index = 0;
0396 
0397   for (
0398     ctx->Map.pcs[ 0 ] = NewlibReqFutexWake_Pre_Count_NegativeOrZero;
0399     ctx->Map.pcs[ 0 ] < NewlibReqFutexWake_Pre_Count_NA;
0400     ++ctx->Map.pcs[ 0 ]
0401   ) {
0402     ctx->Map.entry = NewlibReqFutexWake_PopEntry( ctx );
0403     NewlibReqFutexWake_Prepare( ctx );
0404     NewlibReqFutexWake_TestVariant( ctx );
0405     NewlibReqFutexWake_Cleanup( ctx );
0406   }
0407 }
0408 
0409 /** @} */