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 <string.h>
0057 #include <rtems/test-scheduler.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 typedef enum {
0073 RtemsTaskReqWakeWhen_Pre_TODSet_Yes,
0074 RtemsTaskReqWakeWhen_Pre_TODSet_No,
0075 RtemsTaskReqWakeWhen_Pre_TODSet_NA
0076 } RtemsTaskReqWakeWhen_Pre_TODSet;
0077
0078 typedef enum {
0079 RtemsTaskReqWakeWhen_Pre_TOD_Valid,
0080 RtemsTaskReqWakeWhen_Pre_TOD_Null,
0081 RtemsTaskReqWakeWhen_Pre_TOD_NA
0082 } RtemsTaskReqWakeWhen_Pre_TOD;
0083
0084 typedef enum {
0085 RtemsTaskReqWakeWhen_Pre_TODObj_Future,
0086 RtemsTaskReqWakeWhen_Pre_TODObj_PastOrNow,
0087 RtemsTaskReqWakeWhen_Pre_TODObj_Invalid,
0088 RtemsTaskReqWakeWhen_Pre_TODObj_NA
0089 } RtemsTaskReqWakeWhen_Pre_TODObj;
0090
0091 typedef enum {
0092 RtemsTaskReqWakeWhen_Post_Status_Ok,
0093 RtemsTaskReqWakeWhen_Post_Status_NotDef,
0094 RtemsTaskReqWakeWhen_Post_Status_InvAddr,
0095 RtemsTaskReqWakeWhen_Post_Status_InvClock,
0096 RtemsTaskReqWakeWhen_Post_Status_NA
0097 } RtemsTaskReqWakeWhen_Post_Status;
0098
0099 typedef enum {
0100 RtemsTaskReqWakeWhen_Post_Timer_Inactive,
0101 RtemsTaskReqWakeWhen_Post_Timer_Realtime,
0102 RtemsTaskReqWakeWhen_Post_Timer_NA
0103 } RtemsTaskReqWakeWhen_Post_Timer;
0104
0105 typedef enum {
0106 RtemsTaskReqWakeWhen_Post_Expire_Absolute,
0107 RtemsTaskReqWakeWhen_Post_Expire_NA
0108 } RtemsTaskReqWakeWhen_Post_Expire;
0109
0110 typedef enum {
0111 RtemsTaskReqWakeWhen_Post_Scheduler_Block,
0112 RtemsTaskReqWakeWhen_Post_Scheduler_Nop,
0113 RtemsTaskReqWakeWhen_Post_Scheduler_NA
0114 } RtemsTaskReqWakeWhen_Post_Scheduler;
0115
0116 typedef struct {
0117 uint16_t Skip : 1;
0118 uint16_t Pre_TODSet_NA : 1;
0119 uint16_t Pre_TOD_NA : 1;
0120 uint16_t Pre_TODObj_NA : 1;
0121 uint16_t Post_Status : 3;
0122 uint16_t Post_Timer : 2;
0123 uint16_t Post_Expire : 1;
0124 uint16_t Post_Scheduler : 2;
0125 } RtemsTaskReqWakeWhen_Entry;
0126
0127
0128
0129
0130 typedef struct {
0131
0132
0133
0134 T_scheduler_log_4 scheduler_log;
0135
0136
0137
0138
0139
0140 struct timespec now;
0141
0142
0143
0144
0145 rtems_id worker_id;
0146
0147
0148
0149
0150 TaskTimerInfo timer_info;
0151
0152
0153
0154
0155
0156 rtems_time_of_day tod_obj;
0157
0158
0159
0160
0161
0162 rtems_status_code status;
0163
0164
0165
0166
0167 const rtems_time_of_day *tod;
0168
0169 struct {
0170
0171
0172
0173
0174 size_t pci[ 3 ];
0175
0176
0177
0178
0179 size_t pcs[ 3 ];
0180
0181
0182
0183
0184 bool in_action_loop;
0185
0186
0187
0188
0189 size_t index;
0190
0191
0192
0193
0194 RtemsTaskReqWakeWhen_Entry entry;
0195
0196
0197
0198
0199
0200 bool skip;
0201 } Map;
0202 } RtemsTaskReqWakeWhen_Context;
0203
0204 static RtemsTaskReqWakeWhen_Context
0205 RtemsTaskReqWakeWhen_Instance;
0206
0207 static const char * const RtemsTaskReqWakeWhen_PreDesc_TODSet[] = {
0208 "Yes",
0209 "No",
0210 "NA"
0211 };
0212
0213 static const char * const RtemsTaskReqWakeWhen_PreDesc_TOD[] = {
0214 "Valid",
0215 "Null",
0216 "NA"
0217 };
0218
0219 static const char * const RtemsTaskReqWakeWhen_PreDesc_TODObj[] = {
0220 "Future",
0221 "PastOrNow",
0222 "Invalid",
0223 "NA"
0224 };
0225
0226 static const char * const * const RtemsTaskReqWakeWhen_PreDesc[] = {
0227 RtemsTaskReqWakeWhen_PreDesc_TODSet,
0228 RtemsTaskReqWakeWhen_PreDesc_TOD,
0229 RtemsTaskReqWakeWhen_PreDesc_TODObj,
0230 NULL
0231 };
0232
0233 typedef RtemsTaskReqWakeWhen_Context Context;
0234
0235 static void SetTOD( rtems_time_of_day *tod, uint32_t year )
0236 {
0237 memset( tod, 0, sizeof( *tod ) );
0238 tod->year = year;
0239 tod->month = 1;
0240 tod->day = 1;
0241 }
0242
0243 static void Worker( rtems_task_argument arg )
0244 {
0245 Context *ctx;
0246
0247 ctx = (Context *) arg;
0248
0249 while ( true ) {
0250 T_scheduler_log *log;
0251
0252 SuspendSelf();
0253
0254 log = T_scheduler_record_4( &ctx->scheduler_log );
0255 T_null( log );
0256
0257 _Timecounter_Getnanotime( &ctx->now );
0258
0259 ctx->status = rtems_task_wake_when( ctx->tod );
0260
0261 (void) T_scheduler_record( NULL );
0262 }
0263 }
0264
0265 static void RtemsTaskReqWakeWhen_Pre_TODSet_Prepare(
0266 RtemsTaskReqWakeWhen_Context *ctx,
0267 RtemsTaskReqWakeWhen_Pre_TODSet state
0268 )
0269 {
0270 rtems_status_code sc;
0271 rtems_time_of_day tod;
0272
0273 switch ( state ) {
0274 case RtemsTaskReqWakeWhen_Pre_TODSet_Yes: {
0275
0276
0277
0278 SetTOD( &tod, 2000 );
0279 sc = rtems_clock_set( &tod );
0280 T_rsc_success( sc );
0281 break;
0282 }
0283
0284 case RtemsTaskReqWakeWhen_Pre_TODSet_No: {
0285
0286
0287
0288 UnsetClock();
0289 break;
0290 }
0291
0292 case RtemsTaskReqWakeWhen_Pre_TODSet_NA:
0293 break;
0294 }
0295 }
0296
0297 static void RtemsTaskReqWakeWhen_Pre_TOD_Prepare(
0298 RtemsTaskReqWakeWhen_Context *ctx,
0299 RtemsTaskReqWakeWhen_Pre_TOD state
0300 )
0301 {
0302 switch ( state ) {
0303 case RtemsTaskReqWakeWhen_Pre_TOD_Valid: {
0304
0305
0306
0307
0308 ctx->tod = &ctx->tod_obj;
0309 break;
0310 }
0311
0312 case RtemsTaskReqWakeWhen_Pre_TOD_Null: {
0313
0314
0315
0316 ctx->tod = NULL;
0317 break;
0318 }
0319
0320 case RtemsTaskReqWakeWhen_Pre_TOD_NA:
0321 break;
0322 }
0323 }
0324
0325 static void RtemsTaskReqWakeWhen_Pre_TODObj_Prepare(
0326 RtemsTaskReqWakeWhen_Context *ctx,
0327 RtemsTaskReqWakeWhen_Pre_TODObj state
0328 )
0329 {
0330 switch ( state ) {
0331 case RtemsTaskReqWakeWhen_Pre_TODObj_Future: {
0332
0333
0334
0335
0336 SetTOD( &ctx->tod_obj, 2010 );
0337 break;
0338 }
0339
0340 case RtemsTaskReqWakeWhen_Pre_TODObj_PastOrNow: {
0341
0342
0343
0344
0345
0346 SetTOD( &ctx->tod_obj, 1990 );
0347 break;
0348 }
0349
0350 case RtemsTaskReqWakeWhen_Pre_TODObj_Invalid: {
0351
0352
0353
0354
0355 memset( &ctx->tod_obj, 0xff, sizeof( ctx->tod_obj ) );
0356 break;
0357 }
0358
0359 case RtemsTaskReqWakeWhen_Pre_TODObj_NA:
0360 break;
0361 }
0362 }
0363
0364 static void RtemsTaskReqWakeWhen_Post_Status_Check(
0365 RtemsTaskReqWakeWhen_Context *ctx,
0366 RtemsTaskReqWakeWhen_Post_Status state
0367 )
0368 {
0369 switch ( state ) {
0370 case RtemsTaskReqWakeWhen_Post_Status_Ok: {
0371
0372
0373
0374 T_rsc_success( ctx->status );
0375 break;
0376 }
0377
0378 case RtemsTaskReqWakeWhen_Post_Status_NotDef: {
0379
0380
0381
0382
0383 T_rsc( ctx->status, RTEMS_NOT_DEFINED );
0384 break;
0385 }
0386
0387 case RtemsTaskReqWakeWhen_Post_Status_InvAddr: {
0388
0389
0390
0391
0392 T_rsc( ctx->status, RTEMS_INVALID_ADDRESS );
0393 break;
0394 }
0395
0396 case RtemsTaskReqWakeWhen_Post_Status_InvClock: {
0397
0398
0399
0400
0401 T_rsc( ctx->status, RTEMS_INVALID_CLOCK );
0402 break;
0403 }
0404
0405 case RtemsTaskReqWakeWhen_Post_Status_NA:
0406 break;
0407 }
0408 }
0409
0410 static void RtemsTaskReqWakeWhen_Post_Timer_Check(
0411 RtemsTaskReqWakeWhen_Context *ctx,
0412 RtemsTaskReqWakeWhen_Post_Timer state
0413 )
0414 {
0415 switch ( state ) {
0416 case RtemsTaskReqWakeWhen_Post_Timer_Inactive: {
0417
0418
0419
0420 T_eq_int( ctx->timer_info.state, TASK_TIMER_INACTIVE );
0421 break;
0422 }
0423
0424 case RtemsTaskReqWakeWhen_Post_Timer_Realtime: {
0425
0426
0427
0428
0429 T_eq_int( ctx->timer_info.state, TASK_TIMER_REALTIME );
0430 break;
0431 }
0432
0433 case RtemsTaskReqWakeWhen_Post_Timer_NA:
0434 break;
0435 }
0436 }
0437
0438 static void RtemsTaskReqWakeWhen_Post_Expire_Check(
0439 RtemsTaskReqWakeWhen_Context *ctx,
0440 RtemsTaskReqWakeWhen_Post_Expire state
0441 )
0442 {
0443 switch ( state ) {
0444 case RtemsTaskReqWakeWhen_Post_Expire_Absolute: {
0445
0446
0447
0448
0449 T_eq_i64( ctx->timer_info.expire_timespec.tv_sec, 1262304000 );
0450 T_eq_long( ctx->timer_info.expire_timespec.tv_nsec, 0 );
0451 break;
0452 }
0453
0454 case RtemsTaskReqWakeWhen_Post_Expire_NA:
0455 break;
0456 }
0457 }
0458
0459 static void RtemsTaskReqWakeWhen_Post_Scheduler_Check(
0460 RtemsTaskReqWakeWhen_Context *ctx,
0461 RtemsTaskReqWakeWhen_Post_Scheduler state
0462 )
0463 {
0464 switch ( state ) {
0465 case RtemsTaskReqWakeWhen_Post_Scheduler_Block: {
0466
0467
0468
0469
0470 T_eq_sz( ctx->scheduler_log.header.recorded, 1 );
0471 T_eq_int(
0472 ctx->scheduler_log.events[ 0 ].operation,
0473 T_SCHEDULER_BLOCK
0474 );
0475 break;
0476 }
0477
0478 case RtemsTaskReqWakeWhen_Post_Scheduler_Nop: {
0479
0480
0481
0482
0483 T_eq_sz( ctx->scheduler_log.header.recorded, 0 );
0484 break;
0485 }
0486
0487 case RtemsTaskReqWakeWhen_Post_Scheduler_NA:
0488 break;
0489 }
0490 }
0491
0492 static void RtemsTaskReqWakeWhen_Setup( RtemsTaskReqWakeWhen_Context *ctx )
0493 {
0494 SetSelfPriority( PRIO_NORMAL );
0495 ctx->worker_id = CreateTask( "WORK", PRIO_HIGH );
0496 StartTask( ctx->worker_id, Worker, ctx );
0497 }
0498
0499 static void RtemsTaskReqWakeWhen_Setup_Wrap( void *arg )
0500 {
0501 RtemsTaskReqWakeWhen_Context *ctx;
0502
0503 ctx = arg;
0504 ctx->Map.in_action_loop = false;
0505 RtemsTaskReqWakeWhen_Setup( ctx );
0506 }
0507
0508 static void RtemsTaskReqWakeWhen_Teardown( RtemsTaskReqWakeWhen_Context *ctx )
0509 {
0510 DeleteTask( ctx->worker_id );
0511 RestoreRunnerPriority();
0512 }
0513
0514 static void RtemsTaskReqWakeWhen_Teardown_Wrap( void *arg )
0515 {
0516 RtemsTaskReqWakeWhen_Context *ctx;
0517
0518 ctx = arg;
0519 ctx->Map.in_action_loop = false;
0520 RtemsTaskReqWakeWhen_Teardown( ctx );
0521 }
0522
0523 static void RtemsTaskReqWakeWhen_Prepare( RtemsTaskReqWakeWhen_Context *ctx )
0524 {
0525 ctx->status = RTEMS_NOT_IMPLEMENTED;
0526 }
0527
0528 static void RtemsTaskReqWakeWhen_Action( RtemsTaskReqWakeWhen_Context *ctx )
0529 {
0530 ResumeTask( ctx->worker_id );
0531 (void) T_scheduler_record( NULL );
0532 GetTaskTimerInfo( ctx->worker_id, &ctx->timer_info );
0533 FinalClockTick();
0534 }
0535
0536 static const RtemsTaskReqWakeWhen_Entry
0537 RtemsTaskReqWakeWhen_Entries[] = {
0538 { 0, 0, 0, 1, RtemsTaskReqWakeWhen_Post_Status_InvAddr,
0539 RtemsTaskReqWakeWhen_Post_Timer_Inactive,
0540 RtemsTaskReqWakeWhen_Post_Expire_NA,
0541 RtemsTaskReqWakeWhen_Post_Scheduler_Nop },
0542 { 0, 0, 0, 0, RtemsTaskReqWakeWhen_Post_Status_NotDef,
0543 RtemsTaskReqWakeWhen_Post_Timer_Inactive,
0544 RtemsTaskReqWakeWhen_Post_Expire_NA,
0545 RtemsTaskReqWakeWhen_Post_Scheduler_Nop },
0546 { 0, 0, 0, 1, RtemsTaskReqWakeWhen_Post_Status_NotDef,
0547 RtemsTaskReqWakeWhen_Post_Timer_Inactive,
0548 RtemsTaskReqWakeWhen_Post_Expire_NA,
0549 RtemsTaskReqWakeWhen_Post_Scheduler_Nop },
0550 { 0, 0, 0, 0, RtemsTaskReqWakeWhen_Post_Status_InvClock,
0551 RtemsTaskReqWakeWhen_Post_Timer_Inactive,
0552 RtemsTaskReqWakeWhen_Post_Expire_NA,
0553 RtemsTaskReqWakeWhen_Post_Scheduler_Nop },
0554 { 0, 0, 0, 0, RtemsTaskReqWakeWhen_Post_Status_Ok,
0555 RtemsTaskReqWakeWhen_Post_Timer_Realtime,
0556 RtemsTaskReqWakeWhen_Post_Expire_Absolute,
0557 RtemsTaskReqWakeWhen_Post_Scheduler_Block }
0558 };
0559
0560 static const uint8_t
0561 RtemsTaskReqWakeWhen_Map[] = {
0562 4, 3, 3, 0, 0, 0, 1, 1, 1, 2, 2, 2
0563 };
0564
0565 static size_t RtemsTaskReqWakeWhen_Scope( void *arg, char *buf, size_t n )
0566 {
0567 RtemsTaskReqWakeWhen_Context *ctx;
0568
0569 ctx = arg;
0570
0571 if ( ctx->Map.in_action_loop ) {
0572 return T_get_scope( RtemsTaskReqWakeWhen_PreDesc, buf, n, ctx->Map.pcs );
0573 }
0574
0575 return 0;
0576 }
0577
0578 static T_fixture RtemsTaskReqWakeWhen_Fixture = {
0579 .setup = RtemsTaskReqWakeWhen_Setup_Wrap,
0580 .stop = NULL,
0581 .teardown = RtemsTaskReqWakeWhen_Teardown_Wrap,
0582 .scope = RtemsTaskReqWakeWhen_Scope,
0583 .initial_context = &RtemsTaskReqWakeWhen_Instance
0584 };
0585
0586 static inline RtemsTaskReqWakeWhen_Entry RtemsTaskReqWakeWhen_PopEntry(
0587 RtemsTaskReqWakeWhen_Context *ctx
0588 )
0589 {
0590 size_t index;
0591
0592 index = ctx->Map.index;
0593 ctx->Map.index = index + 1;
0594 return RtemsTaskReqWakeWhen_Entries[
0595 RtemsTaskReqWakeWhen_Map[ index ]
0596 ];
0597 }
0598
0599 static void RtemsTaskReqWakeWhen_SetPreConditionStates(
0600 RtemsTaskReqWakeWhen_Context *ctx
0601 )
0602 {
0603 ctx->Map.pcs[ 0 ] = ctx->Map.pci[ 0 ];
0604 ctx->Map.pcs[ 1 ] = ctx->Map.pci[ 1 ];
0605
0606 if ( ctx->Map.entry.Pre_TODObj_NA ) {
0607 ctx->Map.pcs[ 2 ] = RtemsTaskReqWakeWhen_Pre_TODObj_NA;
0608 } else {
0609 ctx->Map.pcs[ 2 ] = ctx->Map.pci[ 2 ];
0610 }
0611 }
0612
0613 static void RtemsTaskReqWakeWhen_TestVariant(
0614 RtemsTaskReqWakeWhen_Context *ctx
0615 )
0616 {
0617 RtemsTaskReqWakeWhen_Pre_TODSet_Prepare( ctx, ctx->Map.pcs[ 0 ] );
0618 RtemsTaskReqWakeWhen_Pre_TOD_Prepare( ctx, ctx->Map.pcs[ 1 ] );
0619 RtemsTaskReqWakeWhen_Pre_TODObj_Prepare( ctx, ctx->Map.pcs[ 2 ] );
0620 RtemsTaskReqWakeWhen_Action( ctx );
0621 RtemsTaskReqWakeWhen_Post_Status_Check( ctx, ctx->Map.entry.Post_Status );
0622 RtemsTaskReqWakeWhen_Post_Timer_Check( ctx, ctx->Map.entry.Post_Timer );
0623 RtemsTaskReqWakeWhen_Post_Expire_Check( ctx, ctx->Map.entry.Post_Expire );
0624 RtemsTaskReqWakeWhen_Post_Scheduler_Check(
0625 ctx,
0626 ctx->Map.entry.Post_Scheduler
0627 );
0628 }
0629
0630
0631
0632
0633 T_TEST_CASE_FIXTURE( RtemsTaskReqWakeWhen, &RtemsTaskReqWakeWhen_Fixture )
0634 {
0635 RtemsTaskReqWakeWhen_Context *ctx;
0636
0637 ctx = T_fixture_context();
0638 ctx->Map.in_action_loop = true;
0639 ctx->Map.index = 0;
0640
0641 for (
0642 ctx->Map.pci[ 0 ] = RtemsTaskReqWakeWhen_Pre_TODSet_Yes;
0643 ctx->Map.pci[ 0 ] < RtemsTaskReqWakeWhen_Pre_TODSet_NA;
0644 ++ctx->Map.pci[ 0 ]
0645 ) {
0646 for (
0647 ctx->Map.pci[ 1 ] = RtemsTaskReqWakeWhen_Pre_TOD_Valid;
0648 ctx->Map.pci[ 1 ] < RtemsTaskReqWakeWhen_Pre_TOD_NA;
0649 ++ctx->Map.pci[ 1 ]
0650 ) {
0651 for (
0652 ctx->Map.pci[ 2 ] = RtemsTaskReqWakeWhen_Pre_TODObj_Future;
0653 ctx->Map.pci[ 2 ] < RtemsTaskReqWakeWhen_Pre_TODObj_NA;
0654 ++ctx->Map.pci[ 2 ]
0655 ) {
0656 ctx->Map.entry = RtemsTaskReqWakeWhen_PopEntry( ctx );
0657 RtemsTaskReqWakeWhen_SetPreConditionStates( ctx );
0658 RtemsTaskReqWakeWhen_Prepare( ctx );
0659 RtemsTaskReqWakeWhen_TestVariant( ctx );
0660 }
0661 }
0662 }
0663 }
0664
0665