File indexing completed on 2025-05-11 08:24:53
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 "tr-tq-flush-priority-inherit.h"
0056 #include "tx-support.h"
0057
0058 #include <rtems/test.h>
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069 typedef struct {
0070 uint8_t Skip : 1;
0071 uint8_t Pre_Priority_NA : 1;
0072 uint8_t Pre_Queue_NA : 1;
0073 uint8_t Post_Extract : 2;
0074 uint8_t Post_PriorityUpdate : 2;
0075 } ScoreTqReqFlushPriorityInherit_Entry;
0076
0077
0078
0079
0080 typedef struct {
0081
0082
0083
0084 CallWithinISRRequest request;
0085
0086
0087
0088
0089
0090
0091 bool minimum;
0092
0093
0094
0095
0096
0097 TQContext *tq_ctx;
0098
0099 struct {
0100
0101
0102
0103
0104 size_t pci[ 2 ];
0105
0106
0107
0108
0109 size_t pcs[ 2 ];
0110
0111
0112
0113
0114 bool in_action_loop;
0115
0116
0117
0118
0119 size_t index;
0120
0121
0122
0123
0124 ScoreTqReqFlushPriorityInherit_Entry entry;
0125
0126
0127
0128
0129
0130 bool skip;
0131 } Map;
0132 } ScoreTqReqFlushPriorityInherit_Context;
0133
0134 static ScoreTqReqFlushPriorityInherit_Context
0135 ScoreTqReqFlushPriorityInherit_Instance;
0136
0137 static const char * const ScoreTqReqFlushPriorityInherit_PreDesc_Priority[] = {
0138 "Minimum",
0139 "NotMinimum",
0140 "NA"
0141 };
0142
0143 static const char * const ScoreTqReqFlushPriorityInherit_PreDesc_Queue[] = {
0144 "Empty",
0145 "NonEmpty",
0146 "NA"
0147 };
0148
0149 static const char * const * const ScoreTqReqFlushPriorityInherit_PreDesc[] = {
0150 ScoreTqReqFlushPriorityInherit_PreDesc_Priority,
0151 ScoreTqReqFlushPriorityInherit_PreDesc_Queue,
0152 NULL
0153 };
0154
0155 typedef ScoreTqReqFlushPriorityInherit_Context Context;
0156
0157 static const T_scheduler_event *GetUnblock( Context *ctx, size_t *index )
0158 {
0159 return TQGetNextUnblock( ctx->tq_ctx, index );
0160 }
0161
0162 static const T_scheduler_event *GetPriorityUpdate( Context *ctx, size_t *index )
0163 {
0164 return T_scheduler_next(
0165 &ctx->tq_ctx->scheduler_log.header,
0166 T_SCHEDULER_UPDATE_PRIORITY,
0167 index
0168 );
0169 }
0170
0171 static const rtems_tcb *GetTCB( Context *ctx, TQWorkerKind worker )
0172 {
0173 return ctx->tq_ctx->worker_tcb[ worker ];
0174 }
0175
0176 static void Flush( void *arg )
0177 {
0178 Context *ctx;
0179
0180 ctx = arg;
0181 TQSchedulerRecordStart( ctx->tq_ctx );
0182 TQFlush( ctx->tq_ctx, true );
0183 }
0184
0185 static void SchedulerEvent(
0186 void *arg,
0187 const T_scheduler_event *event,
0188 T_scheduler_when when
0189 )
0190 {
0191 Context *ctx;
0192
0193 ctx = arg;
0194
0195 if (
0196 when == T_SCHEDULER_BEFORE &&
0197 event->operation == T_SCHEDULER_BLOCK
0198 ) {
0199 ctx->request.handler = Flush;
0200 ctx->request.arg = ctx;
0201 CallWithinISRSubmit( &ctx->request );
0202 T_scheduler_set_event_handler( NULL, NULL );
0203 }
0204 }
0205
0206 static void ScoreTqReqFlushPriorityInherit_Pre_Priority_Prepare(
0207 ScoreTqReqFlushPriorityInherit_Context *ctx,
0208 ScoreTqReqFlushPriorityInherit_Pre_Priority state
0209 )
0210 {
0211 switch ( state ) {
0212 case ScoreTqReqFlushPriorityInherit_Pre_Priority_Minimum: {
0213
0214
0215
0216
0217 ctx->minimum = true;
0218 break;
0219 }
0220
0221 case ScoreTqReqFlushPriorityInherit_Pre_Priority_NotMinimum: {
0222
0223
0224
0225
0226 ctx->minimum = false;
0227 break;
0228 }
0229
0230 case ScoreTqReqFlushPriorityInherit_Pre_Priority_NA:
0231 break;
0232 }
0233 }
0234
0235 static void ScoreTqReqFlushPriorityInherit_Pre_Queue_Prepare(
0236 ScoreTqReqFlushPriorityInherit_Context *ctx,
0237 ScoreTqReqFlushPriorityInherit_Pre_Queue state
0238 )
0239 {
0240 switch ( state ) {
0241 case ScoreTqReqFlushPriorityInherit_Pre_Queue_Empty: {
0242
0243
0244
0245 ctx->tq_ctx->how_many = 0;
0246 break;
0247 }
0248
0249 case ScoreTqReqFlushPriorityInherit_Pre_Queue_NonEmpty: {
0250
0251
0252
0253 ctx->tq_ctx->how_many = 3;
0254 break;
0255 }
0256
0257 case ScoreTqReqFlushPriorityInherit_Pre_Queue_NA:
0258 break;
0259 }
0260 }
0261
0262 static void ScoreTqReqFlushPriorityInherit_Post_Extract_Check(
0263 ScoreTqReqFlushPriorityInherit_Context *ctx,
0264 ScoreTqReqFlushPriorityInherit_Post_Extract state
0265 )
0266 {
0267 size_t i;
0268 const T_scheduler_event *event;
0269
0270 i = 0;
0271
0272 switch ( state ) {
0273 case ScoreTqReqFlushPriorityInherit_Post_Extract_Nop: {
0274
0275
0276
0277
0278 T_eq_ptr( GetUnblock( ctx, &i )->thread, GetTCB( ctx, TQ_BLOCKER_A ) );
0279 T_eq_ptr( GetPriorityUpdate( ctx, &i ), &T_scheduler_event_null );
0280 break;
0281 }
0282
0283 case ScoreTqReqFlushPriorityInherit_Post_Extract_All: {
0284
0285
0286
0287
0288
0289
0290 event = GetUnblock( ctx, &i );
0291 T_eq_ptr( event->executing, NULL );
0292 T_eq_ptr( event->thread, GetTCB( ctx, TQ_BLOCKER_D ) );
0293
0294 event = GetUnblock( ctx, &i );
0295 T_eq_ptr( event->executing, NULL );
0296 T_eq_ptr( event->thread, GetTCB( ctx, TQ_BLOCKER_C ) );
0297
0298 if ( ctx->minimum ) {
0299
0300
0301
0302
0303 event = GetPriorityUpdate( ctx, &i );
0304 T_eq_ptr( event->executing, NULL );
0305 T_eq_ptr( event->thread, GetTCB( ctx, TQ_BLOCKER_A ) );
0306 }
0307
0308 event = GetUnblock( ctx, &i );
0309 T_eq_ptr( event->executing, GetTCB( ctx, TQ_BLOCKER_B ) );
0310 T_eq_ptr( event->thread, GetTCB( ctx, TQ_BLOCKER_B ) );
0311
0312 if ( ctx->minimum && rtems_configuration_get_maximum_processors() > 1 ) {
0313
0314
0315
0316
0317
0318
0319 event = GetPriorityUpdate( ctx, &i );
0320 T_eq_ptr( event->executing, GetTCB( ctx, TQ_BLOCKER_B ) );
0321 T_eq_ptr( event->thread, GetTCB( ctx, TQ_BLOCKER_A ) );
0322 }
0323
0324 event = GetPriorityUpdate( ctx, &i );
0325 T_eq_ptr( event, &T_scheduler_event_null );
0326
0327 T_eq_u32(
0328 GetPriority( ctx->tq_ctx->worker_id[ TQ_BLOCKER_A ] ),
0329 PRIO_HIGH
0330 );
0331 break;
0332 }
0333
0334 case ScoreTqReqFlushPriorityInherit_Post_Extract_NA:
0335 break;
0336 }
0337 }
0338
0339 static void ScoreTqReqFlushPriorityInherit_Post_PriorityUpdate_Check(
0340 ScoreTqReqFlushPriorityInherit_Context *ctx,
0341 ScoreTqReqFlushPriorityInherit_Post_PriorityUpdate state
0342 )
0343 {
0344 switch ( state ) {
0345 case ScoreTqReqFlushPriorityInherit_Post_PriorityUpdate_No: {
0346
0347
0348
0349
0350
0351 break;
0352 }
0353
0354 case ScoreTqReqFlushPriorityInherit_Post_PriorityUpdate_Yes: {
0355
0356
0357
0358
0359
0360
0361 break;
0362 }
0363
0364 case ScoreTqReqFlushPriorityInherit_Post_PriorityUpdate_NA:
0365 break;
0366 }
0367 }
0368
0369 static void ScoreTqReqFlushPriorityInherit_Setup(
0370 ScoreTqReqFlushPriorityInherit_Context *ctx
0371 )
0372 {
0373 TQReset( ctx->tq_ctx );
0374 TQSetPriority( ctx->tq_ctx, TQ_BLOCKER_A, PRIO_HIGH );
0375 }
0376
0377 static void ScoreTqReqFlushPriorityInherit_Setup_Wrap( void *arg )
0378 {
0379 ScoreTqReqFlushPriorityInherit_Context *ctx;
0380
0381 ctx = arg;
0382 ctx->Map.in_action_loop = false;
0383 ScoreTqReqFlushPriorityInherit_Setup( ctx );
0384 }
0385
0386 static void ScoreTqReqFlushPriorityInherit_Teardown(
0387 ScoreTqReqFlushPriorityInherit_Context *ctx
0388 )
0389 {
0390 TQReset( ctx->tq_ctx );
0391 }
0392
0393 static void ScoreTqReqFlushPriorityInherit_Teardown_Wrap( void *arg )
0394 {
0395 ScoreTqReqFlushPriorityInherit_Context *ctx;
0396
0397 ctx = arg;
0398 ctx->Map.in_action_loop = false;
0399 ScoreTqReqFlushPriorityInherit_Teardown( ctx );
0400 }
0401
0402 static void ScoreTqReqFlushPriorityInherit_Action(
0403 ScoreTqReqFlushPriorityInherit_Context *ctx
0404 )
0405 {
0406 TQSend( ctx->tq_ctx, TQ_BLOCKER_A, TQ_EVENT_ENQUEUE_PREPARE );
0407
0408 if ( ctx->tq_ctx->how_many > 0 ) {
0409 if ( ctx->minimum ) {
0410 if ( rtems_configuration_get_maximum_processors() > 1 ) {
0411 TQSetScheduler( ctx->tq_ctx, TQ_BLOCKER_B, SCHEDULER_B_ID, PRIO_HIGH );
0412 } else {
0413 TQSetScheduler( ctx->tq_ctx, TQ_BLOCKER_B, SCHEDULER_A_ID, PRIO_HIGH );
0414 }
0415
0416 TQSetPriority( ctx->tq_ctx, TQ_BLOCKER_C, PRIO_VERY_HIGH );
0417 TQSetPriority( ctx->tq_ctx, TQ_BLOCKER_D, PRIO_ULTRA_HIGH );
0418 TQSend( ctx->tq_ctx, TQ_BLOCKER_C, TQ_EVENT_ENQUEUE );
0419 TQSend( ctx->tq_ctx, TQ_BLOCKER_D, TQ_EVENT_ENQUEUE );
0420 } else {
0421 TQSetScheduler( ctx->tq_ctx, TQ_BLOCKER_B, SCHEDULER_A_ID, PRIO_HIGH );
0422 TQSetPriority( ctx->tq_ctx, TQ_BLOCKER_C, PRIO_HIGH );
0423 TQSetPriority( ctx->tq_ctx, TQ_BLOCKER_D, PRIO_HIGH );
0424
0425 TQSend( ctx->tq_ctx, TQ_BLOCKER_D, TQ_EVENT_ENQUEUE );
0426 TQSend( ctx->tq_ctx, TQ_BLOCKER_C, TQ_EVENT_ENQUEUE );
0427 }
0428
0429 T_scheduler_set_event_handler( SchedulerEvent, ctx );
0430 TQSendAndWaitForExecutionStop(
0431 ctx->tq_ctx,
0432 TQ_BLOCKER_B,
0433 TQ_EVENT_ENQUEUE
0434 );
0435 } else {
0436 TQSchedulerRecordStart( ctx->tq_ctx );
0437 TQSend( ctx->tq_ctx, TQ_BLOCKER_A, TQ_EVENT_FLUSH_ALL );
0438 }
0439
0440 TQSchedulerRecordStop( ctx->tq_ctx );
0441 TQSend( ctx->tq_ctx, TQ_BLOCKER_A, TQ_EVENT_ENQUEUE_DONE );
0442 }
0443
0444 static const ScoreTqReqFlushPriorityInherit_Entry
0445 ScoreTqReqFlushPriorityInherit_Entries[] = {
0446 { 0, 1, 0, ScoreTqReqFlushPriorityInherit_Post_Extract_Nop,
0447 ScoreTqReqFlushPriorityInherit_Post_PriorityUpdate_No },
0448 { 0, 0, 0, ScoreTqReqFlushPriorityInherit_Post_Extract_All,
0449 ScoreTqReqFlushPriorityInherit_Post_PriorityUpdate_Yes },
0450 { 0, 0, 0, ScoreTqReqFlushPriorityInherit_Post_Extract_All,
0451 ScoreTqReqFlushPriorityInherit_Post_PriorityUpdate_No }
0452 };
0453
0454 static const uint8_t
0455 ScoreTqReqFlushPriorityInherit_Map[] = {
0456 0, 1, 0, 2
0457 };
0458
0459 static size_t ScoreTqReqFlushPriorityInherit_Scope(
0460 void *arg,
0461 char *buf,
0462 size_t n
0463 )
0464 {
0465 ScoreTqReqFlushPriorityInherit_Context *ctx;
0466
0467 ctx = arg;
0468
0469 if ( ctx->Map.in_action_loop ) {
0470 return T_get_scope(
0471 ScoreTqReqFlushPriorityInherit_PreDesc,
0472 buf,
0473 n,
0474 ctx->Map.pcs
0475 );
0476 }
0477
0478 return 0;
0479 }
0480
0481 static T_fixture ScoreTqReqFlushPriorityInherit_Fixture = {
0482 .setup = ScoreTqReqFlushPriorityInherit_Setup_Wrap,
0483 .stop = NULL,
0484 .teardown = ScoreTqReqFlushPriorityInherit_Teardown_Wrap,
0485 .scope = ScoreTqReqFlushPriorityInherit_Scope,
0486 .initial_context = &ScoreTqReqFlushPriorityInherit_Instance
0487 };
0488
0489 static inline ScoreTqReqFlushPriorityInherit_Entry
0490 ScoreTqReqFlushPriorityInherit_PopEntry(
0491 ScoreTqReqFlushPriorityInherit_Context *ctx
0492 )
0493 {
0494 size_t index;
0495
0496 index = ctx->Map.index;
0497 ctx->Map.index = index + 1;
0498 return ScoreTqReqFlushPriorityInherit_Entries[
0499 ScoreTqReqFlushPriorityInherit_Map[ index ]
0500 ];
0501 }
0502
0503 static void ScoreTqReqFlushPriorityInherit_SetPreConditionStates(
0504 ScoreTqReqFlushPriorityInherit_Context *ctx
0505 )
0506 {
0507 if ( ctx->Map.entry.Pre_Priority_NA ) {
0508 ctx->Map.pcs[ 0 ] = ScoreTqReqFlushPriorityInherit_Pre_Priority_NA;
0509 } else {
0510 ctx->Map.pcs[ 0 ] = ctx->Map.pci[ 0 ];
0511 }
0512
0513 ctx->Map.pcs[ 1 ] = ctx->Map.pci[ 1 ];
0514 }
0515
0516 static void ScoreTqReqFlushPriorityInherit_TestVariant(
0517 ScoreTqReqFlushPriorityInherit_Context *ctx
0518 )
0519 {
0520 ScoreTqReqFlushPriorityInherit_Pre_Priority_Prepare(
0521 ctx,
0522 ctx->Map.pcs[ 0 ]
0523 );
0524 ScoreTqReqFlushPriorityInherit_Pre_Queue_Prepare( ctx, ctx->Map.pcs[ 1 ] );
0525 ScoreTqReqFlushPriorityInherit_Action( ctx );
0526 ScoreTqReqFlushPriorityInherit_Post_Extract_Check(
0527 ctx,
0528 ctx->Map.entry.Post_Extract
0529 );
0530 ScoreTqReqFlushPriorityInherit_Post_PriorityUpdate_Check(
0531 ctx,
0532 ctx->Map.entry.Post_PriorityUpdate
0533 );
0534 }
0535
0536 static T_fixture_node ScoreTqReqFlushPriorityInherit_Node;
0537
0538 static T_remark ScoreTqReqFlushPriorityInherit_Remark = {
0539 .next = NULL,
0540 .remark = "ScoreTqReqFlushPriorityInherit"
0541 };
0542
0543 void ScoreTqReqFlushPriorityInherit_Run( TQContext *tq_ctx )
0544 {
0545 ScoreTqReqFlushPriorityInherit_Context *ctx;
0546
0547 ctx = &ScoreTqReqFlushPriorityInherit_Instance;
0548 ctx->tq_ctx = tq_ctx;
0549
0550 ctx = T_push_fixture(
0551 &ScoreTqReqFlushPriorityInherit_Node,
0552 &ScoreTqReqFlushPriorityInherit_Fixture
0553 );
0554 ctx->Map.in_action_loop = true;
0555 ctx->Map.index = 0;
0556
0557 for (
0558 ctx->Map.pci[ 0 ] = ScoreTqReqFlushPriorityInherit_Pre_Priority_Minimum;
0559 ctx->Map.pci[ 0 ] < ScoreTqReqFlushPriorityInherit_Pre_Priority_NA;
0560 ++ctx->Map.pci[ 0 ]
0561 ) {
0562 for (
0563 ctx->Map.pci[ 1 ] = ScoreTqReqFlushPriorityInherit_Pre_Queue_Empty;
0564 ctx->Map.pci[ 1 ] < ScoreTqReqFlushPriorityInherit_Pre_Queue_NA;
0565 ++ctx->Map.pci[ 1 ]
0566 ) {
0567 ctx->Map.entry = ScoreTqReqFlushPriorityInherit_PopEntry( ctx );
0568 ScoreTqReqFlushPriorityInherit_SetPreConditionStates( ctx );
0569 ScoreTqReqFlushPriorityInherit_TestVariant( ctx );
0570 }
0571 }
0572
0573 T_add_remark( &ScoreTqReqFlushPriorityInherit_Remark );
0574 T_pop_fixture();
0575 }
0576
0577