File indexing completed on 2025-05-11 08:24:51
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
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
0066
0067
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
0099
0100 typedef struct {
0101
0102
0103
0104 TQContext tq_ctx;
0105
0106
0107
0108
0109 int expected_value;
0110
0111
0112
0113
0114 struct _Futex_Control futex;
0115
0116
0117
0118
0119 int state;
0120
0121 struct {
0122
0123
0124
0125 size_t pcs[ 1 ];
0126
0127
0128
0129
0130 bool in_action_loop;
0131
0132
0133
0134
0135 size_t index;
0136
0137
0138
0139
0140 NewlibReqFutexWait_Entry entry;
0141
0142
0143
0144
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
0202
0203
0204 ctx->expected_value = 0;
0205 break;
0206 }
0207
0208 case NewlibReqFutexWait_Pre_State_NotEqual: {
0209
0210
0211
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
0233
0234
0235 break;
0236 }
0237
0238 case NewlibReqFutexWait_Post_Result_EAGAIN: {
0239
0240
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
0261
0262
0263
0264 break;
0265 }
0266
0267 case NewlibReqFutexWait_Post_Enqueue_Yes: {
0268
0269
0270
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
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
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