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 "tx-support.h"
0059
0060 #include <rtems/test.h>
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070 typedef enum {
0071 RtemsSemReqDelete_Pre_Id_NoObj,
0072 RtemsSemReqDelete_Pre_Id_Counting,
0073 RtemsSemReqDelete_Pre_Id_Simple,
0074 RtemsSemReqDelete_Pre_Id_Binary,
0075 RtemsSemReqDelete_Pre_Id_PrioCeiling,
0076 RtemsSemReqDelete_Pre_Id_PrioInherit,
0077 RtemsSemReqDelete_Pre_Id_MrsP,
0078 RtemsSemReqDelete_Pre_Id_NA
0079 } RtemsSemReqDelete_Pre_Id;
0080
0081 typedef enum {
0082 RtemsSemReqDelete_Pre_Discipline_FIFO,
0083 RtemsSemReqDelete_Pre_Discipline_Priority,
0084 RtemsSemReqDelete_Pre_Discipline_NA
0085 } RtemsSemReqDelete_Pre_Discipline;
0086
0087 typedef enum {
0088 RtemsSemReqDelete_Pre_State_GtZeroOrNoOwner,
0089 RtemsSemReqDelete_Pre_State_Zero,
0090 RtemsSemReqDelete_Pre_State_Blocked,
0091 RtemsSemReqDelete_Pre_State_NA
0092 } RtemsSemReqDelete_Pre_State;
0093
0094 typedef enum {
0095 RtemsSemReqDelete_Post_Status_Ok,
0096 RtemsSemReqDelete_Post_Status_InvId,
0097 RtemsSemReqDelete_Post_Status_InUse,
0098 RtemsSemReqDelete_Post_Status_NA
0099 } RtemsSemReqDelete_Post_Status;
0100
0101 typedef enum {
0102 RtemsSemReqDelete_Post_Name_Valid,
0103 RtemsSemReqDelete_Post_Name_Invalid,
0104 RtemsSemReqDelete_Post_Name_NA
0105 } RtemsSemReqDelete_Post_Name;
0106
0107 typedef enum {
0108 RtemsSemReqDelete_Post_Flush_FIFO,
0109 RtemsSemReqDelete_Post_Flush_Priority,
0110 RtemsSemReqDelete_Post_Flush_No,
0111 RtemsSemReqDelete_Post_Flush_NA
0112 } RtemsSemReqDelete_Post_Flush;
0113
0114 typedef struct {
0115 uint16_t Skip : 1;
0116 uint16_t Pre_Id_NA : 1;
0117 uint16_t Pre_Discipline_NA : 1;
0118 uint16_t Pre_State_NA : 1;
0119 uint16_t Post_Status : 2;
0120 uint16_t Post_Name : 2;
0121 uint16_t Post_Flush : 2;
0122 } RtemsSemReqDelete_Entry;
0123
0124
0125
0126
0127 typedef struct {
0128
0129
0130
0131 rtems_id worker_id[ 2 ];
0132
0133
0134
0135
0136 uint32_t counter;
0137
0138
0139
0140
0141
0142 uint32_t worker_counter[ 2 ];
0143
0144
0145
0146
0147 rtems_status_code obtain_status;
0148
0149
0150
0151
0152 uint32_t count;
0153
0154
0155
0156
0157 rtems_attribute attribute_set;
0158
0159
0160
0161
0162 rtems_id semaphore_id;
0163
0164
0165
0166
0167
0168 bool valid_id;
0169
0170
0171
0172
0173
0174 bool blocked;
0175
0176
0177
0178
0179
0180 rtems_id id;
0181
0182
0183
0184
0185 rtems_status_code delete_status;
0186
0187 struct {
0188
0189
0190
0191 size_t pcs[ 3 ];
0192
0193
0194
0195
0196 bool in_action_loop;
0197
0198
0199
0200
0201 size_t index;
0202
0203
0204
0205
0206 RtemsSemReqDelete_Entry entry;
0207
0208
0209
0210
0211
0212 bool skip;
0213 } Map;
0214 } RtemsSemReqDelete_Context;
0215
0216 static RtemsSemReqDelete_Context
0217 RtemsSemReqDelete_Instance;
0218
0219 static const char * const RtemsSemReqDelete_PreDesc_Id[] = {
0220 "NoObj",
0221 "Counting",
0222 "Simple",
0223 "Binary",
0224 "PrioCeiling",
0225 "PrioInherit",
0226 "MrsP",
0227 "NA"
0228 };
0229
0230 static const char * const RtemsSemReqDelete_PreDesc_Discipline[] = {
0231 "FIFO",
0232 "Priority",
0233 "NA"
0234 };
0235
0236 static const char * const RtemsSemReqDelete_PreDesc_State[] = {
0237 "GtZeroOrNoOwner",
0238 "Zero",
0239 "Blocked",
0240 "NA"
0241 };
0242
0243 static const char * const * const RtemsSemReqDelete_PreDesc[] = {
0244 RtemsSemReqDelete_PreDesc_Id,
0245 RtemsSemReqDelete_PreDesc_Discipline,
0246 RtemsSemReqDelete_PreDesc_State,
0247 NULL
0248 };
0249
0250 #define NAME rtems_build_name( 'T', 'E', 'S', 'T' )
0251
0252 #define EVENT_OBTAIN RTEMS_EVENT_0
0253
0254 typedef RtemsSemReqDelete_Context Context;
0255
0256 static void WakeUp( Context *ctx, size_t index )
0257 {
0258 SendEvents( ctx->worker_id[ index ], RTEMS_EVENT_0 );
0259 }
0260
0261 static void Worker( rtems_task_argument arg, size_t index )
0262 {
0263 Context *ctx;
0264
0265 ctx = (Context *) arg;
0266
0267
0268
0269
0270
0271 SetMode( RTEMS_NO_PREEMPT, RTEMS_PREEMPT_MASK );
0272
0273 while ( true ) {
0274 rtems_status_code sc;
0275 rtems_event_set events;
0276 uint32_t counter;
0277
0278 events = ReceiveAnyEvents();
0279 T_eq_u32( events, RTEMS_EVENT_0 );
0280
0281 sc = rtems_semaphore_obtain(
0282 ctx->semaphore_id,
0283 RTEMS_WAIT,
0284 RTEMS_NO_TIMEOUT
0285 );
0286 T_rsc( sc, ctx->obtain_status );
0287
0288 counter = ctx->counter;
0289 ++counter;
0290 ctx->counter = counter;
0291 ctx->worker_counter[ index ] = counter;
0292
0293 if ( sc == RTEMS_SUCCESSFUL ) {
0294 sc = rtems_semaphore_release( ctx->semaphore_id );
0295 T_rsc_success( sc );
0296 }
0297 }
0298 }
0299
0300 static void WorkerZero( rtems_task_argument arg )
0301 {
0302 Worker( arg, 0 );
0303 }
0304
0305 static void WorkerOne( rtems_task_argument arg )
0306 {
0307 Worker( arg, 1 );
0308 }
0309
0310 static void RtemsSemReqDelete_Pre_Id_Prepare(
0311 RtemsSemReqDelete_Context *ctx,
0312 RtemsSemReqDelete_Pre_Id state
0313 )
0314 {
0315 switch ( state ) {
0316 case RtemsSemReqDelete_Pre_Id_NoObj: {
0317
0318
0319
0320 ctx->valid_id = false;
0321 break;
0322 }
0323
0324 case RtemsSemReqDelete_Pre_Id_Counting: {
0325
0326
0327
0328 ctx->attribute_set |= RTEMS_COUNTING_SEMAPHORE;
0329 ctx->obtain_status = RTEMS_OBJECT_WAS_DELETED;
0330 break;
0331 }
0332
0333 case RtemsSemReqDelete_Pre_Id_Simple: {
0334
0335
0336
0337
0338 ctx->attribute_set |= RTEMS_SIMPLE_BINARY_SEMAPHORE;
0339 ctx->obtain_status = RTEMS_OBJECT_WAS_DELETED;
0340 break;
0341 }
0342
0343 case RtemsSemReqDelete_Pre_Id_Binary: {
0344
0345
0346
0347 ctx->attribute_set |= RTEMS_BINARY_SEMAPHORE;
0348 break;
0349 }
0350
0351 case RtemsSemReqDelete_Pre_Id_PrioCeiling: {
0352
0353
0354
0355
0356 ctx->attribute_set |= RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY_CEILING;
0357 break;
0358 }
0359
0360 case RtemsSemReqDelete_Pre_Id_PrioInherit: {
0361
0362
0363
0364
0365 ctx->attribute_set |= RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY;
0366 break;
0367 }
0368
0369 case RtemsSemReqDelete_Pre_Id_MrsP: {
0370
0371
0372
0373 ctx->attribute_set |= RTEMS_BINARY_SEMAPHORE |
0374 RTEMS_MULTIPROCESSOR_RESOURCE_SHARING;
0375 break;
0376 }
0377
0378 case RtemsSemReqDelete_Pre_Id_NA:
0379 break;
0380 }
0381 }
0382
0383 static void RtemsSemReqDelete_Pre_Discipline_Prepare(
0384 RtemsSemReqDelete_Context *ctx,
0385 RtemsSemReqDelete_Pre_Discipline state
0386 )
0387 {
0388 switch ( state ) {
0389 case RtemsSemReqDelete_Pre_Discipline_FIFO: {
0390
0391
0392
0393 ctx->attribute_set |= RTEMS_FIFO;
0394 break;
0395 }
0396
0397 case RtemsSemReqDelete_Pre_Discipline_Priority: {
0398
0399
0400
0401 ctx->attribute_set |= RTEMS_PRIORITY;
0402 break;
0403 }
0404
0405 case RtemsSemReqDelete_Pre_Discipline_NA:
0406 break;
0407 }
0408 }
0409
0410 static void RtemsSemReqDelete_Pre_State_Prepare(
0411 RtemsSemReqDelete_Context *ctx,
0412 RtemsSemReqDelete_Pre_State state
0413 )
0414 {
0415 switch ( state ) {
0416 case RtemsSemReqDelete_Pre_State_GtZeroOrNoOwner: {
0417
0418
0419
0420 ctx->blocked = false;
0421 ctx->count = 1;
0422 break;
0423 }
0424
0425 case RtemsSemReqDelete_Pre_State_Zero: {
0426
0427
0428
0429 ctx->blocked = false;
0430 ctx->count = 0;
0431 break;
0432 }
0433
0434 case RtemsSemReqDelete_Pre_State_Blocked: {
0435
0436
0437
0438 ctx->blocked = true;
0439 ctx->count = 0;
0440 break;
0441 }
0442
0443 case RtemsSemReqDelete_Pre_State_NA:
0444 break;
0445 }
0446 }
0447
0448 static void RtemsSemReqDelete_Post_Status_Check(
0449 RtemsSemReqDelete_Context *ctx,
0450 RtemsSemReqDelete_Post_Status state
0451 )
0452 {
0453 switch ( state ) {
0454 case RtemsSemReqDelete_Post_Status_Ok: {
0455
0456
0457
0458
0459 ctx->semaphore_id = 0;
0460 T_rsc_success( ctx->delete_status );
0461 break;
0462 }
0463
0464 case RtemsSemReqDelete_Post_Status_InvId: {
0465
0466
0467
0468
0469 T_rsc( ctx->delete_status, RTEMS_INVALID_ID );
0470 break;
0471 }
0472
0473 case RtemsSemReqDelete_Post_Status_InUse: {
0474
0475
0476
0477
0478 T_rsc( ctx->delete_status, RTEMS_RESOURCE_IN_USE );
0479 break;
0480 }
0481
0482 case RtemsSemReqDelete_Post_Status_NA:
0483 break;
0484 }
0485 }
0486
0487 static void RtemsSemReqDelete_Post_Name_Check(
0488 RtemsSemReqDelete_Context *ctx,
0489 RtemsSemReqDelete_Post_Name state
0490 )
0491 {
0492 rtems_status_code sc;
0493 rtems_id id;
0494
0495 switch ( state ) {
0496 case RtemsSemReqDelete_Post_Name_Valid: {
0497
0498
0499
0500 id = 0;
0501 sc = rtems_semaphore_ident( NAME, RTEMS_SEARCH_LOCAL_NODE, &id );
0502 T_rsc_success( sc );
0503 T_eq_u32( id, ctx->semaphore_id );
0504 break;
0505 }
0506
0507 case RtemsSemReqDelete_Post_Name_Invalid: {
0508
0509
0510
0511 sc = rtems_semaphore_ident( NAME, RTEMS_SEARCH_LOCAL_NODE, &id );
0512 T_rsc( sc, RTEMS_INVALID_NAME );
0513 break;
0514 }
0515
0516 case RtemsSemReqDelete_Post_Name_NA:
0517 break;
0518 }
0519 }
0520
0521 static void RtemsSemReqDelete_Post_Flush_Check(
0522 RtemsSemReqDelete_Context *ctx,
0523 RtemsSemReqDelete_Post_Flush state
0524 )
0525 {
0526 switch ( state ) {
0527 case RtemsSemReqDelete_Post_Flush_FIFO: {
0528
0529
0530
0531 T_eq_u32( ctx->worker_counter[ 0 ], 1 );
0532 T_eq_u32( ctx->worker_counter[ 1 ], 2 );
0533 break;
0534 }
0535
0536 case RtemsSemReqDelete_Post_Flush_Priority: {
0537
0538
0539
0540 T_eq_u32( ctx->worker_counter[ 0 ], 2 );
0541 T_eq_u32( ctx->worker_counter[ 1 ], 1 );
0542 break;
0543 }
0544
0545 case RtemsSemReqDelete_Post_Flush_No: {
0546
0547
0548
0549 T_eq_u32( ctx->worker_counter[ 0 ], 0 );
0550 T_eq_u32( ctx->worker_counter[ 1 ], 0 );
0551 break;
0552 }
0553
0554 case RtemsSemReqDelete_Post_Flush_NA:
0555 break;
0556 }
0557 }
0558
0559 static void RtemsSemReqDelete_Setup( RtemsSemReqDelete_Context *ctx )
0560 {
0561 memset( ctx, 0, sizeof( *ctx ) );
0562 SetSelfPriority( PRIO_NORMAL );
0563 ctx->worker_id[ 0 ] = CreateTask( "WRK0", PRIO_HIGH );
0564 StartTask( ctx->worker_id[ 0 ], WorkerZero, ctx );
0565 ctx->worker_id[ 1 ] = CreateTask( "WRK1", PRIO_VERY_HIGH );
0566 StartTask( ctx->worker_id[ 1 ], WorkerOne, ctx );
0567 }
0568
0569 static void RtemsSemReqDelete_Setup_Wrap( void *arg )
0570 {
0571 RtemsSemReqDelete_Context *ctx;
0572
0573 ctx = arg;
0574 ctx->Map.in_action_loop = false;
0575 RtemsSemReqDelete_Setup( ctx );
0576 }
0577
0578 static void RtemsSemReqDelete_Teardown( RtemsSemReqDelete_Context *ctx )
0579 {
0580 size_t i;
0581
0582 for ( i = 0; i < RTEMS_ARRAY_SIZE( ctx->worker_id ); ++i ) {
0583 DeleteTask( ctx->worker_id[ i ] );
0584 }
0585
0586 RestoreRunnerPriority();
0587 }
0588
0589 static void RtemsSemReqDelete_Teardown_Wrap( void *arg )
0590 {
0591 RtemsSemReqDelete_Context *ctx;
0592
0593 ctx = arg;
0594 ctx->Map.in_action_loop = false;
0595 RtemsSemReqDelete_Teardown( ctx );
0596 }
0597
0598 static void RtemsSemReqDelete_Prepare( RtemsSemReqDelete_Context *ctx )
0599 {
0600 ctx->counter = 0;
0601 ctx->worker_counter[ 0 ] = 0;
0602 ctx->worker_counter[ 1 ] = 0;
0603 ctx->attribute_set = RTEMS_DEFAULT_ATTRIBUTES;
0604 ctx->valid_id = true;
0605 ctx->obtain_status = RTEMS_SUCCESSFUL;
0606 }
0607
0608 static void RtemsSemReqDelete_Action( RtemsSemReqDelete_Context *ctx )
0609 {
0610 rtems_status_code sc;
0611
0612 sc = rtems_semaphore_create(
0613 NAME,
0614 ctx->count,
0615 ctx->attribute_set,
0616 PRIO_ULTRA_HIGH,
0617 &ctx->semaphore_id
0618 );
0619 T_rsc_success( sc );
0620
0621 if ( ctx->blocked ) {
0622 WakeUp( ctx, 0 );
0623 WakeUp( ctx, 1 );
0624 }
0625
0626 if ( ctx->valid_id ) {
0627 ctx->id = ctx->semaphore_id;
0628 } else {
0629 ctx->id = 0;
0630 }
0631
0632 ctx->delete_status = rtems_semaphore_delete( ctx->id );
0633 }
0634
0635 static void RtemsSemReqDelete_Cleanup( RtemsSemReqDelete_Context *ctx )
0636 {
0637 if ( ctx->semaphore_id != 0 ) {
0638 rtems_status_code sc;
0639
0640 if ( ctx->count == 0 ) {
0641 sc = rtems_semaphore_release( ctx->semaphore_id );
0642 T_rsc_success( sc );
0643 }
0644
0645 sc = rtems_semaphore_delete( ctx->semaphore_id );
0646 T_rsc_success( sc );
0647
0648 ctx->semaphore_id = 0;
0649 }
0650 }
0651
0652 static const RtemsSemReqDelete_Entry
0653 RtemsSemReqDelete_Entries[] = {
0654 { 0, 0, 0, 0, RtemsSemReqDelete_Post_Status_Ok,
0655 RtemsSemReqDelete_Post_Name_Invalid, RtemsSemReqDelete_Post_Flush_No },
0656 { 0, 0, 0, 0, RtemsSemReqDelete_Post_Status_InUse,
0657 RtemsSemReqDelete_Post_Name_Valid, RtemsSemReqDelete_Post_Flush_No },
0658 { 1, 0, 0, 0, RtemsSemReqDelete_Post_Status_NA,
0659 RtemsSemReqDelete_Post_Name_NA, RtemsSemReqDelete_Post_Flush_NA },
0660 { 0, 0, 0, 0, RtemsSemReqDelete_Post_Status_InvId,
0661 RtemsSemReqDelete_Post_Name_Valid, RtemsSemReqDelete_Post_Flush_No },
0662 { 0, 0, 0, 0, RtemsSemReqDelete_Post_Status_Ok,
0663 RtemsSemReqDelete_Post_Name_Invalid, RtemsSemReqDelete_Post_Flush_FIFO },
0664 { 0, 0, 0, 0, RtemsSemReqDelete_Post_Status_Ok,
0665 RtemsSemReqDelete_Post_Name_Invalid, RtemsSemReqDelete_Post_Flush_Priority }
0666 };
0667
0668 static const uint8_t
0669 RtemsSemReqDelete_Map[] = {
0670 3, 3, 3, 3, 3, 3, 0, 0, 4, 0, 0, 5, 0, 0, 4, 0, 0, 5, 0, 1, 1, 0, 1, 1, 2, 2,
0671 2, 0, 1, 1, 2, 2, 2, 0, 1, 1, 2, 2, 2, 0, 1, 1
0672 };
0673
0674 static size_t RtemsSemReqDelete_Scope( void *arg, char *buf, size_t n )
0675 {
0676 RtemsSemReqDelete_Context *ctx;
0677
0678 ctx = arg;
0679
0680 if ( ctx->Map.in_action_loop ) {
0681 return T_get_scope( RtemsSemReqDelete_PreDesc, buf, n, ctx->Map.pcs );
0682 }
0683
0684 return 0;
0685 }
0686
0687 static T_fixture RtemsSemReqDelete_Fixture = {
0688 .setup = RtemsSemReqDelete_Setup_Wrap,
0689 .stop = NULL,
0690 .teardown = RtemsSemReqDelete_Teardown_Wrap,
0691 .scope = RtemsSemReqDelete_Scope,
0692 .initial_context = &RtemsSemReqDelete_Instance
0693 };
0694
0695 static inline RtemsSemReqDelete_Entry RtemsSemReqDelete_PopEntry(
0696 RtemsSemReqDelete_Context *ctx
0697 )
0698 {
0699 size_t index;
0700
0701 index = ctx->Map.index;
0702 ctx->Map.index = index + 1;
0703 return RtemsSemReqDelete_Entries[
0704 RtemsSemReqDelete_Map[ index ]
0705 ];
0706 }
0707
0708 static void RtemsSemReqDelete_TestVariant( RtemsSemReqDelete_Context *ctx )
0709 {
0710 RtemsSemReqDelete_Pre_Id_Prepare( ctx, ctx->Map.pcs[ 0 ] );
0711 RtemsSemReqDelete_Pre_Discipline_Prepare( ctx, ctx->Map.pcs[ 1 ] );
0712 RtemsSemReqDelete_Pre_State_Prepare( ctx, ctx->Map.pcs[ 2 ] );
0713 RtemsSemReqDelete_Action( ctx );
0714 RtemsSemReqDelete_Post_Status_Check( ctx, ctx->Map.entry.Post_Status );
0715 RtemsSemReqDelete_Post_Name_Check( ctx, ctx->Map.entry.Post_Name );
0716 RtemsSemReqDelete_Post_Flush_Check( ctx, ctx->Map.entry.Post_Flush );
0717 }
0718
0719
0720
0721
0722 T_TEST_CASE_FIXTURE( RtemsSemReqDelete, &RtemsSemReqDelete_Fixture )
0723 {
0724 RtemsSemReqDelete_Context *ctx;
0725
0726 ctx = T_fixture_context();
0727 ctx->Map.in_action_loop = true;
0728 ctx->Map.index = 0;
0729
0730 for (
0731 ctx->Map.pcs[ 0 ] = RtemsSemReqDelete_Pre_Id_NoObj;
0732 ctx->Map.pcs[ 0 ] < RtemsSemReqDelete_Pre_Id_NA;
0733 ++ctx->Map.pcs[ 0 ]
0734 ) {
0735 for (
0736 ctx->Map.pcs[ 1 ] = RtemsSemReqDelete_Pre_Discipline_FIFO;
0737 ctx->Map.pcs[ 1 ] < RtemsSemReqDelete_Pre_Discipline_NA;
0738 ++ctx->Map.pcs[ 1 ]
0739 ) {
0740 for (
0741 ctx->Map.pcs[ 2 ] = RtemsSemReqDelete_Pre_State_GtZeroOrNoOwner;
0742 ctx->Map.pcs[ 2 ] < RtemsSemReqDelete_Pre_State_NA;
0743 ++ctx->Map.pcs[ 2 ]
0744 ) {
0745 ctx->Map.entry = RtemsSemReqDelete_PopEntry( ctx );
0746
0747 if ( ctx->Map.entry.Skip ) {
0748 continue;
0749 }
0750
0751 RtemsSemReqDelete_Prepare( ctx );
0752 RtemsSemReqDelete_TestVariant( ctx );
0753 RtemsSemReqDelete_Cleanup( ctx );
0754 }
0755 }
0756 }
0757 }
0758
0759