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.h>
0056 #include <rtems/test-scheduler.h>
0057 #include <rtems/score/threaddispatch.h>
0058 #include <rtems/score/timecounter.h>
0059
0060 #include "tx-support.h"
0061
0062 #include <rtems/test.h>
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073 typedef enum {
0074 RtemsTaskReqWakeAfter_Pre_Ticks_Yield,
0075 RtemsTaskReqWakeAfter_Pre_Ticks_Interval,
0076 RtemsTaskReqWakeAfter_Pre_Ticks_NA
0077 } RtemsTaskReqWakeAfter_Pre_Ticks;
0078
0079 typedef enum {
0080 RtemsTaskReqWakeAfter_Pre_Suspended_Yes,
0081 RtemsTaskReqWakeAfter_Pre_Suspended_No,
0082 RtemsTaskReqWakeAfter_Pre_Suspended_NA
0083 } RtemsTaskReqWakeAfter_Pre_Suspended;
0084
0085 typedef enum {
0086 RtemsTaskReqWakeAfter_Post_Status_Ok,
0087 RtemsTaskReqWakeAfter_Post_Status_NA
0088 } RtemsTaskReqWakeAfter_Post_Status;
0089
0090 typedef enum {
0091 RtemsTaskReqWakeAfter_Post_Timer_Inactive,
0092 RtemsTaskReqWakeAfter_Post_Timer_Ticks,
0093 RtemsTaskReqWakeAfter_Post_Timer_NA
0094 } RtemsTaskReqWakeAfter_Post_Timer;
0095
0096 typedef enum {
0097 RtemsTaskReqWakeAfter_Post_Expire_Relative,
0098 RtemsTaskReqWakeAfter_Post_Expire_NA
0099 } RtemsTaskReqWakeAfter_Post_Expire;
0100
0101 typedef enum {
0102 RtemsTaskReqWakeAfter_Post_Scheduler_Block,
0103 RtemsTaskReqWakeAfter_Post_Scheduler_Yield,
0104 RtemsTaskReqWakeAfter_Post_Scheduler_Nop,
0105 RtemsTaskReqWakeAfter_Post_Scheduler_NA
0106 } RtemsTaskReqWakeAfter_Post_Scheduler;
0107
0108 typedef struct {
0109 uint16_t Skip : 1;
0110 uint16_t Pre_Ticks_NA : 1;
0111 uint16_t Pre_Suspended_NA : 1;
0112 uint16_t Post_Status : 1;
0113 uint16_t Post_Timer : 2;
0114 uint16_t Post_Expire : 1;
0115 uint16_t Post_Scheduler : 2;
0116 } RtemsTaskReqWakeAfter_Entry;
0117
0118
0119
0120
0121 typedef struct {
0122
0123
0124
0125 T_scheduler_log_4 scheduler_log;
0126
0127
0128
0129
0130
0131 uint64_t now;
0132
0133
0134
0135
0136 rtems_id worker_id;
0137
0138
0139
0140
0141
0142 bool suspended;
0143
0144
0145
0146
0147 TaskTimerInfo timer_info;
0148
0149
0150
0151
0152
0153 rtems_status_code status;
0154
0155
0156
0157
0158 rtems_interval ticks;
0159
0160 struct {
0161
0162
0163
0164 size_t pcs[ 2 ];
0165
0166
0167
0168
0169 bool in_action_loop;
0170
0171
0172
0173
0174 size_t index;
0175
0176
0177
0178
0179 RtemsTaskReqWakeAfter_Entry entry;
0180
0181
0182
0183
0184
0185 bool skip;
0186 } Map;
0187 } RtemsTaskReqWakeAfter_Context;
0188
0189 static RtemsTaskReqWakeAfter_Context
0190 RtemsTaskReqWakeAfter_Instance;
0191
0192 static const char * const RtemsTaskReqWakeAfter_PreDesc_Ticks[] = {
0193 "Yield",
0194 "Interval",
0195 "NA"
0196 };
0197
0198 static const char * const RtemsTaskReqWakeAfter_PreDesc_Suspended[] = {
0199 "Yes",
0200 "No",
0201 "NA"
0202 };
0203
0204 static const char * const * const RtemsTaskReqWakeAfter_PreDesc[] = {
0205 RtemsTaskReqWakeAfter_PreDesc_Ticks,
0206 RtemsTaskReqWakeAfter_PreDesc_Suspended,
0207 NULL
0208 };
0209
0210 typedef RtemsTaskReqWakeAfter_Context Context;
0211
0212 static void Worker( rtems_task_argument arg )
0213 {
0214 Context *ctx;
0215
0216 ctx = (Context *) arg;
0217
0218 while ( true ) {
0219 T_scheduler_log *log;
0220
0221 SuspendSelf();
0222
0223 ctx->now = rtems_clock_get_ticks_since_boot();
0224
0225 if ( ctx->suspended ) {
0226 Per_CPU_Control *cpu_self;
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237 cpu_self = _Thread_Dispatch_disable();
0238 SuspendSelf();
0239 cpu_self->dispatch_necessary = false;
0240 _Thread_Dispatch_enable( cpu_self );
0241 }
0242
0243 log = T_scheduler_record_4( &ctx->scheduler_log );
0244 T_null( log );
0245
0246 ctx->status = rtems_task_wake_after( ctx->ticks );
0247
0248 (void) T_scheduler_record( NULL );
0249 }
0250 }
0251
0252 static void RtemsTaskReqWakeAfter_Pre_Ticks_Prepare(
0253 RtemsTaskReqWakeAfter_Context *ctx,
0254 RtemsTaskReqWakeAfter_Pre_Ticks state
0255 )
0256 {
0257 switch ( state ) {
0258 case RtemsTaskReqWakeAfter_Pre_Ticks_Yield: {
0259
0260
0261
0262 ctx->ticks = RTEMS_YIELD_PROCESSOR;
0263 break;
0264 }
0265
0266 case RtemsTaskReqWakeAfter_Pre_Ticks_Interval: {
0267
0268
0269
0270 ctx->ticks = UINT32_MAX;
0271 break;
0272 }
0273
0274 case RtemsTaskReqWakeAfter_Pre_Ticks_NA:
0275 break;
0276 }
0277 }
0278
0279 static void RtemsTaskReqWakeAfter_Pre_Suspended_Prepare(
0280 RtemsTaskReqWakeAfter_Context *ctx,
0281 RtemsTaskReqWakeAfter_Pre_Suspended state
0282 )
0283 {
0284 switch ( state ) {
0285 case RtemsTaskReqWakeAfter_Pre_Suspended_Yes: {
0286
0287
0288
0289 ctx->suspended = true;
0290 break;
0291 }
0292
0293 case RtemsTaskReqWakeAfter_Pre_Suspended_No: {
0294
0295
0296
0297 ctx->suspended = false;
0298 break;
0299 }
0300
0301 case RtemsTaskReqWakeAfter_Pre_Suspended_NA:
0302 break;
0303 }
0304 }
0305
0306 static void RtemsTaskReqWakeAfter_Post_Status_Check(
0307 RtemsTaskReqWakeAfter_Context *ctx,
0308 RtemsTaskReqWakeAfter_Post_Status state
0309 )
0310 {
0311 switch ( state ) {
0312 case RtemsTaskReqWakeAfter_Post_Status_Ok: {
0313
0314
0315
0316
0317 T_rsc_success( ctx->status );
0318 break;
0319 }
0320
0321 case RtemsTaskReqWakeAfter_Post_Status_NA:
0322 break;
0323 }
0324 }
0325
0326 static void RtemsTaskReqWakeAfter_Post_Timer_Check(
0327 RtemsTaskReqWakeAfter_Context *ctx,
0328 RtemsTaskReqWakeAfter_Post_Timer state
0329 )
0330 {
0331 switch ( state ) {
0332 case RtemsTaskReqWakeAfter_Post_Timer_Inactive: {
0333
0334
0335
0336 T_eq_int( ctx->timer_info.state, TASK_TIMER_INACTIVE );
0337 break;
0338 }
0339
0340 case RtemsTaskReqWakeAfter_Post_Timer_Ticks: {
0341
0342
0343
0344 T_eq_int( ctx->timer_info.state, TASK_TIMER_TICKS );
0345 break;
0346 }
0347
0348 case RtemsTaskReqWakeAfter_Post_Timer_NA:
0349 break;
0350 }
0351 }
0352
0353 static void RtemsTaskReqWakeAfter_Post_Expire_Check(
0354 RtemsTaskReqWakeAfter_Context *ctx,
0355 RtemsTaskReqWakeAfter_Post_Expire state
0356 )
0357 {
0358 switch ( state ) {
0359 case RtemsTaskReqWakeAfter_Post_Expire_Relative: {
0360
0361
0362
0363
0364
0365 T_eq_u64( ctx->timer_info.expire_ticks, ctx->now + UINT32_MAX );
0366 break;
0367 }
0368
0369 case RtemsTaskReqWakeAfter_Post_Expire_NA:
0370 break;
0371 }
0372 }
0373
0374 static void RtemsTaskReqWakeAfter_Post_Scheduler_Check(
0375 RtemsTaskReqWakeAfter_Context *ctx,
0376 RtemsTaskReqWakeAfter_Post_Scheduler state
0377 )
0378 {
0379 switch ( state ) {
0380 case RtemsTaskReqWakeAfter_Post_Scheduler_Block: {
0381
0382
0383
0384
0385 T_eq_sz( ctx->scheduler_log.header.recorded, 1 );
0386 T_eq_int(
0387 ctx->scheduler_log.events[ 0 ].operation,
0388 T_SCHEDULER_BLOCK
0389 );
0390 break;
0391 }
0392
0393 case RtemsTaskReqWakeAfter_Post_Scheduler_Yield: {
0394
0395
0396
0397
0398 T_eq_sz( ctx->scheduler_log.header.recorded, 1 );
0399 T_eq_int(
0400 ctx->scheduler_log.events[ 0 ].operation,
0401 T_SCHEDULER_YIELD
0402 );
0403 break;
0404 }
0405
0406 case RtemsTaskReqWakeAfter_Post_Scheduler_Nop: {
0407
0408
0409
0410
0411 T_eq_sz( ctx->scheduler_log.header.recorded, 0 );
0412 break;
0413 }
0414
0415 case RtemsTaskReqWakeAfter_Post_Scheduler_NA:
0416 break;
0417 }
0418 }
0419
0420 static void RtemsTaskReqWakeAfter_Setup( RtemsTaskReqWakeAfter_Context *ctx )
0421 {
0422 SetSelfPriority( PRIO_NORMAL );
0423 ctx->worker_id = CreateTask( "WORK", PRIO_HIGH );
0424 StartTask( ctx->worker_id, Worker, ctx );
0425 }
0426
0427 static void RtemsTaskReqWakeAfter_Setup_Wrap( void *arg )
0428 {
0429 RtemsTaskReqWakeAfter_Context *ctx;
0430
0431 ctx = arg;
0432 ctx->Map.in_action_loop = false;
0433 RtemsTaskReqWakeAfter_Setup( ctx );
0434 }
0435
0436 static void RtemsTaskReqWakeAfter_Teardown(
0437 RtemsTaskReqWakeAfter_Context *ctx
0438 )
0439 {
0440 DeleteTask( ctx->worker_id );
0441 RestoreRunnerPriority();
0442 }
0443
0444 static void RtemsTaskReqWakeAfter_Teardown_Wrap( void *arg )
0445 {
0446 RtemsTaskReqWakeAfter_Context *ctx;
0447
0448 ctx = arg;
0449 ctx->Map.in_action_loop = false;
0450 RtemsTaskReqWakeAfter_Teardown( ctx );
0451 }
0452
0453 static void RtemsTaskReqWakeAfter_Prepare( RtemsTaskReqWakeAfter_Context *ctx )
0454 {
0455 ctx->status = RTEMS_NOT_IMPLEMENTED;
0456 }
0457
0458 static void RtemsTaskReqWakeAfter_Action( RtemsTaskReqWakeAfter_Context *ctx )
0459 {
0460 ResumeTask( ctx->worker_id );
0461 (void) T_scheduler_record( NULL );
0462 GetTaskTimerInfo( ctx->worker_id, &ctx->timer_info );
0463
0464 if ( ctx->suspended ) {
0465 ResumeTask( ctx->worker_id );
0466 }
0467
0468 FinalClockTick();
0469 }
0470
0471 static const RtemsTaskReqWakeAfter_Entry
0472 RtemsTaskReqWakeAfter_Entries[] = {
0473 { 0, 0, 0, RtemsTaskReqWakeAfter_Post_Status_Ok,
0474 RtemsTaskReqWakeAfter_Post_Timer_Inactive,
0475 RtemsTaskReqWakeAfter_Post_Expire_NA,
0476 RtemsTaskReqWakeAfter_Post_Scheduler_Nop },
0477 { 0, 0, 0, RtemsTaskReqWakeAfter_Post_Status_Ok,
0478 RtemsTaskReqWakeAfter_Post_Timer_Inactive,
0479 RtemsTaskReqWakeAfter_Post_Expire_NA,
0480 RtemsTaskReqWakeAfter_Post_Scheduler_Yield },
0481 { 0, 0, 0, RtemsTaskReqWakeAfter_Post_Status_Ok,
0482 RtemsTaskReqWakeAfter_Post_Timer_Ticks,
0483 RtemsTaskReqWakeAfter_Post_Expire_Relative,
0484 RtemsTaskReqWakeAfter_Post_Scheduler_Nop },
0485 { 0, 0, 0, RtemsTaskReqWakeAfter_Post_Status_Ok,
0486 RtemsTaskReqWakeAfter_Post_Timer_Ticks,
0487 RtemsTaskReqWakeAfter_Post_Expire_Relative,
0488 RtemsTaskReqWakeAfter_Post_Scheduler_Block }
0489 };
0490
0491 static const uint8_t
0492 RtemsTaskReqWakeAfter_Map[] = {
0493 0, 1, 2, 3
0494 };
0495
0496 static size_t RtemsTaskReqWakeAfter_Scope( void *arg, char *buf, size_t n )
0497 {
0498 RtemsTaskReqWakeAfter_Context *ctx;
0499
0500 ctx = arg;
0501
0502 if ( ctx->Map.in_action_loop ) {
0503 return T_get_scope( RtemsTaskReqWakeAfter_PreDesc, buf, n, ctx->Map.pcs );
0504 }
0505
0506 return 0;
0507 }
0508
0509 static T_fixture RtemsTaskReqWakeAfter_Fixture = {
0510 .setup = RtemsTaskReqWakeAfter_Setup_Wrap,
0511 .stop = NULL,
0512 .teardown = RtemsTaskReqWakeAfter_Teardown_Wrap,
0513 .scope = RtemsTaskReqWakeAfter_Scope,
0514 .initial_context = &RtemsTaskReqWakeAfter_Instance
0515 };
0516
0517 static inline RtemsTaskReqWakeAfter_Entry RtemsTaskReqWakeAfter_PopEntry(
0518 RtemsTaskReqWakeAfter_Context *ctx
0519 )
0520 {
0521 size_t index;
0522
0523 index = ctx->Map.index;
0524 ctx->Map.index = index + 1;
0525 return RtemsTaskReqWakeAfter_Entries[
0526 RtemsTaskReqWakeAfter_Map[ index ]
0527 ];
0528 }
0529
0530 static void RtemsTaskReqWakeAfter_TestVariant(
0531 RtemsTaskReqWakeAfter_Context *ctx
0532 )
0533 {
0534 RtemsTaskReqWakeAfter_Pre_Ticks_Prepare( ctx, ctx->Map.pcs[ 0 ] );
0535 RtemsTaskReqWakeAfter_Pre_Suspended_Prepare( ctx, ctx->Map.pcs[ 1 ] );
0536 RtemsTaskReqWakeAfter_Action( ctx );
0537 RtemsTaskReqWakeAfter_Post_Status_Check( ctx, ctx->Map.entry.Post_Status );
0538 RtemsTaskReqWakeAfter_Post_Timer_Check( ctx, ctx->Map.entry.Post_Timer );
0539 RtemsTaskReqWakeAfter_Post_Expire_Check( ctx, ctx->Map.entry.Post_Expire );
0540 RtemsTaskReqWakeAfter_Post_Scheduler_Check(
0541 ctx,
0542 ctx->Map.entry.Post_Scheduler
0543 );
0544 }
0545
0546
0547
0548
0549 T_TEST_CASE_FIXTURE( RtemsTaskReqWakeAfter, &RtemsTaskReqWakeAfter_Fixture )
0550 {
0551 RtemsTaskReqWakeAfter_Context *ctx;
0552
0553 ctx = T_fixture_context();
0554 ctx->Map.in_action_loop = true;
0555 ctx->Map.index = 0;
0556
0557 for (
0558 ctx->Map.pcs[ 0 ] = RtemsTaskReqWakeAfter_Pre_Ticks_Yield;
0559 ctx->Map.pcs[ 0 ] < RtemsTaskReqWakeAfter_Pre_Ticks_NA;
0560 ++ctx->Map.pcs[ 0 ]
0561 ) {
0562 for (
0563 ctx->Map.pcs[ 1 ] = RtemsTaskReqWakeAfter_Pre_Suspended_Yes;
0564 ctx->Map.pcs[ 1 ] < RtemsTaskReqWakeAfter_Pre_Suspended_NA;
0565 ++ctx->Map.pcs[ 1 ]
0566 ) {
0567 ctx->Map.entry = RtemsTaskReqWakeAfter_PopEntry( ctx );
0568 RtemsTaskReqWakeAfter_Prepare( ctx );
0569 RtemsTaskReqWakeAfter_TestVariant( ctx );
0570 }
0571 }
0572 }
0573
0574