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-mtx-surrender.h"
0059 #include "tr-sem-surrender.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 RtemsSemReqRelease_Pre_Class_Counting,
0075 RtemsSemReqRelease_Pre_Class_Simple,
0076 RtemsSemReqRelease_Pre_Class_Binary,
0077 RtemsSemReqRelease_Pre_Class_PrioCeiling,
0078 RtemsSemReqRelease_Pre_Class_PrioInherit,
0079 RtemsSemReqRelease_Pre_Class_MrsP,
0080 RtemsSemReqRelease_Pre_Class_NA
0081 } RtemsSemReqRelease_Pre_Class;
0082
0083 typedef enum {
0084 RtemsSemReqRelease_Pre_Discipline_FIFO,
0085 RtemsSemReqRelease_Pre_Discipline_Priority,
0086 RtemsSemReqRelease_Pre_Discipline_NA
0087 } RtemsSemReqRelease_Pre_Discipline;
0088
0089 typedef enum {
0090 RtemsSemReqRelease_Pre_Id_Valid,
0091 RtemsSemReqRelease_Pre_Id_Invalid,
0092 RtemsSemReqRelease_Pre_Id_NA
0093 } RtemsSemReqRelease_Pre_Id;
0094
0095 typedef enum {
0096 RtemsSemReqRelease_Post_Action_InvId,
0097 RtemsSemReqRelease_Post_Action_BinarySurrender,
0098 RtemsSemReqRelease_Post_Action_CountingSurrender,
0099 RtemsSemReqRelease_Post_Action_MtxSurrender,
0100 RtemsSemReqRelease_Post_Action_InheritMtxSurrender,
0101 RtemsSemReqRelease_Post_Action_CeilingMtxSurrender,
0102 RtemsSemReqRelease_Post_Action_MrsPMtxSurrender,
0103 RtemsSemReqRelease_Post_Action_NA
0104 } RtemsSemReqRelease_Post_Action;
0105
0106 typedef struct {
0107 uint8_t Skip : 1;
0108 uint8_t Pre_Class_NA : 1;
0109 uint8_t Pre_Discipline_NA : 1;
0110 uint8_t Pre_Id_NA : 1;
0111 uint8_t Post_Action : 3;
0112 } RtemsSemReqRelease_Entry;
0113
0114
0115
0116
0117 typedef struct {
0118
0119
0120
0121 union {
0122 TQContext tq_ctx;
0123 TQMtxContext tq_mtx_ctx;
0124 TQSemContext tq_sem_ctx;
0125 };
0126
0127
0128
0129
0130 rtems_attribute attribute_set;
0131
0132 struct {
0133
0134
0135
0136 size_t pcs[ 3 ];
0137
0138
0139
0140
0141 bool in_action_loop;
0142
0143
0144
0145
0146 size_t index;
0147
0148
0149
0150
0151 RtemsSemReqRelease_Entry entry;
0152
0153
0154
0155
0156
0157 bool skip;
0158 } Map;
0159 } RtemsSemReqRelease_Context;
0160
0161 static RtemsSemReqRelease_Context
0162 RtemsSemReqRelease_Instance;
0163
0164 static const char * const RtemsSemReqRelease_PreDesc_Class[] = {
0165 "Counting",
0166 "Simple",
0167 "Binary",
0168 "PrioCeiling",
0169 "PrioInherit",
0170 "MrsP",
0171 "NA"
0172 };
0173
0174 static const char * const RtemsSemReqRelease_PreDesc_Discipline[] = {
0175 "FIFO",
0176 "Priority",
0177 "NA"
0178 };
0179
0180 static const char * const RtemsSemReqRelease_PreDesc_Id[] = {
0181 "Valid",
0182 "Invalid",
0183 "NA"
0184 };
0185
0186 static const char * const * const RtemsSemReqRelease_PreDesc[] = {
0187 RtemsSemReqRelease_PreDesc_Class,
0188 RtemsSemReqRelease_PreDesc_Discipline,
0189 RtemsSemReqRelease_PreDesc_Id,
0190 NULL
0191 };
0192
0193 #define NAME rtems_build_name( 'T', 'E', 'S', 'T' )
0194
0195 typedef RtemsSemReqRelease_Context Context;
0196
0197 static void RtemsSemReqRelease_Pre_Class_Prepare(
0198 RtemsSemReqRelease_Context *ctx,
0199 RtemsSemReqRelease_Pre_Class state
0200 )
0201 {
0202 switch ( state ) {
0203 case RtemsSemReqRelease_Pre_Class_Counting: {
0204
0205
0206
0207 ctx->attribute_set |= RTEMS_COUNTING_SEMAPHORE;
0208 break;
0209 }
0210
0211 case RtemsSemReqRelease_Pre_Class_Simple: {
0212
0213
0214
0215 ctx->attribute_set |= RTEMS_SIMPLE_BINARY_SEMAPHORE;
0216 break;
0217 }
0218
0219 case RtemsSemReqRelease_Pre_Class_Binary: {
0220
0221
0222
0223 ctx->attribute_set |= RTEMS_BINARY_SEMAPHORE;
0224 break;
0225 }
0226
0227 case RtemsSemReqRelease_Pre_Class_PrioCeiling: {
0228
0229
0230
0231 ctx->attribute_set |= RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY_CEILING;
0232 break;
0233 }
0234
0235 case RtemsSemReqRelease_Pre_Class_PrioInherit: {
0236
0237
0238
0239 ctx->attribute_set |= RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY;
0240 break;
0241 }
0242
0243 case RtemsSemReqRelease_Pre_Class_MrsP: {
0244
0245
0246
0247 ctx->attribute_set |= RTEMS_BINARY_SEMAPHORE |
0248 RTEMS_MULTIPROCESSOR_RESOURCE_SHARING;
0249 break;
0250 }
0251
0252 case RtemsSemReqRelease_Pre_Class_NA:
0253 break;
0254 }
0255 }
0256
0257 static void RtemsSemReqRelease_Pre_Discipline_Prepare(
0258 RtemsSemReqRelease_Context *ctx,
0259 RtemsSemReqRelease_Pre_Discipline state
0260 )
0261 {
0262 switch ( state ) {
0263 case RtemsSemReqRelease_Pre_Discipline_FIFO: {
0264
0265
0266
0267 ctx->attribute_set |= RTEMS_FIFO;
0268 ctx->tq_ctx.discipline = TQ_FIFO;
0269 break;
0270 }
0271
0272 case RtemsSemReqRelease_Pre_Discipline_Priority: {
0273
0274
0275
0276 ctx->attribute_set |= RTEMS_PRIORITY;
0277 ctx->tq_ctx.discipline = TQ_PRIORITY;
0278 break;
0279 }
0280
0281 case RtemsSemReqRelease_Pre_Discipline_NA:
0282 break;
0283 }
0284 }
0285
0286 static void RtemsSemReqRelease_Pre_Id_Prepare(
0287 RtemsSemReqRelease_Context *ctx,
0288 RtemsSemReqRelease_Pre_Id state
0289 )
0290 {
0291 switch ( state ) {
0292 case RtemsSemReqRelease_Pre_Id_Valid: {
0293
0294
0295
0296
0297 break;
0298 }
0299
0300 case RtemsSemReqRelease_Pre_Id_Invalid: {
0301
0302
0303
0304
0305 break;
0306 }
0307
0308 case RtemsSemReqRelease_Pre_Id_NA:
0309 break;
0310 }
0311 }
0312
0313 static void RtemsSemReqRelease_Post_Action_Check(
0314 RtemsSemReqRelease_Context *ctx,
0315 RtemsSemReqRelease_Post_Action state
0316 )
0317 {
0318 rtems_status_code sc;
0319
0320 switch ( state ) {
0321 case RtemsSemReqRelease_Post_Action_InvId: {
0322
0323
0324
0325
0326 sc = rtems_semaphore_release( 0xffffffff );
0327 T_rsc( sc, RTEMS_INVALID_ID );
0328 break;
0329 }
0330
0331 case RtemsSemReqRelease_Post_Action_BinarySurrender: {
0332
0333
0334
0335
0336 ctx->tq_ctx.enqueue_variant = TQ_ENQUEUE_BLOCKS;
0337 ctx->tq_ctx.get_owner = NULL;
0338 ctx->tq_sem_ctx.variant = TQ_SEM_BINARY;
0339 ctx->tq_sem_ctx.get_count = TQSemGetCountClassic;
0340 ctx->tq_sem_ctx.set_count = TQSemSetCountClassic;
0341 ScoreSemReqSurrender_Run( &ctx->tq_sem_ctx );
0342 break;
0343 }
0344
0345 case RtemsSemReqRelease_Post_Action_CountingSurrender: {
0346
0347
0348
0349
0350 ctx->tq_ctx.enqueue_variant = TQ_ENQUEUE_BLOCKS;
0351 ctx->tq_ctx.get_owner = NULL;
0352 ctx->tq_sem_ctx.variant = TQ_SEM_COUNTING;
0353 ctx->tq_sem_ctx.get_count = TQSemGetCountClassic;
0354 ctx->tq_sem_ctx.set_count = TQSemSetCountClassic;
0355 ScoreSemReqSurrender_Run( &ctx->tq_sem_ctx );
0356 break;
0357 }
0358
0359 case RtemsSemReqRelease_Post_Action_MtxSurrender: {
0360
0361
0362
0363
0364
0365
0366 ctx->tq_ctx.enqueue_variant = TQ_ENQUEUE_BLOCKS;
0367 ctx->tq_ctx.get_owner = TQGetOwnerClassicSem;
0368 ctx->tq_mtx_ctx.protocol = TQ_MTX_NO_PROTOCOL;
0369 ctx->tq_mtx_ctx.recursive = TQ_MTX_RECURSIVE_ALLOWED;
0370 ctx->tq_mtx_ctx.owner_check = TQ_MTX_CHECKS_OWNER;
0371 ctx->tq_mtx_ctx.priority_ceiling = PRIO_INVALID;
0372 ScoreMtxReqSurrender_Run( &ctx->tq_mtx_ctx );
0373 break;
0374 }
0375
0376 case RtemsSemReqRelease_Post_Action_InheritMtxSurrender: {
0377
0378
0379
0380
0381
0382
0383 ctx->tq_ctx.enqueue_variant = TQ_ENQUEUE_BLOCKS;
0384 ctx->tq_ctx.get_owner = TQGetOwnerClassicSem;
0385 ctx->tq_mtx_ctx.protocol = TQ_MTX_PRIORITY_INHERIT;
0386 ctx->tq_mtx_ctx.recursive = TQ_MTX_RECURSIVE_ALLOWED;
0387 ctx->tq_mtx_ctx.owner_check = TQ_MTX_CHECKS_OWNER;
0388 ctx->tq_mtx_ctx.priority_ceiling = PRIO_INVALID;
0389 ScoreMtxReqSurrender_Run( &ctx->tq_mtx_ctx );
0390 break;
0391 }
0392
0393 case RtemsSemReqRelease_Post_Action_CeilingMtxSurrender: {
0394
0395
0396
0397
0398
0399
0400 ctx->tq_ctx.enqueue_variant = TQ_ENQUEUE_BLOCKS;
0401 ctx->tq_ctx.get_owner = TQGetOwnerClassicSem;
0402 ctx->tq_mtx_ctx.protocol = TQ_MTX_PRIORITY_CEILING;
0403 ctx->tq_mtx_ctx.recursive = TQ_MTX_RECURSIVE_ALLOWED;
0404 ctx->tq_mtx_ctx.owner_check = TQ_MTX_CHECKS_OWNER;
0405 ctx->tq_mtx_ctx.priority_ceiling = PRIO_VERY_HIGH;
0406 ScoreMtxReqSurrender_Run( &ctx->tq_mtx_ctx );
0407 break;
0408 }
0409
0410 case RtemsSemReqRelease_Post_Action_MrsPMtxSurrender: {
0411
0412
0413
0414
0415
0416
0417 ctx->tq_ctx.enqueue_variant = TQ_ENQUEUE_STICKY;
0418 ctx->tq_ctx.get_owner = TQGetOwnerClassicSem;
0419 ctx->tq_mtx_ctx.protocol = TQ_MTX_MRSP;
0420 ctx->tq_mtx_ctx.recursive = TQ_MTX_RECURSIVE_DEADLOCK;
0421 ctx->tq_mtx_ctx.owner_check = TQ_MTX_CHECKS_OWNER;
0422 ctx->tq_mtx_ctx.priority_ceiling = PRIO_VERY_HIGH;
0423 ScoreMtxReqSurrender_Run( &ctx->tq_mtx_ctx );
0424 break;
0425 }
0426
0427 case RtemsSemReqRelease_Post_Action_NA:
0428 break;
0429 }
0430 }
0431
0432 static void RtemsSemReqRelease_Setup( RtemsSemReqRelease_Context *ctx )
0433 {
0434 SetSelfPriority( PRIO_NORMAL );
0435 memset( ctx, 0, sizeof( *ctx ) );
0436 ctx->tq_ctx.deadlock = TQ_DEADLOCK_STATUS;
0437 ctx->tq_ctx.enqueue_prepare = TQEnqueuePrepareDefault;
0438 ctx->tq_ctx.enqueue_done = TQEnqueueDoneDefault;
0439 ctx->tq_ctx.enqueue = TQEnqueueClassicSem;
0440 ctx->tq_ctx.surrender = TQSurrenderClassicSem;
0441 ctx->tq_ctx.convert_status = TQConvertStatusClassic;
0442 TQInitialize( &ctx->tq_ctx );
0443 }
0444
0445 static void RtemsSemReqRelease_Setup_Wrap( void *arg )
0446 {
0447 RtemsSemReqRelease_Context *ctx;
0448
0449 ctx = arg;
0450 ctx->Map.in_action_loop = false;
0451 RtemsSemReqRelease_Setup( ctx );
0452 }
0453
0454 static void RtemsSemReqRelease_Teardown( RtemsSemReqRelease_Context *ctx )
0455 {
0456 TQDestroy( &ctx->tq_ctx );
0457 RestoreRunnerPriority();
0458 }
0459
0460 static void RtemsSemReqRelease_Teardown_Wrap( void *arg )
0461 {
0462 RtemsSemReqRelease_Context *ctx;
0463
0464 ctx = arg;
0465 ctx->Map.in_action_loop = false;
0466 RtemsSemReqRelease_Teardown( ctx );
0467 }
0468
0469 static void RtemsSemReqRelease_Prepare( RtemsSemReqRelease_Context *ctx )
0470 {
0471 ctx->attribute_set = RTEMS_DEFAULT_ATTRIBUTES;
0472 }
0473
0474 static void RtemsSemReqRelease_Action( RtemsSemReqRelease_Context *ctx )
0475 {
0476 rtems_status_code sc;
0477
0478 sc = rtems_semaphore_create(
0479 NAME,
0480 1,
0481 ctx->attribute_set,
0482 PRIO_VERY_HIGH,
0483 &ctx->tq_ctx.thread_queue_id
0484 );
0485 T_rsc_success( sc );
0486
0487 if ( ( ctx->attribute_set & RTEMS_MULTIPROCESSOR_RESOURCE_SHARING ) != 0 ) {
0488 rtems_task_priority prio;
0489
0490 sc = rtems_semaphore_set_priority(
0491 ctx->tq_ctx.thread_queue_id,
0492 SCHEDULER_B_ID,
0493 PRIO_VERY_HIGH,
0494 &prio
0495 );
0496 T_rsc_success( sc );
0497 }
0498 }
0499
0500 static void RtemsSemReqRelease_Cleanup( RtemsSemReqRelease_Context *ctx )
0501 {
0502 rtems_status_code sc;
0503 sc = rtems_semaphore_delete( ctx->tq_ctx.thread_queue_id ); T_rsc_success( sc );
0504 }
0505
0506 static const RtemsSemReqRelease_Entry
0507 RtemsSemReqRelease_Entries[] = {
0508 { 0, 0, 0, 0, RtemsSemReqRelease_Post_Action_InvId },
0509 { 1, 0, 0, 0, RtemsSemReqRelease_Post_Action_NA },
0510 { 0, 0, 0, 0, RtemsSemReqRelease_Post_Action_CountingSurrender },
0511 { 0, 0, 0, 0, RtemsSemReqRelease_Post_Action_BinarySurrender },
0512 { 0, 0, 0, 0, RtemsSemReqRelease_Post_Action_MtxSurrender },
0513 { 0, 0, 0, 0, RtemsSemReqRelease_Post_Action_CeilingMtxSurrender },
0514 { 0, 0, 0, 0, RtemsSemReqRelease_Post_Action_InheritMtxSurrender },
0515 #if defined(RTEMS_SMP)
0516 { 0, 0, 0, 0, RtemsSemReqRelease_Post_Action_MrsPMtxSurrender },
0517 #else
0518 { 1, 0, 0, 0, RtemsSemReqRelease_Post_Action_NA },
0519 #endif
0520 #if defined(RTEMS_SMP)
0521 { 0, 0, 0, 0, RtemsSemReqRelease_Post_Action_InvId }
0522 #else
0523 { 1, 0, 0, 0, RtemsSemReqRelease_Post_Action_NA }
0524 #endif
0525 };
0526
0527 static const uint8_t
0528 RtemsSemReqRelease_Map[] = {
0529 2, 0, 2, 0, 3, 0, 3, 0, 4, 0, 4, 0, 1, 1, 5, 0, 1, 1, 6, 0, 1, 1, 7, 8
0530 };
0531
0532 static size_t RtemsSemReqRelease_Scope( void *arg, char *buf, size_t n )
0533 {
0534 RtemsSemReqRelease_Context *ctx;
0535
0536 ctx = arg;
0537
0538 if ( ctx->Map.in_action_loop ) {
0539 return T_get_scope( RtemsSemReqRelease_PreDesc, buf, n, ctx->Map.pcs );
0540 }
0541
0542 return 0;
0543 }
0544
0545 static T_fixture RtemsSemReqRelease_Fixture = {
0546 .setup = RtemsSemReqRelease_Setup_Wrap,
0547 .stop = NULL,
0548 .teardown = RtemsSemReqRelease_Teardown_Wrap,
0549 .scope = RtemsSemReqRelease_Scope,
0550 .initial_context = &RtemsSemReqRelease_Instance
0551 };
0552
0553 static inline RtemsSemReqRelease_Entry RtemsSemReqRelease_PopEntry(
0554 RtemsSemReqRelease_Context *ctx
0555 )
0556 {
0557 size_t index;
0558
0559 index = ctx->Map.index;
0560 ctx->Map.index = index + 1;
0561 return RtemsSemReqRelease_Entries[
0562 RtemsSemReqRelease_Map[ index ]
0563 ];
0564 }
0565
0566 static void RtemsSemReqRelease_TestVariant( RtemsSemReqRelease_Context *ctx )
0567 {
0568 RtemsSemReqRelease_Pre_Class_Prepare( ctx, ctx->Map.pcs[ 0 ] );
0569 RtemsSemReqRelease_Pre_Discipline_Prepare( ctx, ctx->Map.pcs[ 1 ] );
0570 RtemsSemReqRelease_Pre_Id_Prepare( ctx, ctx->Map.pcs[ 2 ] );
0571 RtemsSemReqRelease_Action( ctx );
0572 RtemsSemReqRelease_Post_Action_Check( ctx, ctx->Map.entry.Post_Action );
0573 }
0574
0575
0576
0577
0578 T_TEST_CASE_FIXTURE( RtemsSemReqRelease, &RtemsSemReqRelease_Fixture )
0579 {
0580 RtemsSemReqRelease_Context *ctx;
0581
0582 ctx = T_fixture_context();
0583 ctx->Map.in_action_loop = true;
0584 ctx->Map.index = 0;
0585
0586 for (
0587 ctx->Map.pcs[ 0 ] = RtemsSemReqRelease_Pre_Class_Counting;
0588 ctx->Map.pcs[ 0 ] < RtemsSemReqRelease_Pre_Class_NA;
0589 ++ctx->Map.pcs[ 0 ]
0590 ) {
0591 for (
0592 ctx->Map.pcs[ 1 ] = RtemsSemReqRelease_Pre_Discipline_FIFO;
0593 ctx->Map.pcs[ 1 ] < RtemsSemReqRelease_Pre_Discipline_NA;
0594 ++ctx->Map.pcs[ 1 ]
0595 ) {
0596 for (
0597 ctx->Map.pcs[ 2 ] = RtemsSemReqRelease_Pre_Id_Valid;
0598 ctx->Map.pcs[ 2 ] < RtemsSemReqRelease_Pre_Id_NA;
0599 ++ctx->Map.pcs[ 2 ]
0600 ) {
0601 ctx->Map.entry = RtemsSemReqRelease_PopEntry( ctx );
0602
0603 if ( ctx->Map.entry.Skip ) {
0604 continue;
0605 }
0606
0607 RtemsSemReqRelease_Prepare( ctx );
0608 RtemsSemReqRelease_TestVariant( ctx );
0609 RtemsSemReqRelease_Cleanup( ctx );
0610 }
0611 }
0612 }
0613 }
0614
0615