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 <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 RtemsBarrierReqWait_Pre_Id_NoObj,
0072 RtemsBarrierReqWait_Pre_Id_Manual,
0073 RtemsBarrierReqWait_Pre_Id_Auto,
0074 RtemsBarrierReqWait_Pre_Id_NA
0075 } RtemsBarrierReqWait_Pre_Id;
0076
0077 typedef enum {
0078 RtemsBarrierReqWait_Pre_Timeout_Ticks,
0079 RtemsBarrierReqWait_Pre_Timeout_Forever,
0080 RtemsBarrierReqWait_Pre_Timeout_NA
0081 } RtemsBarrierReqWait_Pre_Timeout;
0082
0083 typedef enum {
0084 RtemsBarrierReqWait_Pre_Satisfy_Never,
0085 RtemsBarrierReqWait_Pre_Satisfy_Wait,
0086 RtemsBarrierReqWait_Pre_Satisfy_Release,
0087 RtemsBarrierReqWait_Pre_Satisfy_Delete,
0088 RtemsBarrierReqWait_Pre_Satisfy_NA
0089 } RtemsBarrierReqWait_Pre_Satisfy;
0090
0091 typedef enum {
0092 RtemsBarrierReqWait_Post_Status_Ok,
0093 RtemsBarrierReqWait_Post_Status_InvId,
0094 RtemsBarrierReqWait_Post_Status_Timeout,
0095 RtemsBarrierReqWait_Post_Status_ObjDel,
0096 RtemsBarrierReqWait_Post_Status_NoReturn,
0097 RtemsBarrierReqWait_Post_Status_NA
0098 } RtemsBarrierReqWait_Post_Status;
0099
0100 typedef struct {
0101 uint8_t Skip : 1;
0102 uint8_t Pre_Id_NA : 1;
0103 uint8_t Pre_Timeout_NA : 1;
0104 uint8_t Pre_Satisfy_NA : 1;
0105 uint8_t Post_Status : 3;
0106 } RtemsBarrierReqWait_Entry;
0107
0108
0109
0110
0111 typedef struct {
0112 rtems_id main_id;
0113
0114 rtems_id high_worker_id;
0115
0116 rtems_id low_worker_id;
0117
0118 rtems_id manual_release_id;
0119
0120 rtems_id auto_release_id;
0121
0122 rtems_id id;
0123
0124 rtems_interval timeout;
0125
0126 rtems_status_code status;
0127
0128 struct {
0129
0130
0131
0132
0133 size_t pci[ 3 ];
0134
0135
0136
0137
0138 size_t pcs[ 3 ];
0139
0140
0141
0142
0143 bool in_action_loop;
0144
0145
0146
0147
0148 size_t index;
0149
0150
0151
0152
0153 RtemsBarrierReqWait_Entry entry;
0154
0155
0156
0157
0158
0159 bool skip;
0160 } Map;
0161 } RtemsBarrierReqWait_Context;
0162
0163 static RtemsBarrierReqWait_Context
0164 RtemsBarrierReqWait_Instance;
0165
0166 static const char * const RtemsBarrierReqWait_PreDesc_Id[] = {
0167 "NoObj",
0168 "Manual",
0169 "Auto",
0170 "NA"
0171 };
0172
0173 static const char * const RtemsBarrierReqWait_PreDesc_Timeout[] = {
0174 "Ticks",
0175 "Forever",
0176 "NA"
0177 };
0178
0179 static const char * const RtemsBarrierReqWait_PreDesc_Satisfy[] = {
0180 "Never",
0181 "Wait",
0182 "Release",
0183 "Delete",
0184 "NA"
0185 };
0186
0187 static const char * const * const RtemsBarrierReqWait_PreDesc[] = {
0188 RtemsBarrierReqWait_PreDesc_Id,
0189 RtemsBarrierReqWait_PreDesc_Timeout,
0190 RtemsBarrierReqWait_PreDesc_Satisfy,
0191 NULL
0192 };
0193
0194 #define NAME rtems_build_name( 'T', 'E', 'S', 'T' )
0195
0196 #define EVENT_TIMER_INACTIVE RTEMS_EVENT_0
0197
0198 #define EVENT_WAIT RTEMS_EVENT_1
0199
0200 #define EVENT_RELEASE RTEMS_EVENT_2
0201
0202 #define EVENT_DELETE RTEMS_EVENT_3
0203
0204 #define EVENT_TIMER_EXPIRE RTEMS_EVENT_4
0205
0206 typedef RtemsBarrierReqWait_Context Context;
0207
0208 static void Worker( rtems_task_argument arg )
0209 {
0210 Context *ctx;
0211
0212 ctx = (Context *) arg;
0213
0214 while ( true ) {
0215 rtems_status_code sc;
0216 rtems_event_set events;
0217
0218 events = ReceiveAnyEvents();
0219
0220 if ( ( events & EVENT_TIMER_INACTIVE ) != 0 ) {
0221 T_eq_int(
0222 T_get_thread_timer_state( ctx->main_id ),
0223 T_THREAD_TIMER_INACTIVE
0224 );
0225 }
0226
0227 if ( ( events & EVENT_WAIT ) != 0 ) {
0228 sc = rtems_barrier_wait( ctx->id, RTEMS_NO_TIMEOUT );
0229 T_rsc_success( sc );
0230 }
0231
0232 if ( ( events & EVENT_RELEASE ) != 0 ) {
0233 uint32_t released;
0234
0235 sc = rtems_barrier_release( ctx->id, &released );
0236 T_rsc_success( sc );
0237 }
0238
0239 if ( ( events & EVENT_DELETE ) != 0 ) {
0240 rtems_attribute attribute_set;
0241 uint32_t maximum_waiters;
0242 rtems_id *id;
0243 rtems_task_priority prio;
0244
0245 if ( ctx->id == ctx->manual_release_id ) {
0246 attribute_set = RTEMS_BARRIER_MANUAL_RELEASE;
0247 maximum_waiters = 0;
0248 id = &ctx->manual_release_id;
0249 } else {
0250 attribute_set = RTEMS_BARRIER_AUTOMATIC_RELEASE;
0251 maximum_waiters = 2;
0252 id = &ctx->auto_release_id;
0253 }
0254
0255 prio = SetSelfPriority( PRIO_HIGH );
0256 T_eq_u32( prio, PRIO_LOW );
0257
0258 sc = rtems_barrier_delete( ctx->id );
0259 T_rsc_success( sc );
0260
0261 sc = rtems_barrier_create( NAME, attribute_set, maximum_waiters, id );
0262 T_rsc_success( sc );
0263
0264 prio = SetSelfPriority( prio );
0265 T_eq_u32( prio, PRIO_HIGH );
0266 }
0267
0268 if ( ( events & EVENT_TIMER_EXPIRE ) != 0 ) {
0269 T_eq_int(
0270 T_get_thread_timer_state( ctx->main_id ),
0271 T_THREAD_TIMER_SCHEDULED
0272 );
0273 FinalClockTick();
0274 }
0275 }
0276 }
0277
0278 static void RtemsBarrierReqWait_Pre_Id_Prepare(
0279 RtemsBarrierReqWait_Context *ctx,
0280 RtemsBarrierReqWait_Pre_Id state
0281 )
0282 {
0283 switch ( state ) {
0284 case RtemsBarrierReqWait_Pre_Id_NoObj: {
0285
0286
0287
0288 ctx->id = 0xffffffff;
0289 break;
0290 }
0291
0292 case RtemsBarrierReqWait_Pre_Id_Manual: {
0293
0294
0295
0296
0297 ctx->id = ctx->manual_release_id;
0298 break;
0299 }
0300
0301 case RtemsBarrierReqWait_Pre_Id_Auto: {
0302
0303
0304
0305
0306 ctx->id = ctx->auto_release_id;
0307 break;
0308 }
0309
0310 case RtemsBarrierReqWait_Pre_Id_NA:
0311 break;
0312 }
0313 }
0314
0315 static void RtemsBarrierReqWait_Pre_Timeout_Prepare(
0316 RtemsBarrierReqWait_Context *ctx,
0317 RtemsBarrierReqWait_Pre_Timeout state
0318 )
0319 {
0320 switch ( state ) {
0321 case RtemsBarrierReqWait_Pre_Timeout_Ticks: {
0322
0323
0324
0325 ctx->timeout = UINT32_MAX;
0326 break;
0327 }
0328
0329 case RtemsBarrierReqWait_Pre_Timeout_Forever: {
0330
0331
0332
0333 ctx->timeout = RTEMS_NO_TIMEOUT;
0334 break;
0335 }
0336
0337 case RtemsBarrierReqWait_Pre_Timeout_NA:
0338 break;
0339 }
0340 }
0341
0342 static void RtemsBarrierReqWait_Pre_Satisfy_Prepare(
0343 RtemsBarrierReqWait_Context *ctx,
0344 RtemsBarrierReqWait_Pre_Satisfy state
0345 )
0346 {
0347 switch ( state ) {
0348 case RtemsBarrierReqWait_Pre_Satisfy_Never: {
0349
0350
0351
0352
0353 if ( ctx->timeout == RTEMS_NO_TIMEOUT ) {
0354 SendEvents( ctx->low_worker_id, EVENT_TIMER_INACTIVE | EVENT_RELEASE );
0355 } else {
0356 SendEvents( ctx->low_worker_id, EVENT_TIMER_EXPIRE );
0357 }
0358 break;
0359 }
0360
0361 case RtemsBarrierReqWait_Pre_Satisfy_Wait: {
0362
0363
0364
0365 SendEvents( ctx->high_worker_id, EVENT_WAIT );
0366 break;
0367 }
0368
0369 case RtemsBarrierReqWait_Pre_Satisfy_Release: {
0370
0371
0372
0373
0374 SendEvents( ctx->low_worker_id, EVENT_RELEASE );
0375 break;
0376 }
0377
0378 case RtemsBarrierReqWait_Pre_Satisfy_Delete: {
0379
0380
0381
0382
0383 SendEvents( ctx->low_worker_id, EVENT_DELETE );
0384 break;
0385 }
0386
0387 case RtemsBarrierReqWait_Pre_Satisfy_NA:
0388 break;
0389 }
0390 }
0391
0392 static void RtemsBarrierReqWait_Post_Status_Check(
0393 RtemsBarrierReqWait_Context *ctx,
0394 RtemsBarrierReqWait_Post_Status state
0395 )
0396 {
0397 switch ( state ) {
0398 case RtemsBarrierReqWait_Post_Status_Ok: {
0399
0400
0401
0402 T_rsc_success( ctx->status );
0403 break;
0404 }
0405
0406 case RtemsBarrierReqWait_Post_Status_InvId: {
0407
0408
0409
0410 T_rsc( ctx->status, RTEMS_INVALID_ID );
0411 break;
0412 }
0413
0414 case RtemsBarrierReqWait_Post_Status_Timeout: {
0415
0416
0417
0418 T_rsc( ctx->status, RTEMS_TIMEOUT );
0419 break;
0420 }
0421
0422 case RtemsBarrierReqWait_Post_Status_ObjDel: {
0423
0424
0425
0426
0427 T_rsc( ctx->status, RTEMS_OBJECT_WAS_DELETED );
0428 break;
0429 }
0430
0431 case RtemsBarrierReqWait_Post_Status_NoReturn: {
0432
0433
0434
0435 T_rsc_success( ctx->status );
0436 break;
0437 }
0438
0439 case RtemsBarrierReqWait_Post_Status_NA:
0440 break;
0441 }
0442 }
0443
0444 static void RtemsBarrierReqWait_Setup( RtemsBarrierReqWait_Context *ctx )
0445 {
0446 rtems_status_code sc;
0447
0448 memset( ctx, 0, sizeof( *ctx ) );
0449 ctx->main_id = rtems_task_self();
0450 SetSelfPriority( PRIO_NORMAL );
0451 ctx->high_worker_id = CreateTask( "WRKH", PRIO_HIGH );
0452 StartTask( ctx->high_worker_id, Worker, ctx );
0453 ctx->low_worker_id = CreateTask( "WRKL", PRIO_LOW );
0454 StartTask( ctx->low_worker_id, Worker, ctx );
0455
0456 sc = rtems_barrier_create(
0457 NAME,
0458 RTEMS_BARRIER_MANUAL_RELEASE,
0459 0,
0460 &ctx->manual_release_id
0461 );
0462 T_assert_rsc_success( sc );
0463
0464 sc = rtems_barrier_create(
0465 NAME,
0466 RTEMS_BARRIER_AUTOMATIC_RELEASE,
0467 2,
0468 &ctx->auto_release_id
0469 );
0470 T_assert_rsc_success( sc );
0471 }
0472
0473 static void RtemsBarrierReqWait_Setup_Wrap( void *arg )
0474 {
0475 RtemsBarrierReqWait_Context *ctx;
0476
0477 ctx = arg;
0478 ctx->Map.in_action_loop = false;
0479 RtemsBarrierReqWait_Setup( ctx );
0480 }
0481
0482 static void RtemsBarrierReqWait_Teardown( RtemsBarrierReqWait_Context *ctx )
0483 {
0484 rtems_status_code sc;
0485
0486 DeleteTask( ctx->high_worker_id );
0487 DeleteTask( ctx->low_worker_id );
0488
0489 if ( ctx->manual_release_id != 0 ) {
0490 sc = rtems_barrier_delete( ctx->manual_release_id );
0491 T_rsc_success( sc );
0492 }
0493
0494 if ( ctx->auto_release_id != 0 ) {
0495 sc = rtems_barrier_delete( ctx->auto_release_id );
0496 T_rsc_success( sc );
0497 }
0498
0499 RestoreRunnerPriority();
0500 }
0501
0502 static void RtemsBarrierReqWait_Teardown_Wrap( void *arg )
0503 {
0504 RtemsBarrierReqWait_Context *ctx;
0505
0506 ctx = arg;
0507 ctx->Map.in_action_loop = false;
0508 RtemsBarrierReqWait_Teardown( ctx );
0509 }
0510
0511 static void RtemsBarrierReqWait_Action( RtemsBarrierReqWait_Context *ctx )
0512 {
0513 ctx->status = rtems_barrier_wait( ctx->id, ctx->timeout );
0514 }
0515
0516 static const RtemsBarrierReqWait_Entry
0517 RtemsBarrierReqWait_Entries[] = {
0518 { 0, 0, 1, 1, RtemsBarrierReqWait_Post_Status_InvId },
0519 { 0, 0, 0, 0, RtemsBarrierReqWait_Post_Status_Ok },
0520 { 0, 0, 0, 0, RtemsBarrierReqWait_Post_Status_ObjDel },
0521 { 0, 0, 0, 0, RtemsBarrierReqWait_Post_Status_Timeout },
0522 { 1, 0, 0, 0, RtemsBarrierReqWait_Post_Status_NA },
0523 { 0, 0, 0, 0, RtemsBarrierReqWait_Post_Status_NoReturn }
0524 };
0525
0526 static const uint8_t
0527 RtemsBarrierReqWait_Map[] = {
0528 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 1, 2, 5, 4, 1, 2, 3, 1, 1, 2, 5, 1, 1, 2
0529 };
0530
0531 static size_t RtemsBarrierReqWait_Scope( void *arg, char *buf, size_t n )
0532 {
0533 RtemsBarrierReqWait_Context *ctx;
0534
0535 ctx = arg;
0536
0537 if ( ctx->Map.in_action_loop ) {
0538 return T_get_scope( RtemsBarrierReqWait_PreDesc, buf, n, ctx->Map.pcs );
0539 }
0540
0541 return 0;
0542 }
0543
0544 static T_fixture RtemsBarrierReqWait_Fixture = {
0545 .setup = RtemsBarrierReqWait_Setup_Wrap,
0546 .stop = NULL,
0547 .teardown = RtemsBarrierReqWait_Teardown_Wrap,
0548 .scope = RtemsBarrierReqWait_Scope,
0549 .initial_context = &RtemsBarrierReqWait_Instance
0550 };
0551
0552 static inline RtemsBarrierReqWait_Entry RtemsBarrierReqWait_PopEntry(
0553 RtemsBarrierReqWait_Context *ctx
0554 )
0555 {
0556 size_t index;
0557
0558 index = ctx->Map.index;
0559 ctx->Map.index = index + 1;
0560 return RtemsBarrierReqWait_Entries[
0561 RtemsBarrierReqWait_Map[ index ]
0562 ];
0563 }
0564
0565 static void RtemsBarrierReqWait_SetPreConditionStates(
0566 RtemsBarrierReqWait_Context *ctx
0567 )
0568 {
0569 ctx->Map.pcs[ 0 ] = ctx->Map.pci[ 0 ];
0570
0571 if ( ctx->Map.entry.Pre_Timeout_NA ) {
0572 ctx->Map.pcs[ 1 ] = RtemsBarrierReqWait_Pre_Timeout_NA;
0573 } else {
0574 ctx->Map.pcs[ 1 ] = ctx->Map.pci[ 1 ];
0575 }
0576
0577 if ( ctx->Map.entry.Pre_Satisfy_NA ) {
0578 ctx->Map.pcs[ 2 ] = RtemsBarrierReqWait_Pre_Satisfy_NA;
0579 } else {
0580 ctx->Map.pcs[ 2 ] = ctx->Map.pci[ 2 ];
0581 }
0582 }
0583
0584 static void RtemsBarrierReqWait_TestVariant( RtemsBarrierReqWait_Context *ctx )
0585 {
0586 RtemsBarrierReqWait_Pre_Id_Prepare( ctx, ctx->Map.pcs[ 0 ] );
0587 RtemsBarrierReqWait_Pre_Timeout_Prepare( ctx, ctx->Map.pcs[ 1 ] );
0588 RtemsBarrierReqWait_Pre_Satisfy_Prepare( ctx, ctx->Map.pcs[ 2 ] );
0589 RtemsBarrierReqWait_Action( ctx );
0590 RtemsBarrierReqWait_Post_Status_Check( ctx, ctx->Map.entry.Post_Status );
0591 }
0592
0593
0594
0595
0596 T_TEST_CASE_FIXTURE( RtemsBarrierReqWait, &RtemsBarrierReqWait_Fixture )
0597 {
0598 RtemsBarrierReqWait_Context *ctx;
0599
0600 ctx = T_fixture_context();
0601 ctx->Map.in_action_loop = true;
0602 ctx->Map.index = 0;
0603
0604 for (
0605 ctx->Map.pci[ 0 ] = RtemsBarrierReqWait_Pre_Id_NoObj;
0606 ctx->Map.pci[ 0 ] < RtemsBarrierReqWait_Pre_Id_NA;
0607 ++ctx->Map.pci[ 0 ]
0608 ) {
0609 for (
0610 ctx->Map.pci[ 1 ] = RtemsBarrierReqWait_Pre_Timeout_Ticks;
0611 ctx->Map.pci[ 1 ] < RtemsBarrierReqWait_Pre_Timeout_NA;
0612 ++ctx->Map.pci[ 1 ]
0613 ) {
0614 for (
0615 ctx->Map.pci[ 2 ] = RtemsBarrierReqWait_Pre_Satisfy_Never;
0616 ctx->Map.pci[ 2 ] < RtemsBarrierReqWait_Pre_Satisfy_NA;
0617 ++ctx->Map.pci[ 2 ]
0618 ) {
0619 ctx->Map.entry = RtemsBarrierReqWait_PopEntry( ctx );
0620
0621 if ( ctx->Map.entry.Skip ) {
0622 continue;
0623 }
0624
0625 RtemsBarrierReqWait_SetPreConditionStates( ctx );
0626 RtemsBarrierReqWait_TestVariant( ctx );
0627 }
0628 }
0629 }
0630 }
0631
0632