File indexing completed on 2025-05-11 08:24:52
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 <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
0067
0068
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
0105
0106 typedef struct {
0107
0108
0109
0110 TQContext tq_ctx;
0111
0112
0113
0114
0115 rtems_attribute attribute_set;
0116
0117 struct {
0118
0119
0120
0121 size_t pcs[ 2 ];
0122
0123
0124
0125
0126 bool in_action_loop;
0127
0128
0129
0130
0131 size_t index;
0132
0133
0134
0135
0136 RtemsSemReqTimeout_Entry entry;
0137
0138
0139
0140
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
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
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
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
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
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
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
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
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
0283
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
0293
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
0307
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
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