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-flush-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 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
0098
0099 typedef struct {
0100
0101
0102
0103 TQContext tq_ctx;
0104
0105
0106
0107
0108 struct _Futex_Control futex;
0109
0110
0111
0112
0113 int state;
0114
0115 struct {
0116
0117
0118
0119 size_t pcs[ 1 ];
0120
0121
0122
0123
0124 bool in_action_loop;
0125
0126
0127
0128
0129 size_t index;
0130
0131
0132
0133
0134 NewlibReqFutexWake_Entry entry;
0135
0136
0137
0138
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
0212
0213
0214 break;
0215 }
0216
0217 case NewlibReqFutexWake_Pre_Count_Positive: {
0218
0219
0220
0221
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
0239
0240
0241
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
0259
0260
0261
0262 break;
0263 }
0264
0265 case NewlibReqFutexWake_Post_Flush_Yes: {
0266
0267
0268
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
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
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