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 <rtems/score/smpimpl.h>
0056 #include <rtems/score/threadimpl.h>
0057
0058 #include "tr-tq-timeout-mrsp.h"
0059 #include "tx-support.h"
0060
0061 #include <rtems/test.h>
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071 typedef struct {
0072 uint8_t Skip : 1;
0073 uint8_t Pre_Scheduler_NA : 1;
0074 uint8_t Pre_WaitState_NA : 1;
0075 uint8_t Post_Status : 2;
0076 uint8_t Post_Unblock : 1;
0077 } ScoreTqReqTimeoutMrsp_Entry;
0078
0079
0080
0081
0082 typedef struct {
0083
0084
0085
0086
0087 bool other_scheduler;
0088
0089
0090
0091
0092
0093 bool restore_scheduler;
0094
0095
0096
0097
0098
0099 TQContext *tq_ctx;
0100
0101 struct {
0102
0103
0104
0105 size_t pcs[ 2 ];
0106
0107
0108
0109
0110 bool in_action_loop;
0111
0112
0113
0114
0115 size_t index;
0116
0117
0118
0119
0120 ScoreTqReqTimeoutMrsp_Entry entry;
0121
0122
0123
0124
0125
0126 bool skip;
0127 } Map;
0128 } ScoreTqReqTimeoutMrsp_Context;
0129
0130 static ScoreTqReqTimeoutMrsp_Context
0131 ScoreTqReqTimeoutMrsp_Instance;
0132
0133 static const char * const ScoreTqReqTimeoutMrsp_PreDesc_Scheduler[] = {
0134 "Same",
0135 "Other",
0136 "NA"
0137 };
0138
0139 static const char * const ScoreTqReqTimeoutMrsp_PreDesc_WaitState[] = {
0140 "IntendToBlock",
0141 "ReadyAgain",
0142 "NA"
0143 };
0144
0145 static const char * const * const ScoreTqReqTimeoutMrsp_PreDesc[] = {
0146 ScoreTqReqTimeoutMrsp_PreDesc_Scheduler,
0147 ScoreTqReqTimeoutMrsp_PreDesc_WaitState,
0148 NULL
0149 };
0150
0151 typedef ScoreTqReqTimeoutMrsp_Context Context;
0152
0153 static const rtems_tcb *GetUnblock( Context *ctx, size_t *index )
0154 {
0155 return TQGetNextUnblock( ctx->tq_ctx, index )->thread;
0156 }
0157
0158 static void Tick( void *arg )
0159 {
0160 Context *ctx;
0161
0162 ctx = arg;
0163 TQSchedulerRecordStart( ctx->tq_ctx );
0164 FinalClockTick();
0165 TQSchedulerRecordStop( ctx->tq_ctx );
0166 }
0167
0168 static void ScoreTqReqTimeoutMrsp_Pre_Scheduler_Prepare(
0169 ScoreTqReqTimeoutMrsp_Context *ctx,
0170 ScoreTqReqTimeoutMrsp_Pre_Scheduler state
0171 )
0172 {
0173 switch ( state ) {
0174 case ScoreTqReqTimeoutMrsp_Pre_Scheduler_Same: {
0175
0176
0177
0178
0179 ctx->other_scheduler = false;
0180
0181 TQSetScheduler(
0182 ctx->tq_ctx,
0183 TQ_BLOCKER_A,
0184 SCHEDULER_A_ID,
0185 PRIO_LOW
0186 );
0187 RemoveProcessor( SCHEDULER_B_ID, 1 );
0188 AddProcessor( SCHEDULER_A_ID, 1 );
0189 ctx->restore_scheduler = true;
0190 break;
0191 }
0192
0193 case ScoreTqReqTimeoutMrsp_Pre_Scheduler_Other: {
0194
0195
0196
0197
0198 ctx->other_scheduler = true;
0199
0200 TQSetScheduler(
0201 ctx->tq_ctx,
0202 TQ_BLOCKER_A,
0203 SCHEDULER_B_ID,
0204 PRIO_NORMAL
0205 );
0206 break;
0207 }
0208
0209 case ScoreTqReqTimeoutMrsp_Pre_Scheduler_NA:
0210 break;
0211 }
0212 }
0213
0214 static void ScoreTqReqTimeoutMrsp_Pre_WaitState_Prepare(
0215 ScoreTqReqTimeoutMrsp_Context *ctx,
0216 ScoreTqReqTimeoutMrsp_Pre_WaitState state
0217 )
0218 {
0219 switch ( state ) {
0220 case ScoreTqReqTimeoutMrsp_Pre_WaitState_IntendToBlock: {
0221
0222
0223
0224
0225 Per_CPU_Control *cpu;
0226
0227 TQEnqueuePrepare( ctx->tq_ctx );
0228 TQSendAndWaitForIntendToBlock(
0229 ctx->tq_ctx,
0230 TQ_BLOCKER_A,
0231 TQ_EVENT_ENQUEUE
0232 );
0233 cpu = _Thread_Get_CPU( ctx->tq_ctx->worker_tcb[ TQ_BLOCKER_A ] );
0234
0235
0236
0237
0238
0239
0240 while ( cpu->thread_dispatch_disable_level != 0 ) {
0241
0242 }
0243
0244 Tick( ctx );
0245 WaitForExecutionStop( ctx->tq_ctx->worker_id[ TQ_BLOCKER_A ] );
0246 TQEnqueueDone( ctx->tq_ctx );
0247 break;
0248 }
0249
0250 case ScoreTqReqTimeoutMrsp_Pre_WaitState_ReadyAgain: {
0251
0252
0253
0254
0255 TQEnqueuePrepare( ctx->tq_ctx );
0256 TQSendAndWaitForIntendToBlock(
0257 ctx->tq_ctx,
0258 TQ_BLOCKER_A,
0259 TQ_EVENT_ENQUEUE | TQ_EVENT_TIMEOUT | TQ_EVENT_SURRENDER |
0260 TQ_EVENT_SCHEDULER_RECORD_STOP
0261 );
0262 TQSchedulerRecordStart( ctx->tq_ctx );
0263 TQEnqueueDone( ctx->tq_ctx );
0264 WaitForExecutionStop( ctx->tq_ctx->worker_id[ TQ_BLOCKER_A ] );
0265 break;
0266 }
0267
0268 case ScoreTqReqTimeoutMrsp_Pre_WaitState_NA:
0269 break;
0270 }
0271 }
0272
0273 static void ScoreTqReqTimeoutMrsp_Post_Status_Check(
0274 ScoreTqReqTimeoutMrsp_Context *ctx,
0275 ScoreTqReqTimeoutMrsp_Post_Status state
0276 )
0277 {
0278 switch ( state ) {
0279 case ScoreTqReqTimeoutMrsp_Post_Status_Ok: {
0280
0281
0282
0283
0284 T_eq_int(
0285 ctx->tq_ctx->status[ TQ_BLOCKER_A ],
0286 TQConvertStatus( ctx->tq_ctx, STATUS_SUCCESSFUL )
0287 );
0288 break;
0289 }
0290
0291 case ScoreTqReqTimeoutMrsp_Post_Status_Timeout: {
0292
0293
0294
0295
0296 T_eq_int(
0297 ctx->tq_ctx->status[ TQ_BLOCKER_A ],
0298 TQConvertStatus( ctx->tq_ctx, STATUS_TIMEOUT )
0299 );
0300 break;
0301 }
0302
0303 case ScoreTqReqTimeoutMrsp_Post_Status_NA:
0304 break;
0305 }
0306 }
0307
0308 static void ScoreTqReqTimeoutMrsp_Post_Unblock_Check(
0309 ScoreTqReqTimeoutMrsp_Context *ctx,
0310 ScoreTqReqTimeoutMrsp_Post_Unblock state
0311 )
0312 {
0313 size_t i;
0314
0315 i = 0;
0316
0317 switch ( state ) {
0318 case ScoreTqReqTimeoutMrsp_Post_Unblock_No: {
0319
0320
0321
0322
0323 T_eq_ptr( GetUnblock( ctx, &i ), NULL );
0324 break;
0325 }
0326
0327 case ScoreTqReqTimeoutMrsp_Post_Unblock_NA:
0328 break;
0329 }
0330 }
0331
0332 static void ScoreTqReqTimeoutMrsp_Setup( ScoreTqReqTimeoutMrsp_Context *ctx )
0333 {
0334 TQReset( ctx->tq_ctx );
0335 }
0336
0337 static void ScoreTqReqTimeoutMrsp_Setup_Wrap( void *arg )
0338 {
0339 ScoreTqReqTimeoutMrsp_Context *ctx;
0340
0341 ctx = arg;
0342 ctx->Map.in_action_loop = false;
0343 ScoreTqReqTimeoutMrsp_Setup( ctx );
0344 }
0345
0346 static void ScoreTqReqTimeoutMrsp_Teardown(
0347 ScoreTqReqTimeoutMrsp_Context *ctx
0348 )
0349 {
0350 TQReset( ctx->tq_ctx );
0351 }
0352
0353 static void ScoreTqReqTimeoutMrsp_Teardown_Wrap( void *arg )
0354 {
0355 ScoreTqReqTimeoutMrsp_Context *ctx;
0356
0357 ctx = arg;
0358 ctx->Map.in_action_loop = false;
0359 ScoreTqReqTimeoutMrsp_Teardown( ctx );
0360 }
0361
0362 static void ScoreTqReqTimeoutMrsp_Prepare( ScoreTqReqTimeoutMrsp_Context *ctx )
0363 {
0364 ctx->restore_scheduler = false;
0365 }
0366
0367 static void ScoreTqReqTimeoutMrsp_Action( ScoreTqReqTimeoutMrsp_Context *ctx )
0368 {
0369
0370
0371
0372 }
0373
0374 static void ScoreTqReqTimeoutMrsp_Cleanup( ScoreTqReqTimeoutMrsp_Context *ctx )
0375 {
0376 if ( ctx->restore_scheduler ) {
0377 RemoveProcessor( SCHEDULER_A_ID, 1 );
0378 AddProcessor( SCHEDULER_B_ID, 1 );
0379 }
0380 }
0381
0382 static const ScoreTqReqTimeoutMrsp_Entry
0383 ScoreTqReqTimeoutMrsp_Entries[] = {
0384 { 0, 0, 0, ScoreTqReqTimeoutMrsp_Post_Status_Timeout,
0385 ScoreTqReqTimeoutMrsp_Post_Unblock_No },
0386 { 0, 0, 0, ScoreTqReqTimeoutMrsp_Post_Status_Ok,
0387 ScoreTqReqTimeoutMrsp_Post_Unblock_No }
0388 };
0389
0390 static const uint8_t
0391 ScoreTqReqTimeoutMrsp_Map[] = {
0392 0, 1, 0, 1
0393 };
0394
0395 static size_t ScoreTqReqTimeoutMrsp_Scope( void *arg, char *buf, size_t n )
0396 {
0397 ScoreTqReqTimeoutMrsp_Context *ctx;
0398
0399 ctx = arg;
0400
0401 if ( ctx->Map.in_action_loop ) {
0402 return T_get_scope( ScoreTqReqTimeoutMrsp_PreDesc, buf, n, ctx->Map.pcs );
0403 }
0404
0405 return 0;
0406 }
0407
0408 static T_fixture ScoreTqReqTimeoutMrsp_Fixture = {
0409 .setup = ScoreTqReqTimeoutMrsp_Setup_Wrap,
0410 .stop = NULL,
0411 .teardown = ScoreTqReqTimeoutMrsp_Teardown_Wrap,
0412 .scope = ScoreTqReqTimeoutMrsp_Scope,
0413 .initial_context = &ScoreTqReqTimeoutMrsp_Instance
0414 };
0415
0416 static inline ScoreTqReqTimeoutMrsp_Entry ScoreTqReqTimeoutMrsp_PopEntry(
0417 ScoreTqReqTimeoutMrsp_Context *ctx
0418 )
0419 {
0420 size_t index;
0421
0422 index = ctx->Map.index;
0423 ctx->Map.index = index + 1;
0424 return ScoreTqReqTimeoutMrsp_Entries[
0425 ScoreTqReqTimeoutMrsp_Map[ index ]
0426 ];
0427 }
0428
0429 static void ScoreTqReqTimeoutMrsp_TestVariant(
0430 ScoreTqReqTimeoutMrsp_Context *ctx
0431 )
0432 {
0433 ScoreTqReqTimeoutMrsp_Pre_Scheduler_Prepare( ctx, ctx->Map.pcs[ 0 ] );
0434 ScoreTqReqTimeoutMrsp_Pre_WaitState_Prepare( ctx, ctx->Map.pcs[ 1 ] );
0435 ScoreTqReqTimeoutMrsp_Action( ctx );
0436 ScoreTqReqTimeoutMrsp_Post_Status_Check( ctx, ctx->Map.entry.Post_Status );
0437 ScoreTqReqTimeoutMrsp_Post_Unblock_Check( ctx, ctx->Map.entry.Post_Unblock );
0438 }
0439
0440 static T_fixture_node ScoreTqReqTimeoutMrsp_Node;
0441
0442 static T_remark ScoreTqReqTimeoutMrsp_Remark = {
0443 .next = NULL,
0444 .remark = "ScoreTqReqTimeoutMrsp"
0445 };
0446
0447 void ScoreTqReqTimeoutMrsp_Run( TQContext *tq_ctx )
0448 {
0449 ScoreTqReqTimeoutMrsp_Context *ctx;
0450
0451 ctx = &ScoreTqReqTimeoutMrsp_Instance;
0452 ctx->tq_ctx = tq_ctx;
0453
0454 ctx = T_push_fixture(
0455 &ScoreTqReqTimeoutMrsp_Node,
0456 &ScoreTqReqTimeoutMrsp_Fixture
0457 );
0458 ctx->Map.in_action_loop = true;
0459 ctx->Map.index = 0;
0460
0461 for (
0462 ctx->Map.pcs[ 0 ] = ScoreTqReqTimeoutMrsp_Pre_Scheduler_Same;
0463 ctx->Map.pcs[ 0 ] < ScoreTqReqTimeoutMrsp_Pre_Scheduler_NA;
0464 ++ctx->Map.pcs[ 0 ]
0465 ) {
0466 for (
0467 ctx->Map.pcs[ 1 ] = ScoreTqReqTimeoutMrsp_Pre_WaitState_IntendToBlock;
0468 ctx->Map.pcs[ 1 ] < ScoreTqReqTimeoutMrsp_Pre_WaitState_NA;
0469 ++ctx->Map.pcs[ 1 ]
0470 ) {
0471 ctx->Map.entry = ScoreTqReqTimeoutMrsp_PopEntry( ctx );
0472 ScoreTqReqTimeoutMrsp_Prepare( ctx );
0473 ScoreTqReqTimeoutMrsp_TestVariant( ctx );
0474 ScoreTqReqTimeoutMrsp_Cleanup( ctx );
0475 }
0476 }
0477
0478 T_add_remark( &ScoreTqReqTimeoutMrsp_Remark );
0479 T_pop_fixture();
0480 }
0481
0482