File indexing completed on 2025-05-11 08:24:37
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 #ifdef HAVE_CONFIG_H
0030 #include "config.h"
0031 #endif
0032
0033 #include <time.h>
0034 #include <errno.h>
0035 #include <stdint.h>
0036
0037 #include "pmacros.h"
0038 #include "pritime.h"
0039
0040 #include <rtems.h>
0041 #include <rtems/score/todimpl.h>
0042
0043 const char rtems_test_name[] = "PSXCLOCK";
0044
0045 static void check_enosys(int status)
0046 {
0047 if ( (status == -1) && (errno == ENOSYS) )
0048 return;
0049 puts( "ERROR -- did not return ENOSYS as expected" );
0050 rtems_test_exit(0);
0051 }
0052
0053 static void wait_ticks( rtems_interval ticks )
0054 {
0055
0056
0057
0058 rtems_test_assert( rtems_task_wake_after( ticks ) == RTEMS_SUCCESSFUL );
0059 }
0060
0061 struct clock_context;
0062 typedef struct clock_context clock_context;
0063 typedef void (*clock_sleeper)(clock_context* ctx);
0064 struct clock_context {
0065 const char* name;
0066 int instance;
0067 rtems_id tid;
0068 int counter;
0069 int result;
0070 rtems_interval ticks;
0071 struct timespec tspec;
0072 clock_sleeper sleeper;
0073 };
0074
0075 static void clock_context_init(
0076 clock_context* ctx, const char* name, int instance,
0077 time_t secs, long nsecs, clock_sleeper sleeper)
0078 {
0079 memset( ctx, 0, sizeof( *ctx ) );
0080 ctx->name = name;
0081 ctx->instance = instance;
0082 ctx->tspec.tv_sec = secs;
0083 ctx->tspec.tv_nsec = nsecs;
0084 ctx->sleeper = sleeper;
0085 }
0086
0087 static void test_nanosleep( clock_context* ctx )
0088 {
0089 if ( nanosleep ( &ctx->tspec, NULL ) < 0 )
0090 {
0091 ctx->result = errno;
0092 }
0093 }
0094
0095 static void test_clock_nanosleep_realtime( clock_context* ctx )
0096 {
0097 if ( clock_nanosleep ( CLOCK_REALTIME, 0, &ctx->tspec, NULL ) < 0 )
0098 {
0099 ctx->result = errno;
0100 }
0101 }
0102
0103 static void test_clock_nanosleep_monotonic( clock_context* ctx )
0104 {
0105 if ( clock_nanosleep ( CLOCK_MONOTONIC, 0, &ctx->tspec, NULL ) < 0 )
0106 {
0107 ctx->result = errno;
0108 }
0109 }
0110
0111 static void test_clock_check( clock_context* ctx, const rtems_interval ticks_per_sec )
0112 {
0113 const long tick_period_nsec = 1000000000LLU / ticks_per_sec;
0114 rtems_interval ticks =
0115 (((ctx->tspec.tv_sec * 1000000000LLU) + ctx->tspec.tv_nsec) / tick_period_nsec) + 1;
0116 rtems_test_assert( ctx->result == 0 );
0117 printf(
0118 "clock: %s: sec=%" PRIdtime_t" nsec=%li ticks=%u expected-ticks=%u\n",
0119 ctx->name, ctx->tspec.tv_sec, ctx->tspec.tv_nsec, ctx->ticks, ticks);
0120 rtems_test_assert( ctx->ticks == ticks );
0121 }
0122
0123 static void task_clock( rtems_task_argument arg )
0124 {
0125 clock_context* ctx = (clock_context*) arg;
0126 rtems_interval start = rtems_clock_get_ticks_since_boot();
0127 rtems_interval end;
0128 ctx->result = 0;
0129 ctx->sleeper( ctx );
0130 end = rtems_clock_get_ticks_since_boot();
0131 ctx->ticks = end - start;
0132 ++ctx->counter;
0133 rtems_task_delete( RTEMS_SELF );
0134 }
0135
0136 static void test_start_task( clock_context* ctx )
0137 {
0138 rtems_status_code sc;
0139 sc = rtems_task_create(
0140 rtems_build_name( 'C', 'R', 'T', '0' + ctx->instance ),
0141 1,
0142 RTEMS_MINIMUM_STACK_SIZE,
0143 RTEMS_DEFAULT_MODES,
0144 RTEMS_DEFAULT_ATTRIBUTES,
0145 &ctx->tid
0146 );
0147 rtems_test_assert( sc == RTEMS_SUCCESSFUL );
0148 sc = rtems_task_start( ctx->tid, task_clock, (rtems_task_argument) ctx );
0149 rtems_test_assert( sc == RTEMS_SUCCESSFUL );
0150 }
0151
0152 static void test_settime_and_sleeping_step( int step )
0153 {
0154 const rtems_interval ticks_per_sec = rtems_clock_get_ticks_per_second();
0155 struct timespec tv;
0156
0157 clock_context ns_ctx;
0158 clock_context cnr_ctx;
0159 clock_context cnm_ctx;
0160
0161 printf( "\nClock settime while sleeping: step=%i\n", step );
0162
0163 clock_context_init(
0164 &ns_ctx, "nanosleep", 0, 0, 500000000,
0165 test_nanosleep );
0166 clock_context_init(
0167 &cnr_ctx, "clock_nanosleep(CLOCK_REALTIME)", 0, 0, 500000000,
0168 test_clock_nanosleep_realtime );
0169 clock_context_init(
0170 &cnm_ctx, "clock_nanosleep(CLOCK_MONOTONIC)", 0, 0, 500000000,
0171 test_clock_nanosleep_monotonic );
0172
0173
0174 tv.tv_sec = 946684800;
0175 tv.tv_nsec = 0;
0176 rtems_test_assert( clock_settime( CLOCK_REALTIME, &tv ) == 0 );
0177
0178 wait_ticks( 1 );
0179
0180 test_start_task( &ns_ctx );
0181 test_start_task( &cnr_ctx );
0182 test_start_task( &cnm_ctx );
0183
0184 wait_ticks( 2 );
0185
0186
0187
0188
0189 if ( step != 0 )
0190 {
0191 tv.tv_sec = 946684800 + step;
0192 tv.tv_nsec = 0;
0193 rtems_test_assert( clock_settime( CLOCK_REALTIME, &tv ) == 0 );
0194 }
0195
0196 while (true)
0197 {
0198 int counts = 0;
0199 wait_ticks( ticks_per_sec / 4 );
0200 counts += ns_ctx.counter;
0201 counts += cnr_ctx.counter;
0202 counts += cnm_ctx.counter;
0203 if (counts == 3)
0204 {
0205 break;
0206 }
0207 }
0208
0209 test_clock_check( &ns_ctx, ticks_per_sec );
0210 test_clock_check( &cnr_ctx, ticks_per_sec );
0211 test_clock_check( &cnm_ctx, ticks_per_sec );
0212 }
0213
0214 static void test_settime_and_sleeping( void )
0215 {
0216 test_settime_and_sleeping_step( 0 );
0217 test_settime_and_sleeping_step( 1 );
0218 test_settime_and_sleeping_step( -1 );
0219 }
0220
0221 typedef struct {
0222 int counter;
0223 struct timespec delta;
0224 } nanosleep_contex;
0225
0226 static void task_nanosleep( rtems_task_argument arg )
0227 {
0228 nanosleep_contex *ctx;
0229
0230 ctx = (nanosleep_contex *) arg;
0231 ++ctx->counter;
0232 nanosleep( &ctx->delta, NULL );
0233 }
0234
0235 static void test_far_future_nanosleep( void )
0236 {
0237 rtems_status_code sc;
0238 rtems_id id;
0239 nanosleep_contex ctx;
0240
0241 sc = rtems_task_create(
0242 rtems_build_name( 'N', 'A', 'N', 'O' ),
0243 1,
0244 RTEMS_MINIMUM_STACK_SIZE,
0245 RTEMS_DEFAULT_MODES,
0246 RTEMS_DEFAULT_ATTRIBUTES,
0247 &id
0248 );
0249 rtems_test_assert( sc == RTEMS_SUCCESSFUL );
0250
0251 ctx.counter = 0;
0252 ctx.delta.tv_sec = INT64_MAX;
0253 ctx.delta.tv_nsec = 999999999;
0254 sc = rtems_task_start( id, task_nanosleep, (rtems_task_argument) &ctx );
0255 rtems_test_assert( sc == RTEMS_SUCCESSFUL );
0256
0257 sc = rtems_task_wake_after( RTEMS_YIELD_PROCESSOR );
0258 rtems_test_assert( sc == RTEMS_SUCCESSFUL );
0259
0260 rtems_test_assert( ctx.counter == 1 );
0261
0262 sc = rtems_task_delete( id );
0263 rtems_test_assert( sc == RTEMS_SUCCESSFUL );
0264 }
0265
0266 static rtems_task Init(
0267 rtems_task_argument argument
0268 )
0269 {
0270 struct timespec tv;
0271 struct timespec tr;
0272 int sc;
0273 time_t seconds;
0274 time_t seconds1;
0275 unsigned int remaining;
0276 struct tm tm;
0277 struct timespec delay_request;
0278
0279 TEST_BEGIN();
0280
0281 tm_build_time( &tm, TM_FRIDAY, TM_MAY, 24, 96, 11, 5, 0 );
0282
0283
0284
0285 puts( "Init: clock_gettime - EINVAL (NULL timespec)" );
0286 errno = 0;
0287 sc = clock_gettime( CLOCK_REALTIME, NULL );
0288 rtems_test_assert( sc == -1 );
0289 rtems_test_assert( errno == EINVAL );
0290
0291 puts( "Init: clock_gettime - EINVAL (invalid clockid)" );
0292 errno = 0;
0293 sc = clock_gettime( (clockid_t)-1, &tv );
0294 rtems_test_assert( sc == -1 );
0295 rtems_test_assert( errno == EINVAL );
0296
0297 puts( "Init: clock_settime - EINVAL (invalid clockid)" );
0298 errno = 0;
0299 sc = clock_settime( (clockid_t)-1, &tv );
0300 rtems_test_assert( sc == -1 );
0301 rtems_test_assert( errno == EINVAL );
0302
0303
0304 tv.tv_sec = 1;
0305 tv.tv_nsec = 0;
0306 printf( ctime( &tv.tv_sec ) );
0307 puts( "Init: clock_settime - before 1988 EINVAL" );
0308 errno = 0;
0309 sc = clock_settime( CLOCK_REALTIME, &tv );
0310 rtems_test_assert( sc == -1 );
0311 rtems_test_assert( errno == EINVAL );
0312
0313 puts( "Init: clock_settime - invalid nanoseconds EINVAL" );
0314 tv.tv_sec = 946681200;
0315 tv.tv_nsec = 2000000000;
0316 errno = 0;
0317 sc = clock_settime( CLOCK_REALTIME, &tv );
0318 rtems_test_assert( sc == -1 );
0319 rtems_test_assert( errno == EINVAL );
0320
0321 puts( "Init: clock_settime - 2400-01-01T00:00:00.999999999Z SUCCESSFUL" );
0322 tv.tv_sec = 13569465600;
0323 tv.tv_nsec = 999999999;
0324 sc = clock_settime( CLOCK_REALTIME, &tv );
0325 rtems_test_assert( sc == 0 );
0326
0327 puts( "Init: clock_settime - 2400-01-01T00:00:01Z EINVAL" );
0328 tv.tv_sec = 13569465601;
0329 tv.tv_nsec = 0;
0330 errno = 0;
0331 sc = clock_settime( CLOCK_REALTIME, &tv );
0332 rtems_test_assert( sc == -1 );
0333 rtems_test_assert( errno == EINVAL );
0334
0335 puts( "Init: clock_settime - far future EINVAL" );
0336 tv.tv_sec = 17179869184;
0337 tv.tv_nsec = 0;
0338 errno = 0;
0339 sc = clock_settime( CLOCK_REALTIME, &tv );
0340 rtems_test_assert( sc == -1 );
0341 rtems_test_assert( errno == EINVAL );
0342
0343
0344
0345 puts( "Init: clock_getres - EINVAL (invalid clockid)" );
0346 errno = 0;
0347 sc = clock_getres( (clockid_t) -1, &tv );
0348 rtems_test_assert( sc == -1 );
0349 rtems_test_assert( errno == EINVAL );
0350
0351 puts( "Init: clock_getres - EINVAL (NULL resolution)" );
0352 errno = 0;
0353 sc = clock_getres( CLOCK_REALTIME, NULL );
0354 rtems_test_assert( sc == -1 );
0355 rtems_test_assert( errno == EINVAL );
0356
0357 puts( "Init: clock_getres - SUCCESSFUL" );
0358 sc = clock_getres( CLOCK_REALTIME, &tv );
0359 printf( "Init: resolution = sec (%" PRIdtime_t "), nsec (%ld)\n", tv.tv_sec, tv.tv_nsec );
0360 rtems_test_assert( !sc );
0361
0362
0363
0364 tv.tv_sec = mktime( &tm );
0365 rtems_test_assert( tv.tv_sec != -1 );
0366
0367 tv.tv_nsec = 0;
0368
0369
0370
0371 empty_line();
0372
0373 printf( asctime( &tm ) );
0374 puts( "Init: clock_settime - SUCCESSFUL" );
0375 sc = clock_settime( CLOCK_REALTIME, &tv );
0376 rtems_test_assert( !sc );
0377
0378 printf( asctime( &tm ) );
0379 printf( ctime( &tv.tv_sec ) );
0380
0381
0382
0383 remaining = sleep( 3 );
0384 rtems_test_assert( !remaining );
0385
0386
0387 sc = clock_gettime( CLOCK_PROCESS_CPUTIME_ID, &tv );
0388 rtems_test_assert( !sc );
0389 printf("Time since boot: (%" PRIdtime_t ", %ld)\n", tv.tv_sec,tv.tv_nsec );
0390
0391 sc = clock_gettime( CLOCK_REALTIME, &tv );
0392 rtems_test_assert( !sc );
0393
0394 printf( ctime( &tv.tv_sec ) );
0395
0396 seconds = time( NULL );
0397 printf( ctime( &seconds ) );
0398
0399
0400
0401 seconds = time( &seconds1 );
0402 rtems_test_assert( seconds == seconds1 );
0403
0404
0405
0406 printf( "Init: seconds remaining (%d)\n", (int)remaining );
0407 rtems_test_assert( !remaining );
0408
0409 test_far_future_nanosleep();
0410
0411
0412
0413 empty_line();
0414 puts( "Init: nanosleep - EINVAL (NULL time)" );
0415 sc = nanosleep ( NULL, &tr );
0416 rtems_test_assert( sc == -1 );
0417 rtems_test_assert( errno == EINVAL );
0418
0419 tv.tv_sec = 0;
0420 tv.tv_nsec = TOD_NANOSECONDS_PER_SECOND * 2;
0421 puts( "Init: nanosleep - EINVAL (too many nanoseconds)" );
0422 errno = 0;
0423 sc = nanosleep ( &tv, &tr );
0424 rtems_test_assert( sc == -1 );
0425 rtems_test_assert( errno == EINVAL );
0426
0427
0428 tv.tv_sec = -1;
0429 tv.tv_nsec = 0;
0430 puts( "Init: nanosleep - negative seconds - EINVAL" );
0431 errno = 0;
0432 sc = nanosleep ( &tv, &tr );
0433 rtems_test_assert( sc == -1 );
0434 rtems_test_assert( errno == EINVAL );
0435
0436
0437 tv.tv_sec = 0;
0438 tv.tv_nsec = -1;
0439 puts( "Init: nanosleep - negative nanoseconds - EINVAL" );
0440 errno = 0;
0441 sc = nanosleep ( &tv, &tr );
0442 rtems_test_assert( sc == -1 );
0443 rtems_test_assert( errno == EINVAL );
0444
0445
0446 tv.tv_sec = 0;
0447 tv.tv_nsec = 1;
0448 puts( "Init: nanosleep - delay so small results in one tick" );
0449 sc = nanosleep ( &tv, &tr );
0450 rtems_test_assert( !sc );
0451 rtems_test_assert( !tr.tv_sec );
0452 rtems_test_assert( !tr.tv_nsec );
0453
0454
0455
0456 tv.tv_sec = 0;
0457 tv.tv_nsec = 0;
0458
0459 puts( "Init: nanosleep - yield with remaining" );
0460 sc = nanosleep ( &tv, &tr );
0461 rtems_test_assert( !sc );
0462 rtems_test_assert( !tr.tv_sec );
0463 rtems_test_assert( !tr.tv_nsec );
0464
0465 puts( "Init: nanosleep - yield with NULL time remaining" );
0466 sc = nanosleep ( &tv, NULL );
0467 rtems_test_assert( !sc );
0468 rtems_test_assert( !tr.tv_sec );
0469 rtems_test_assert( !tr.tv_nsec );
0470
0471
0472
0473 tv.tv_sec = 3;
0474 tv.tv_nsec = 500000;
0475
0476 puts( "Init: nanosleep - 1.05 seconds" );
0477 sc = nanosleep ( &tv, &tr );
0478 rtems_test_assert( !sc );
0479
0480
0481 sc = clock_gettime( CLOCK_REALTIME, &tv );
0482 rtems_test_assert( !sc );
0483 printf( ctime( &tv.tv_sec ) );
0484
0485
0486
0487 printf( "Init: sec (%" PRIdtime_t "), nsec (%ld) remaining\n", tr.tv_sec, tr.tv_nsec );
0488 rtems_test_assert( !tr.tv_sec && !tr.tv_nsec );
0489
0490 puts( "Init: nanosleep - 1.35 seconds" );
0491 delay_request.tv_sec = 1;
0492 delay_request.tv_nsec = 35000000;
0493 sc = nanosleep( &delay_request, NULL );
0494 rtems_test_assert( !sc );
0495
0496
0497 sc = clock_gettime( CLOCK_REALTIME, &tv );
0498 rtems_test_assert( !sc );
0499 printf( ctime( &tv.tv_sec ) );
0500
0501 empty_line();
0502 puts( "clock_gettime - CLOCK_THREAD_CPUTIME_ID -- ENOSYS" );
0503 #if defined(_POSIX_THREAD_CPUTIME)
0504 {
0505 struct timespec tp;
0506 sc = clock_gettime( CLOCK_THREAD_CPUTIME_ID, &tp );
0507 check_enosys( sc );
0508 }
0509 #endif
0510
0511 puts( "clock_settime - CLOCK_PROCESS_CPUTIME_ID -- ENOSYS" );
0512 #if defined(_POSIX_CPUTIME)
0513 {
0514 struct timespec tp;
0515 sc = clock_settime( CLOCK_PROCESS_CPUTIME_ID, &tp );
0516 check_enosys( sc );
0517 }
0518 #endif
0519
0520 puts( "clock_settime - CLOCK_THREAD_CPUTIME_ID -- ENOSYS" );
0521 #if defined(_POSIX_THREAD_CPUTIME)
0522 {
0523 struct timespec tp;
0524 sc = clock_settime( CLOCK_THREAD_CPUTIME_ID, &tp );
0525 check_enosys( sc );
0526 }
0527 #endif
0528
0529 test_settime_and_sleeping( );
0530
0531 TEST_END();
0532 rtems_test_exit(0);
0533 }
0534
0535
0536
0537 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
0538 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
0539
0540 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
0541
0542 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
0543 #define CONFIGURE_MAXIMUM_TASKS 4
0544
0545 #define CONFIGURE_INIT
0546 #include <rtems/confdefs.h>